Unpack disk3.tgz
This commit is contained in:
parent
3a12151067
commit
777c904054
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
*
|
||||
* This header file defines an equivalence between several of the
|
||||
* standard level 2 I/O functions and their console I/O counterparts.
|
||||
* Use this header file for programs which perform all of these functions
|
||||
* to the console only, and need an unbuffered, direct interface to the
|
||||
* user's console. See Section 3.2.3 of the manual for more information.
|
||||
*
|
||||
**/
|
||||
#define getchar getch
|
||||
#define putchar putch
|
||||
#define gets cgets
|
||||
#define puts cputs
|
||||
#define printf cprintf
|
||||
#define scanf cscanf
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
*
|
||||
* This header file defines various ASCII character manipulation macros,
|
||||
* as follows:
|
||||
*
|
||||
* isalpha(c) non-zero if c is alpha
|
||||
* isupper(c) non-zero if c is upper case
|
||||
* islower(c) non-zero if c is lower case
|
||||
* isdigit(c) non-zero if c is a digit (0 to 9)
|
||||
* isxdigit(c) non-zero if c is a hexadecimal digit (0 to 9, A to F,
|
||||
* a to f)
|
||||
* isspace(c) non-zero if c is white space
|
||||
* ispunct(c) non-zero if c is punctuation
|
||||
* isalnum(c) non-zero if c is alpha or digit
|
||||
* isprint(c) non-zero if c is printable (including blank)
|
||||
* isgraph(c) non-zero if c is graphic (excluding blank)
|
||||
* iscntrl(c) non-zero if c is control character
|
||||
* isascii(c) non-zero if c is ASCII
|
||||
* iscsym(c) non-zero if valid character for C symbols
|
||||
* iscsymf(c) non-zero if valid first character for C symbols
|
||||
*
|
||||
**/
|
||||
|
||||
#define _U 1 /* upper case flag */
|
||||
#define _L 2 /* lower case flag */
|
||||
#define _N 4 /* number flag */
|
||||
#define _S 8 /* space flag */
|
||||
#define _P 16 /* punctuation flag */
|
||||
#define _C 32 /* control character flag */
|
||||
#define _B 64 /* blank flag */
|
||||
#define _X 128 /* hexadecimal flag */
|
||||
|
||||
extern char _ctype[]; /* character type table */
|
||||
|
||||
#define isalpha(c) (_ctype[(c)+1]&(_U|_L))
|
||||
#define isupper(c) (_ctype[(c)+1]&_U)
|
||||
#define islower(c) (_ctype[(c)+1]&_L)
|
||||
#define isdigit(c) (_ctype[(c)+1]&_N)
|
||||
#define isxdigit(c) (_ctype[(c)+1]&_X)
|
||||
#define isspace(c) (_ctype[(c)+1]&_S)
|
||||
#define ispunct(c) (_ctype[(c)+1]&_P)
|
||||
#define isalnum(c) (_ctype[(c)+1]&(_U|_L|_N))
|
||||
#define isprint(c) (_ctype[(c)+1]&(_P|_U|_L|_N|_B))
|
||||
#define isgraph(c) (_ctype[(c)+1]&(_P|_U|_L|_N))
|
||||
#define iscntrl(c) (_ctype[(c)+1]&_C)
|
||||
#define isascii(c) ((unsigned)(c)<=127)
|
||||
#define iscsym(c) (isalnum(c)||(((c)&127)==0x5f))
|
||||
#define iscsymf(c) (isalpha(c)||(((c)&127)==0x5f))
|
||||
|
||||
#define toupper(c) (islower(c)?((c)-('a'-'A')):(c))
|
||||
#define tolower(c) (isupper(c)?((c)+('a'-'A')):(c))
|
||||
#define toascii(c) ((c)&127)
|
||||
|
||||
/**
|
||||
*
|
||||
* Define NULL if it's not already defined
|
||||
*
|
||||
*/
|
||||
#ifndef NULL
|
||||
#if SPTR
|
||||
#define NULL 0 /* null pointer value */
|
||||
#else
|
||||
#define NULL 0L
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,476 @@
|
|||
/**
|
||||
*
|
||||
* This header file supplies information needed to interface with the
|
||||
* particular operating system and C compiler being used.
|
||||
*
|
||||
**/
|
||||
|
||||
/**
|
||||
*
|
||||
* Define NULL if it's not already defined
|
||||
*
|
||||
*/
|
||||
#ifndef NULL
|
||||
#if SPTR
|
||||
#define NULL 0 /* null pointer value */
|
||||
#else
|
||||
#define NULL 0L
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* The following symbols specify which operating system is being used.
|
||||
*
|
||||
* CPM Any CP/M OS
|
||||
* CPM80 CP/M for Intel 8080 or Zilog Z80
|
||||
* CPM86 CP/M for Intel 8086
|
||||
* CPM68 CP/M for Motorola 68000
|
||||
* MSDOS Microsoft's MSDOS
|
||||
*
|
||||
* Note: CPM will be set to 1 for any of the above.
|
||||
*
|
||||
* UNIX "Standard" UNIX
|
||||
* MIBS General Automation's MIBS OS
|
||||
*
|
||||
*/
|
||||
|
||||
#if CPM80
|
||||
#define CPM 1
|
||||
#endif
|
||||
#if CPM86
|
||||
#define CPM 1
|
||||
#endif
|
||||
#if CPM68
|
||||
#define CPM 1
|
||||
#endif
|
||||
#if MSDOS
|
||||
#define CPM 1
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The following definitions specify the particular C compiler being used.
|
||||
*
|
||||
* LATTICE Lattice C compiler
|
||||
*
|
||||
*/
|
||||
#define LATTICE 1
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The following type definitions take care of the particularly nasty
|
||||
* machine dependency caused by the unspecified handling of sign extension
|
||||
* in the C language. When converting "char" to "int" some compilers
|
||||
* will extend the sign, while others will not. Both are correct, and
|
||||
* the unsuspecting programmer is the loser. For situations where it
|
||||
* matters, the new type "byte" is equivalent to "unsigned char".
|
||||
*
|
||||
*/
|
||||
#if LATTICE
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Miscellaneous definitions
|
||||
*
|
||||
*/
|
||||
#define SECSIZ 128 /* disk sector size */
|
||||
#if CPM
|
||||
#define DMA (char *)0x80 /* disk buffer address */
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* The following structure is a File Control Block. Operating systems
|
||||
* with CPM-like characteristics use the FCB to store information about
|
||||
* a file while it is open.
|
||||
*
|
||||
*/
|
||||
#if CPM
|
||||
struct FCB
|
||||
{
|
||||
char fcbdrv; /* drive code */
|
||||
char fcbnam[8]; /* file name */
|
||||
char fcbext[3]; /* file name extension */
|
||||
#if MSDOS
|
||||
short fcbcb; /* current block number */
|
||||
short fcblrs; /* logical record size */
|
||||
long fcblfs; /* logical file size */
|
||||
short fcbdat; /* create/change date */
|
||||
char fcbsys[10]; /* reserved */
|
||||
char fcbcr; /* current record number */
|
||||
long fcbrec; /* random record number */
|
||||
#else
|
||||
char fcbexn; /* extent number */
|
||||
char fcbs1; /* reserved */
|
||||
char fcbs2; /* reserved */
|
||||
char fcbrc; /* record count */
|
||||
char fcbsys[16]; /* reserved */
|
||||
char fcbcr; /* current record number */
|
||||
short fcbrec; /* random record number */
|
||||
char fcbovf; /* random record overflow */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define FCBSIZ sizeof(struct FCB)
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* The following symbols define the sizes of file names and node names.
|
||||
*
|
||||
*/
|
||||
#if CPM
|
||||
#define FNSIZE 13 /* maximum file node size */
|
||||
#define FMSIZE 64 /* maximum file name size */
|
||||
#define FESIZE 4 /* maximum file extension size */
|
||||
#else
|
||||
#define FNSIZE 16 /* maximum file node size */
|
||||
#define FMSIZE 64 /* maximum file name size */
|
||||
#define FESIZE 4 /* maximum file extension size */
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The following structures define the 8086 registers that are passed to
|
||||
* various low-level operating system service functions.
|
||||
*
|
||||
*/
|
||||
#if I8086
|
||||
struct XREG
|
||||
{
|
||||
short ax,bx,cx,dx,si,di;
|
||||
};
|
||||
|
||||
struct HREG
|
||||
{
|
||||
byte al,ah,bl,bh,cl,ch,dl,dh;
|
||||
};
|
||||
|
||||
union REGS
|
||||
{
|
||||
struct XREG x;
|
||||
struct HREG h;
|
||||
};
|
||||
|
||||
struct SREGS
|
||||
{
|
||||
short es,cs,ss,ds;
|
||||
};
|
||||
|
||||
struct XREGS
|
||||
{
|
||||
short ax,bx,cx,dx,si,di,ds,es;
|
||||
};
|
||||
|
||||
union REGSS
|
||||
{
|
||||
struct XREGS x;
|
||||
struct HREG h;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The following codes are returned by the low-level operating system service
|
||||
* calls. They are usually placed into _OSERR by the OS interface functions.
|
||||
*
|
||||
*/
|
||||
#if MSDOS
|
||||
#define E_FUNC 1 /* invalid function code */
|
||||
#define E_FNF 2 /* file not found */
|
||||
#define E_PNF 3 /* path not found */
|
||||
#define E_NMH 4 /* no more file handles */
|
||||
#define E_ACC 5 /* access denied */
|
||||
#define E_IFH 6 /* invalid file handle */
|
||||
#define E_MCB 7 /* memory control block problem */
|
||||
#define E_MEM 8 /* insufficient memory */
|
||||
#define E_MBA 9 /* invalid memory block address */
|
||||
#define E_ENV 10 /* invalid environment */
|
||||
#define E_FMT 11 /* invalid format */
|
||||
#define E_IAC 12 /* invalid access code */
|
||||
#define E_DATA 13 /* invalid data */
|
||||
#define E_DRV 15 /* invalid drive code */
|
||||
#define E_RMV 16 /* remove denied */
|
||||
#define E_DEV 17 /* invalid device */
|
||||
#define E_NMF 18 /* no more files */
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* This structure contains disk size information returned by the getdfs
|
||||
* function.
|
||||
*/
|
||||
struct DISKINFO
|
||||
{
|
||||
unsigned short free; /* number of free clusters */
|
||||
unsigned short cpd; /* clusters per drive */
|
||||
unsigned short spc; /* sectors per cluster */
|
||||
unsigned short bps; /* bytes per sector */
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* The following structure is used by the dfind and dnext functions to
|
||||
* hold file information.
|
||||
*
|
||||
*/
|
||||
struct FILEINFO
|
||||
{
|
||||
char resv[21]; /* reserved */
|
||||
char attr; /* actual file attribute */
|
||||
long time; /* file time and date */
|
||||
long size; /* file size in bytes */
|
||||
char name[13]; /* file name */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The following structure appears at the beginning (low address) of
|
||||
* each free memory block.
|
||||
*
|
||||
*/
|
||||
struct MELT
|
||||
{
|
||||
struct MELT *fwd; /* points to next free block */
|
||||
#if SPTR
|
||||
unsigned size; /* number of MELTs in this block */
|
||||
#else
|
||||
long size; /* number of MELTs in this block */
|
||||
#endif
|
||||
};
|
||||
#define MELTSIZE sizeof(struct MELT)
|
||||
|
||||
/**
|
||||
*
|
||||
* The following structure is a device header. It is copied to _OSCED
|
||||
* when a critical error occurs.
|
||||
*
|
||||
*/
|
||||
struct DEV
|
||||
{
|
||||
long nextdev; /* long pointer to next device */
|
||||
short attr; /* device attributes */
|
||||
short sfunc; /* short pointer to strategy function */
|
||||
short ifunc; /* short pointer to interrupt function */
|
||||
char name[8]; /* device name */
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* The following structure contains country-dependent information returned
|
||||
* by the getcdi function.
|
||||
*
|
||||
*/
|
||||
struct CDI2 /* DOS Version 2 format */
|
||||
{
|
||||
short fdate; /* date/time format */
|
||||
/* 0 => USA (h:m:s m/d/y) */
|
||||
/* 1 => Europe (h:m:s d/m/y) */
|
||||
/* 2 => Japan (h:m:s d:m:y) */
|
||||
char curr[2]; /* currency symbol and null */
|
||||
char sthou[2]; /* thousands separator and null */
|
||||
char sdec[2]; /* decimal separator and null */
|
||||
char resv[24]; /* reserved */
|
||||
};
|
||||
|
||||
struct CDI3 /* DOS Version 3 format */
|
||||
{
|
||||
short fdate; /* date format */
|
||||
/* 0 => USA (m d y) */
|
||||
/* 1 => Europe (d m y) */
|
||||
/* 2 => Japan (d m y) */
|
||||
char curr[5]; /* currency symbol, null-terminated */
|
||||
char sthou[2]; /* thousands separator and null */
|
||||
char sdec[2]; /* decimal separator and null */
|
||||
char sdate[2]; /* date separator and null */
|
||||
char stime[2]; /* time separator and null */
|
||||
char fcurr; /* currency format */
|
||||
/* Bit 0 => 0 if symbol precedes value */
|
||||
/* => 1 if symbol follows value */
|
||||
/* Bit 1 => number of spaces between value */
|
||||
/* and symbol */
|
||||
char dcurr; /* number of decimals in currency */
|
||||
char ftime; /* time format */
|
||||
/* Bit 0 => 0 if 12-hour clock */
|
||||
/* => 1 if 24-hour clock */
|
||||
long pcase; /* far pointer to case map function */
|
||||
char sdata[2]; /* data list separator and null */
|
||||
short resv[5]; /* reserved */
|
||||
};
|
||||
|
||||
union CDI
|
||||
{
|
||||
struct CDI2 v2;
|
||||
struct CDI3 v3;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Level 0 I/O services
|
||||
*
|
||||
**/
|
||||
#ifndef NARGS
|
||||
extern void chgdta(char *);
|
||||
extern int chgfa(char *, int);
|
||||
extern int chgft(int, long);
|
||||
extern int dclose(int);
|
||||
extern int dcreat(char *, int);
|
||||
extern int dcreatx(char *, int);
|
||||
extern int dfind(struct FILEINFO *, char *, int);
|
||||
extern int dnext(struct FILEINFO *);
|
||||
extern int dopen(char *, int);
|
||||
extern unsigned dread(int, char *, unsigned);
|
||||
extern long dseek(int, long, int);
|
||||
extern int dunique(char *, int);
|
||||
extern unsigned dwrite(int, char *, unsigned);
|
||||
extern int getcd(int,char *);
|
||||
extern int getch(void);
|
||||
extern int getche(void);
|
||||
extern int getdfs(int, struct DISKINFO *);
|
||||
extern char *getdta(void);
|
||||
extern int getfa(char *);
|
||||
extern int getfc(int, int *);
|
||||
extern long getft(int);
|
||||
extern int getvfy(void);
|
||||
extern int kbhit(void);
|
||||
extern int putch(int);
|
||||
extern int rlock(int, long, long);
|
||||
extern void rstdta(void);
|
||||
extern void rstvfy(void);
|
||||
extern int runlk(int, long, long);
|
||||
extern void setvfy(void);
|
||||
extern int ungetch(int);
|
||||
#else
|
||||
extern void chgdta();
|
||||
extern int chgfa();
|
||||
extern int chgft();
|
||||
extern int dclose();
|
||||
extern int dcreat();
|
||||
extern int dcreatx();
|
||||
extern int dfind();
|
||||
extern int dnext();
|
||||
extern int dopen();
|
||||
extern unsigned dread();
|
||||
extern long dseek();
|
||||
extern int dunique();
|
||||
extern unsigned dwrite();
|
||||
extern int getcd();
|
||||
extern int getch();
|
||||
extern int getche();
|
||||
extern int getdfs();
|
||||
extern char *getdta();
|
||||
extern int getfa();
|
||||
extern int getfc();
|
||||
extern long getft();
|
||||
extern int getvfy();
|
||||
extern int kbhit();
|
||||
extern int putch();
|
||||
extern int rlock();
|
||||
extern void rstdta();
|
||||
extern void rstvfy();
|
||||
extern int runlk();
|
||||
extern void setvfy();
|
||||
extern int ungetch();
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Miscellaneous external definitions
|
||||
*
|
||||
*/
|
||||
#ifndef NARGS
|
||||
extern int chgclk(unsigned char *);
|
||||
extern int chgdsk(int);
|
||||
extern char *envpack(char **, char **);
|
||||
extern int envunpk(char *);
|
||||
#if SPTR
|
||||
extern unsigned FP_OFF(long);
|
||||
extern unsigned FP_SEG(long);
|
||||
#else
|
||||
extern unsigned FP_OFF(char *);
|
||||
extern unsigned FP_SEG(char *);
|
||||
#endif
|
||||
extern long ftpack(char *);
|
||||
extern void ftunpk(long, char *);
|
||||
extern int getbrk(void);
|
||||
extern int getcdi(int, struct CDI3 *);
|
||||
extern void getclk(unsigned char *);
|
||||
extern int getdsk(void);
|
||||
extern int getpf(char *, char *);
|
||||
extern int getpfe(char *, char *);
|
||||
extern unsigned inp(unsigned);
|
||||
extern int int86(int, union REGS *, union REGS *);
|
||||
extern int int86s(int, union REGSS *, union REGSS *);
|
||||
extern int int86x(int, union REGS *, union REGS *, struct SREGS *);
|
||||
extern int intdos(union REGS *, union REGS *);
|
||||
extern int intdoss(union REGSS *, union REGSS *);
|
||||
extern int intdosx(union REGS *, union REGS *, struct SREGS *);
|
||||
extern int isnet(void);
|
||||
extern int isnetdc(int);
|
||||
extern int isnetfh(int);
|
||||
extern int isneton(void);
|
||||
extern void makedv(char *, unsigned *, unsigned *);
|
||||
extern void makepv(int(*)(), unsigned *, unsigned *);
|
||||
extern void movedata(unsigned, unsigned, unsigned, unsigned, unsigned);
|
||||
extern int onbreak(int(*)());
|
||||
extern void onerror(int);
|
||||
extern void outp(unsigned, unsigned);
|
||||
extern void peek(unsigned, unsigned, char *, unsigned);
|
||||
extern void poke(unsigned, unsigned, char *, unsigned);
|
||||
extern int poserr(char *);
|
||||
extern void rstbrk(void);
|
||||
extern void rstdsk(void);
|
||||
extern int setcdi(int);
|
||||
extern void setbrk(void);
|
||||
#else
|
||||
extern int chgclk();
|
||||
extern int chgdsk();
|
||||
extern char *envpack();
|
||||
extern int envunpk();
|
||||
extern unsigned FP_OFF();
|
||||
extern unsigned FP_SEG();
|
||||
extern long ftpack();
|
||||
extern void ftunpk();
|
||||
extern int getbrk();
|
||||
extern int getcdi();
|
||||
extern void getclk();
|
||||
extern int getdsk();
|
||||
extern int getpf();
|
||||
extern int getpfe();
|
||||
extern unsigned inp();
|
||||
extern int int86();
|
||||
extern int int86s();
|
||||
extern int int86x();
|
||||
extern int intdos();
|
||||
extern int intdoss();
|
||||
extern int intdosx();
|
||||
extern int isnet();
|
||||
extern int isnetdc();
|
||||
extern int isnetfh();
|
||||
extern int isneton();
|
||||
extern void makedv();
|
||||
extern void makepv();
|
||||
extern void movedata();
|
||||
extern int onbreak();
|
||||
extern void onerror();
|
||||
extern void outp();
|
||||
extern void peek();
|
||||
extern void poke();
|
||||
extern int poserr();
|
||||
extern void rstbrk();
|
||||
extern void rstdsk();
|
||||
extern int setcdi();
|
||||
extern void setbrk();
|
||||
#endif
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
.XLIST
|
||||
PAGE 58,132
|
||||
;**
|
||||
;
|
||||
; This macro library defines the operating environment for the 8086 S
|
||||
; memory model, which allows 64Kbytes of data and 64Kbytes of program.
|
||||
;
|
||||
;**
|
||||
MSDOS EQU 2
|
||||
|
||||
;**
|
||||
;
|
||||
; The following symbols define the 8086 memory mode being used. Set LPROG
|
||||
; to 1 for a large program segment (greater than 64K-bytes), and set LDATA
|
||||
; to 1 for a large data segment. Set COM to 1 to generate .COM files
|
||||
; instead of .EXE files. Note that if COM is not zero, then LPROG and
|
||||
; LDATA must be 0.
|
||||
;
|
||||
;**
|
||||
COM EQU 0
|
||||
LPROG EQU 0
|
||||
LDATA EQU 0
|
||||
|
||||
;**
|
||||
;
|
||||
; The following symbols are established via LPROG and LDATA as follows:
|
||||
;
|
||||
; S8086 set for small model (small prog, small data)
|
||||
; D8086 set for model with large data, small prog
|
||||
; P8086 set for model with large prog, small data
|
||||
; L8086 set for large model
|
||||
;
|
||||
;**
|
||||
IF (LPROG EQ 0) AND (LDATA EQ 0)
|
||||
S8086 EQU 1
|
||||
D8086 EQU 0
|
||||
P8086 EQU 0
|
||||
L8086 EQU 0
|
||||
ENDIF
|
||||
|
||||
IF (LPROG EQ 0) AND (LDATA NE 0)
|
||||
S8086 EQU 0
|
||||
D8086 EQU 1
|
||||
P8086 EQU 0
|
||||
L8086 EQU 0
|
||||
ENDIF
|
||||
|
||||
IF (LPROG NE 0) AND (LDATA EQ 0)
|
||||
S8086 EQU 0
|
||||
D8086 EQU 0
|
||||
P8086 EQU 1
|
||||
L8086 EQU 0
|
||||
ENDIF
|
||||
|
||||
IF (LPROG NE 0) AND (LDATA NE 0)
|
||||
S8086 EQU 0
|
||||
D8086 EQU 0
|
||||
P8086 EQU 0
|
||||
L8086 EQU 1
|
||||
ENDIF
|
||||
|
||||
|
||||
;**
|
||||
;
|
||||
; The DSEG and PSEG macros are defined to generate the appropriate GROUP
|
||||
; and SEGMENT statements for the memory model being used. The ENDDS and
|
||||
; ENDPS macros are then used to end the segments.
|
||||
;
|
||||
;**
|
||||
DSEG MACRO
|
||||
DGROUP GROUP DATA
|
||||
DATA SEGMENT WORD PUBLIC 'DATA'
|
||||
ASSUME DS:DGROUP
|
||||
ENDM
|
||||
ENDDS MACRO
|
||||
DATA ENDS
|
||||
ENDM
|
||||
|
||||
IF S8086
|
||||
PSEG MACRO
|
||||
PGROUP GROUP PROG
|
||||
PROG SEGMENT BYTE PUBLIC 'PROG'
|
||||
ASSUME CS:PGROUP
|
||||
ENDM
|
||||
ENDPS MACRO
|
||||
PROG ENDS
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
IF D8086
|
||||
PSEG MACRO
|
||||
CGROUP GROUP CODE
|
||||
CODE SEGMENT BYTE PUBLIC 'CODE'
|
||||
ASSUME CS:CGROUP
|
||||
ENDM
|
||||
ENDPS MACRO
|
||||
CODE ENDS
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
IF P8086
|
||||
PSEG MACRO
|
||||
_CODE SEGMENT BYTE PUBLIC 'CODE'
|
||||
ASSUME CS:_CODE
|
||||
ENDM
|
||||
ENDPS MACRO
|
||||
_CODE ENDS
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
IF L8086
|
||||
PSEG MACRO
|
||||
_PROG SEGMENT BYTE PUBLIC 'PROG'
|
||||
ASSUME CS:_PROG
|
||||
ENDM
|
||||
ENDPS MACRO
|
||||
_PROG ENDS
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
;**
|
||||
;
|
||||
; The BEGIN and ENTRY macros establish appropriate function entry points
|
||||
; depending on whether NEAR or FAR program addressing is being used. The
|
||||
; only difference between the two is that BEGIN generates a PROC operation
|
||||
; to start a segment.
|
||||
;
|
||||
BEGIN MACRO NAME ; begin a function
|
||||
PUBLIC NAME
|
||||
IF LPROG
|
||||
NAME PROC FAR
|
||||
ELSE
|
||||
NAME PROC NEAR
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
ENTRY MACRO NAME
|
||||
PUBLIC NAME
|
||||
IF LPROG
|
||||
NAME LABEL FAR
|
||||
ELSE
|
||||
NAME LABEL NEAR
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
;**
|
||||
;
|
||||
; The following symbols are defined to help set up a STRUC defining the
|
||||
; stack frame:
|
||||
;
|
||||
; CPSIZE -> code pointer size (2 or 4)
|
||||
; DPSIZE -> data pointer size (2 or 4)
|
||||
;
|
||||
; These wouldn't be necessary if it were possible to use macros or even
|
||||
; conditionals within a STRUC.
|
||||
;
|
||||
IF LPROG
|
||||
CPSIZE EQU 4
|
||||
ELSE
|
||||
CPSIZE EQU 2
|
||||
ENDIF
|
||||
IF LDATA
|
||||
DPSIZE EQU 4
|
||||
ELSE
|
||||
DPSIZE EQU 2
|
||||
ENDIF
|
||||
|
||||
;
|
||||
; The SETX macro sets the symbol X to 4 if LPROG is 0 or to 6 otherwise.
|
||||
; X can then be used to skip past the BP and return address save area
|
||||
; in the stack frame when accessing the function arguments.
|
||||
;
|
||||
SETX MACRO
|
||||
IF LPROG
|
||||
X EQU 6
|
||||
ELSE
|
||||
X EQU 4
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
;
|
||||
; The PEXTRN macro defines an external pointer in the data segment.
|
||||
;
|
||||
PEXTRN MACRO NAME
|
||||
IF LDATA
|
||||
EXTRN NAME:DWORD
|
||||
ELSE
|
||||
EXTRN NAME:WORD
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
.LIST
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
dog equ 1
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
*
|
||||
* Structure to hold information about math exceptions
|
||||
*
|
||||
*/
|
||||
struct exception
|
||||
{
|
||||
int type; /* error type */
|
||||
char *name; /* math function name */
|
||||
double arg1, arg2; /* function arguments */
|
||||
double retval; /* proposed return value */
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* Exception type codes, found in exception.type
|
||||
*
|
||||
*/
|
||||
#define DOMAIN 1 /* domain error */
|
||||
#define SING 2 /* singularity */
|
||||
#define OVERFLOW 3 /* overflow */
|
||||
#define UNDERFLOW 4 /* underflow */
|
||||
#define TLOSS 5 /* total loss of significance */
|
||||
#define PLOSS 6 /* partial loss of significance */
|
||||
|
||||
/**
|
||||
*
|
||||
* Error codes generated by basic arithmetic operations (+ - * /)
|
||||
*
|
||||
*/
|
||||
#define FPEUND 1 /* underflow */
|
||||
#define FPEOVF 2 /* overflow */
|
||||
#define FPEZDV 3 /* zero divisor */
|
||||
#define FPENAN 4 /* not a number (invalid operation) */
|
||||
#define FPECOM 5 /* not comparable */
|
||||
|
||||
/**
|
||||
*
|
||||
* Constants
|
||||
*
|
||||
*/
|
||||
#define PI 3.14159265358979323846
|
||||
#define PID2 1.57079632679489661923 /* PI divided by 2 */
|
||||
#define PID4 0.78539816339744830962 /* PI divided by 4 */
|
||||
#define I_PI 0.31830988618379067154 /* Inverse of PI */
|
||||
#define I_PID2 0.63661977236758134308 /* Inverse of PID2 */
|
||||
|
||||
#define HUGE 1.797693e308 /* huge value */
|
||||
#define TINY 2.2e-308 /* tiny value */
|
||||
#define LOGHUGE 709.778 /* natural log of huge value */
|
||||
#define LOGTINY -708.396 /* natural log of tiny value */
|
||||
|
||||
/**
|
||||
*
|
||||
* External declarations
|
||||
*
|
||||
*/
|
||||
extern int _FPERR; /* floating point arithmetic error */
|
||||
extern int errno; /* UNIX error code */
|
||||
|
||||
#ifndef NARGS
|
||||
extern double acos(double);
|
||||
extern double asin(double);
|
||||
extern double atan(double);
|
||||
extern double atan2(double, double);
|
||||
extern double atof(char *);
|
||||
extern double ceil(double);
|
||||
extern double cos(double);
|
||||
extern double cosh(double);
|
||||
extern void CXFERR(int);
|
||||
extern double drand48(void);
|
||||
extern char *ecvt(double, int, int *, int *);
|
||||
extern double erand48(short *);
|
||||
extern double except(int, char *, double, double, double);
|
||||
extern double exp(double);
|
||||
extern double fabs(double);
|
||||
extern char *fcvt(double, int, int *, int *);
|
||||
extern double floor(double);
|
||||
extern double fmod(double, double);
|
||||
extern double frexp(double, int *);
|
||||
extern char *gcvt(double, int, char *);
|
||||
extern long jrand48(short *);
|
||||
extern double ldexp(double, int);
|
||||
extern void lcong48(short *);
|
||||
extern double log(double);
|
||||
extern double log10(double);
|
||||
extern long lrand48(void);
|
||||
extern int matherr(struct exception *);
|
||||
extern double modf(double, double *);
|
||||
extern long mrand48(void);
|
||||
extern long nrand48(short *);
|
||||
extern double pow(double, double);
|
||||
extern int rand(void);
|
||||
extern short *seed48(short *);
|
||||
extern double sin(double);
|
||||
extern double sinh(double);
|
||||
extern double sqrt(double);
|
||||
extern void srand(unsigned);
|
||||
extern void srand48(long);
|
||||
extern double tan(double);
|
||||
extern double tanh(double);
|
||||
|
||||
#else
|
||||
extern double acos();
|
||||
extern double asin();
|
||||
extern double atan();
|
||||
extern double atan2();
|
||||
extern double atof();
|
||||
extern double ceil();
|
||||
extern double cos();
|
||||
extern double cosh();
|
||||
extern void CXFERR();
|
||||
extern double drand48();
|
||||
extern char *ecvt();
|
||||
extern double erand48();
|
||||
extern double except();
|
||||
extern double exp();
|
||||
extern double fabs();
|
||||
extern char *fcvt();
|
||||
extern double floor();
|
||||
extern double fmod();
|
||||
extern double frexp();
|
||||
extern char *gcvt();
|
||||
extern long jrand48();
|
||||
extern void lcong48();
|
||||
extern double ldexp();
|
||||
extern double log();
|
||||
extern double log10();
|
||||
extern long lrand48();
|
||||
extern int matherr();
|
||||
extern double modf();
|
||||
extern long mrand48();
|
||||
extern long nrand48();
|
||||
extern double pow();
|
||||
extern int rand();
|
||||
extern short *seed48();
|
||||
extern double sin();
|
||||
extern double sinh();
|
||||
extern double sqrt();
|
||||
extern void srand();
|
||||
extern void srand48();
|
||||
extern double tan();
|
||||
extern double tanh();
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Macros
|
||||
*
|
||||
*/
|
||||
#define abs(x) ((x)<0?-(x):(x))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define min(a,b) ((a)<=(b)?(a):(b))
|
||||
|
||||
/**
|
||||
*
|
||||
* Define NULL if it's not already defined
|
||||
*
|
||||
*/
|
||||
#ifndef NULL
|
||||
#if SPTR
|
||||
#define NULL 0 /* null pointer value */
|
||||
#else
|
||||
#define NULL 0L
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
IFDEF REGMEM
|
||||
MIN_PAGESIZE EQU 0C00H ; Minimum page size for conventional memory
|
||||
ENDIF
|
||||
|
||||
IFDEF EXPMEM
|
||||
MIN_PAGESIZE EQU 04000h ; Minimum page size for expanded memory
|
||||
ENDIF
|
||||
|
||||
IFDEF EXTMEM
|
||||
MIN_PAGESIZE EQU 04000h ; Minimum page size for extended memory
|
||||
ENDIF
|
||||
|
||||
IFDEF PROMEM
|
||||
MIN_PAGESIZE EQU 0C00h ; Minimum page size for protected memory
|
||||
MAX_PAGESIZE EQU 07FF0h ; Maximum page size for protected memory
|
||||
ENDIF
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#ifdef REGMEM
|
||||
#define MIN_PAGESIZE 0x0C00
|
||||
#endif
|
||||
|
||||
#ifdef EXPMEM
|
||||
#define MIN_PAGESIZE 0x4000
|
||||
#endif
|
||||
|
||||
#ifdef EXTMEM
|
||||
#define MIN_PAGESIZE 0x4000
|
||||
#endif
|
||||
|
||||
#ifdef PROMEM
|
||||
#define MIN_PAGESIZE 0x0C00
|
||||
#define MAX_PAGESIZE 0x7FF0
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
;
|
||||
; A list of EQU's for the various types of PCs
|
||||
;
|
||||
UNKNOWN equ 0
|
||||
TIPC equ 1
|
||||
IBMPC equ 0ffh
|
||||
IBMXT equ 0feh
|
||||
IBMJR equ 0fdh
|
||||
IBMAT equ 0fch ;IBM PC-AT
|
||||
IBM80 equ 0f8h ;IBM PS/2 Model 80
|
||||
IBMTYPE equ 0f0h ;IBM machine types >= this value
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/* A list of DEFINES's for the various types of PCs */
|
||||
#define UNKNOWN 0
|
||||
#define TIPC 1
|
||||
#define IBMPC 0x0ff
|
||||
#define IBMXT 0x0fe
|
||||
#define IBMJR 0x0fd
|
||||
#define IBMAT 0x0fc
|
||||
#define IBM80 0xf8h ;IBM PS/2 Model 80
|
||||
#define IBMTYPE 0xf0h ;IBM machine types >= this value
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,888 @@
|
|||
; =====> PROSREAD.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* S-Expression reading *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 24 March 1986 *
|
||||
;* Last Modification: 10 Feb 1987 *
|
||||
;* *
|
||||
;* tc 2/10/87 fix to convert first *
|
||||
;* char after # to upper case *
|
||||
;* tc 2/10/87 added support to do *
|
||||
;* readline *
|
||||
;***************************************
|
||||
page 60,132
|
||||
include scheme.equ
|
||||
include sinterp.arg
|
||||
|
||||
SPACE equ 20h
|
||||
CTRL_Z equ 1Ah
|
||||
LINEFEED equ 0Ah
|
||||
RETURN equ 0Dh
|
||||
COM equ 3Bh
|
||||
BK_SLASH equ 5Ch
|
||||
BUFSIZE equ 256
|
||||
TEST_NUM equ 8
|
||||
EOFERR equ 1
|
||||
SHARPERR equ 7
|
||||
PORTERR equ -2
|
||||
HEAPERR equ -3
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
public test_ch, t_array
|
||||
extrn locases:word
|
||||
extrn hicases:word
|
||||
extrn CXFERR_s:word
|
||||
extrn port_r:word
|
||||
srd_str db "READ-ATOM",0
|
||||
sln_str db "READ-LINE",0
|
||||
inv_char db "Invalid character constant",0
|
||||
limit dw ? ; current size of atom buffer
|
||||
main_reg dw ? ; main register
|
||||
flg_eof dw ? ; whether to flag end-of-file
|
||||
atomb dw ? ; atom buffer
|
||||
test_ch db 0Ah,20h,7Fh,0Ch,09h,08h,0Dh,1Bh ; special characters
|
||||
char db 20h ; most recently received char
|
||||
t_str1 db "NEWLINE",0
|
||||
t_str2 db "SPACE",0
|
||||
t_str3 db "RUBOUT",0
|
||||
t_str4 db "PAGE",0
|
||||
t_str5 db "TAB",0
|
||||
t_str6 db "BACKSPACE",0
|
||||
t_str7 db "RETURN",0
|
||||
t_str8 db "ESCAPE",0
|
||||
t_array dw t_str1
|
||||
dw t_str2
|
||||
dw t_str3
|
||||
dw t_str4
|
||||
dw t_str5
|
||||
dw t_str6
|
||||
dw t_str7
|
||||
dw t_str8
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;;;***************************************************************************
|
||||
;;; Support for read-line
|
||||
;;;***************************************************************************
|
||||
rln_proc proc
|
||||
extrn next_SP:near
|
||||
extrn src_err:near
|
||||
|
||||
public srd_line
|
||||
srd_line: lods byte ptr ES:[SI]
|
||||
save <SI>
|
||||
add AX,offset reg0 ; compute register address
|
||||
mov main_reg,AX
|
||||
xor BX,BX
|
||||
push BX
|
||||
push AX
|
||||
C_call get_port,,Load_ES ; get the port object
|
||||
mov SP,BP ; get the return status
|
||||
test AX,AX ; error returned?
|
||||
jnz srd_lerr
|
||||
pushm <tmp_disp,tmp_page,main_reg>
|
||||
call sread_ln ; get a line
|
||||
mov SP,BP
|
||||
jmp next_SP ; return to interpreter
|
||||
;
|
||||
srd_lerr: lea BX,sln_str
|
||||
jmp src_err ; link to error handler
|
||||
rln_proc endp
|
||||
|
||||
;;;***************************************************************************
|
||||
;;; Set up for the operation of reading a single line from the given port.
|
||||
;;;***************************************************************************
|
||||
extrn setabort:near
|
||||
extrn abort:near
|
||||
extrn ssetadr:near
|
||||
srdlnarg struc
|
||||
temp_r dw ? ; temporary storage
|
||||
srdln_BP dw ? ; caller's BP
|
||||
dw ? ; caller's return address
|
||||
rp_reg dw ? ; port register
|
||||
rpg dw ? ; adjusted page number
|
||||
rdisp dw ? ; displacement
|
||||
srdlnarg ends
|
||||
;
|
||||
public sread_at
|
||||
sread_ln proc near
|
||||
push BP
|
||||
sub SP, offset srdln_BP ; allocate local storage
|
||||
mov BP,SP
|
||||
call setabort ; save stack pointer
|
||||
pushm <[BP].rdisp,[BP].rpg>
|
||||
call ssetadr ; set port address
|
||||
mov SP,BP
|
||||
test AX,AX ; check return status
|
||||
jz srdl_010
|
||||
mov AX,PORTERR ; port error
|
||||
push AX
|
||||
call abort
|
||||
;
|
||||
mov flg_eof,1 ; flag eof
|
||||
srdl_010:
|
||||
call rcvchar ; get char, eof won't return here
|
||||
cmp AL,LINEFEED ; is char linefeed?
|
||||
je srdl_010 ; if so, ignore
|
||||
|
||||
mov [BP].temp_r,AX ; save character read
|
||||
|
||||
mov AX,BUFSIZE ; Get buffer size
|
||||
mov limit,AX
|
||||
push AX
|
||||
C_call getmem ; allocate buffer
|
||||
mov SP,BP
|
||||
cmp AX,0 ; memory available?
|
||||
jne srdl_020
|
||||
;error allocate C heap space
|
||||
mov AX,HEAPERR ; no, error
|
||||
push AX
|
||||
call abortrea
|
||||
mov SP,BP
|
||||
jmp srdln_ret
|
||||
|
||||
srdl_020: mov SI,AX
|
||||
mov atomb,AX ; address of buffer
|
||||
mov flg_eof,0 ; don't flag error on EOF
|
||||
xor BX,BX ; index into buffer
|
||||
mov AX,[BP].temp_r ; restore saved character
|
||||
; read characters
|
||||
srdln_cha:
|
||||
cmp AL,RETURN ; Return character?
|
||||
je srdln_ret ; yes, return
|
||||
cmp AL,CTRL_Z ; EOF character?
|
||||
je srdln_ret ; yes, return
|
||||
cmp AL,LINEFEED ; Linefeed character?
|
||||
je srdln_ret ; yes, don't put in atomb
|
||||
|
||||
pushm <AX,BX>
|
||||
call addchar ; Add character to buffer
|
||||
mov SP,BP
|
||||
inc BX
|
||||
srdln_nxt:
|
||||
call rcvchar ; Get next character
|
||||
jmp srdln_cha ; Go get next character
|
||||
|
||||
srdln_ret:
|
||||
mov CX,STRTYPE ; Allocate string data type
|
||||
mov [BP].temp_r,BX
|
||||
pushm <BX,CX,main_reg>
|
||||
c_call alloc_bl,,Load_ES
|
||||
mov SP,BP
|
||||
mov CX,3 ; Copy buffer to Scheme string
|
||||
mov SI,atomb
|
||||
pushm <[BP].temp_r,SI,CX,main_reg>
|
||||
call toblock
|
||||
mov AX,limit ; Release buffer
|
||||
pushm <AX,atomb>
|
||||
C_call rlsmem
|
||||
mov SP,BP
|
||||
mov flg_eof,1 ; Reset flags
|
||||
mov limit,0
|
||||
add SP,offset srdln_BP ; Deallocate local storage
|
||||
pop BP
|
||||
ret ; Return
|
||||
sread_ln endp
|
||||
|
||||
;;;***************************************************************************
|
||||
;;; Support for read-atom
|
||||
;;;***************************************************************************
|
||||
rds_proc proc
|
||||
extrn next_SP:near
|
||||
extrn src_err:near
|
||||
|
||||
public srd_atom
|
||||
srd_atom: lods byte ptr ES:[SI]
|
||||
save <SI>
|
||||
add AX,offset reg0 ; compute register address
|
||||
mov main_reg,AX
|
||||
xor BX,BX
|
||||
push BX
|
||||
push AX
|
||||
C_call get_port,,Load_ES ; get the port object
|
||||
mov SP,BP ; get the return status
|
||||
test AX,AX ; error returned?
|
||||
jnz srd_err
|
||||
pushm <tmp_disp,tmp_page,main_reg>
|
||||
call sread_at ; sread_atom()
|
||||
mov SP,BP
|
||||
jmp next_SP ; return to interpreter
|
||||
;
|
||||
srd_err: lea BX,srd_str
|
||||
jmp src_err ; link to error handler
|
||||
rds_proc endp
|
||||
|
||||
;;;***************************************************************************
|
||||
;;; Set up for the operation of reading a single atom from the given port.
|
||||
;;; Special characters such as ')' are parsed as lists(!) to tell them from
|
||||
;;; ordianry atoms.
|
||||
;;;***************************************************************************
|
||||
extrn setabort:near
|
||||
extrn abort:near
|
||||
extrn ssetadr:near
|
||||
sreadarg struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's return address
|
||||
p_reg dw ? ; port register
|
||||
pg dw ? ; adjusted page number
|
||||
disp dw ? ; displacement
|
||||
sreadarg ends
|
||||
;
|
||||
public sread_at
|
||||
sread_at proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
call setabort ; save stack pointer
|
||||
mov BX,[BP].p_reg ;be certain main_reg gets set if
|
||||
;sread_at gets called directly from C
|
||||
mov main_reg,BX
|
||||
pushm <[BP].disp,[BP].pg>
|
||||
call ssetadr ; set port address
|
||||
mov SP,BP
|
||||
test AX,AX ; check return status
|
||||
jz srd_010
|
||||
mov AX,PORTERR ; port error
|
||||
push AX
|
||||
call abort
|
||||
;
|
||||
srd_010: mov flg_eof,1 ; initialization
|
||||
mov limit,0
|
||||
; skip spaces
|
||||
srd_spa: call rcvchar
|
||||
call ck_space ; check for space
|
||||
test CX,CX
|
||||
jz srd_spa ; yes, skip
|
||||
; skip comments
|
||||
srd_com: cmp AL,COM ; check for comment
|
||||
jne srd_at
|
||||
srd_c10: call rcvchar
|
||||
cmp AL,RETURN
|
||||
jne srd_c10 ; yes, ignore the whole line
|
||||
jmp srd_spa
|
||||
;
|
||||
srd_at: test AL,AL ; null character?
|
||||
jz srd_spa
|
||||
call read_ato
|
||||
pop BP
|
||||
ret
|
||||
sread_at endp
|
||||
|
||||
;;;***************************************************************************
|
||||
;;; Fetch one character from the input stream
|
||||
;;;***************************************************************************
|
||||
extrn take_ch:near
|
||||
rcvchar proc near
|
||||
pop DX ; fetch return address
|
||||
;
|
||||
push DX ; save registers
|
||||
push SI
|
||||
push DI
|
||||
push CX
|
||||
push BX
|
||||
call take_ch ; takechar()
|
||||
pop BX ; restore registers
|
||||
pop CX
|
||||
pop DI
|
||||
pop SI
|
||||
pop DX
|
||||
; Check the character
|
||||
cmp AX,256
|
||||
jge rcv_10
|
||||
cmp AL,CTRL_Z ; EOF character?
|
||||
je rcv_10 ; yes, jump
|
||||
mov char,AL
|
||||
jmp DX ; return to caller
|
||||
; EOF character is fetched
|
||||
rcv_10: cmp flg_eof,0 ; EOF flag set?
|
||||
jne rcv_20 ; yes, error
|
||||
mov AX,CTRL_Z
|
||||
mov char,AL
|
||||
jmp DX ; return to caller
|
||||
;
|
||||
rcv_20: mov AX,EOFERR
|
||||
push AX
|
||||
call abortrea ; abortread(EOFERR)
|
||||
rcvchar endp
|
||||
|
||||
;;;***************************************************************************
|
||||
;;; Read in an atom (symbol, string, number)
|
||||
;;; Store the pointer to the atom in REG.
|
||||
;;; Special characters such as ')' or ',' are read as atoms themselves.
|
||||
;;; Normal atoms will end in a whitespace or a terminating macro character;
|
||||
;;; strings end with the closing '"'.
|
||||
;;; Numbers in the requested base are interpreted as such.
|
||||
;;; On exit, the next character in the buffer is the one following the last
|
||||
;;; character of the atom.
|
||||
;;;***************************************************************************
|
||||
extrn toblock:near
|
||||
extrn cons:near
|
||||
extrn buildint:near
|
||||
extrn alloc_st:near
|
||||
extrn scannum:near
|
||||
extrn pushchar:near
|
||||
|
||||
readarg struc
|
||||
num_base dw ? ; base of number
|
||||
tmpreg dw ?
|
||||
inputch dw ? ; whether the #\ macro is in effect
|
||||
escaped dw ? ; whether an escape char is used
|
||||
inflo dq ? ; for floating point value
|
||||
bignum dw ?
|
||||
biglimit dw ?
|
||||
read_BP dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; caller's return address
|
||||
readarg ends
|
||||
;
|
||||
read_ato proc near
|
||||
push ES
|
||||
push BP
|
||||
sub SP,offset read_BP ; allocate local storage
|
||||
mov BP,SP
|
||||
xor CX,CX
|
||||
mov [BP].tmpreg,AX
|
||||
;;; cmp AL,SPACE ; check for space?
|
||||
;;; jne read_at
|
||||
;;; mov [DI].C_page,CX ; yes, form NIL and return
|
||||
;;; mov [DI].C_disp,CX
|
||||
;;; jmp read_end
|
||||
read_at: mov flg_eof,CX ; initialization
|
||||
mov [BP].inputch,CX
|
||||
mov [BP].escaped,CX
|
||||
mov CXFERR_s,CX
|
||||
mov AX,BUFSIZE
|
||||
mov limit,AX
|
||||
mov [BP].num_base,10
|
||||
push AX
|
||||
C_call getmem ; allocate memory
|
||||
mov SP,BP
|
||||
cmp AX,0 ; memory available?
|
||||
jne read_01
|
||||
memerr: mov AX,HEAPERR ; no, error
|
||||
push AX
|
||||
call abortrea
|
||||
mov SP,BP
|
||||
jmp read_ret
|
||||
read_01: mov SI,AX
|
||||
mov atomb,AX ; save the address of atom buffer
|
||||
mov DI,main_reg
|
||||
xor BX,BX
|
||||
mov AX,[BP].tmpreg
|
||||
; check for the special character first
|
||||
cmp AL,5Bh ; [
|
||||
je read_10
|
||||
cmp AL,5Dh ; ]
|
||||
je read_10
|
||||
cmp AL,7Bh ; {
|
||||
je read_10
|
||||
cmp AL,7Dh ; }
|
||||
je read_10
|
||||
cmp AL,28h ; (
|
||||
je read_10
|
||||
cmp AL,29h ; )
|
||||
je read_10
|
||||
cmp AL,27h ; '
|
||||
je read_10
|
||||
cmp AL,60h ; `
|
||||
jne read_st
|
||||
; special character case
|
||||
read_10: mov [SI],AL ; *atomb = ch
|
||||
inc BX
|
||||
jmp read_sp
|
||||
;
|
||||
read_st: cmp AL,22h ; "
|
||||
jne read_co
|
||||
; string case
|
||||
push AX
|
||||
call delimby ; get the string
|
||||
mov SP,BP
|
||||
mov [BP].tmpreg,BX ; save BX register
|
||||
mov CX,STRTYPE
|
||||
pushm <BX,CX,main_reg>
|
||||
C_call alloc_bl,,Load_ES ; allocate string object
|
||||
mov SP,BP
|
||||
mov CX,3
|
||||
mov SI,atomb
|
||||
pushm <[BP].tmpreg,SI,CX,main_reg>
|
||||
call toblock ; copy string to string object
|
||||
jmp read_bye
|
||||
;
|
||||
read_co: cmp AL,2Ch ; ,
|
||||
jne read_mac
|
||||
; comma case
|
||||
mov [SI],AL
|
||||
inc BX
|
||||
call rcvchar ; get the next character
|
||||
cmp AL,40h ; check for @
|
||||
je read_20
|
||||
cmp AL,2Eh ; check for .
|
||||
je read_20
|
||||
jmp read_nor
|
||||
read_20: mov [SI+BX],AL
|
||||
inc BX
|
||||
jmp read_sp
|
||||
;
|
||||
read_mac: cmp AL,23h ; #
|
||||
je read_25
|
||||
jmp read_sym
|
||||
; macro case
|
||||
read_25: mov flg_eof,1
|
||||
read_30: test BX,BX ; first character?
|
||||
jz read_34
|
||||
read_32: jmp read_200 ; no, jump
|
||||
;
|
||||
read_34: cmp AL,23h ; #
|
||||
jne read_32 ; no, jump
|
||||
call rcvchar ; get the next character
|
||||
call ck_space ; check for space
|
||||
test CX,CX
|
||||
jnz read_40
|
||||
read_35: mov AX,SHARPERR ; yes, error
|
||||
push AX
|
||||
call abortrea
|
||||
;
|
||||
read_40: mov byte ptr [SI+1],AL ; save the character
|
||||
push BX
|
||||
mov BX,offset locases ; address of lower-case characters
|
||||
xlat
|
||||
pop BX ; restore registers
|
||||
cmp AL,62h ; b?
|
||||
jne read_d
|
||||
mov [BP].num_base,2
|
||||
jmp read_100
|
||||
;
|
||||
read_d: cmp AL,64h ; d?
|
||||
jne read_x
|
||||
mov [BP].num_base,10
|
||||
jmp read_100
|
||||
;
|
||||
read_x: cmp AL,78h ; x?
|
||||
je read_50
|
||||
cmp AL,68h ; h?
|
||||
jne read_o
|
||||
read_50: mov [BP].num_base,16
|
||||
jmp read_100
|
||||
;
|
||||
read_o: cmp AL,6Fh ; o?
|
||||
jne read_ba
|
||||
mov [BP].num_base,8
|
||||
jmp read_100
|
||||
;
|
||||
read_ba: cmp AL,BK_SLASH ; \?
|
||||
jne read_i
|
||||
call rcvchar
|
||||
pushm <AX,BX>
|
||||
call addchar
|
||||
mov SP,BP
|
||||
inc BX
|
||||
mov [BP].inputch,1
|
||||
mov [BP].escaped,1
|
||||
jmp read_100
|
||||
;
|
||||
read_i: cmp AL,69h ; i?
|
||||
je read_100
|
||||
cmp AL,65h ; e?
|
||||
je read_100
|
||||
cmp AL,73h ; s?
|
||||
je read_100
|
||||
cmp AL,6Ch ; l?
|
||||
je read_100
|
||||
cmp AL,3Ch ; <?
|
||||
je read_60 ; yes, error
|
||||
cmp AL,29h ; )?
|
||||
jne read_70
|
||||
read_60: jmp read_35 ; yes, error
|
||||
;
|
||||
read_70: mov byte ptr [SI],23h ; default
|
||||
mov BX,offset hicases ; address of higher-case characters
|
||||
xlat
|
||||
mov byte ptr [SI+1],AL ; Change letter past # to upper case
|
||||
mov BX,2
|
||||
cmp AL,28h ; check for (
|
||||
jne read_100
|
||||
jmp read_sp ; yes, special case
|
||||
;
|
||||
read_100: call rcvchar ; get the next character
|
||||
jmp read_30
|
||||
;
|
||||
read_200: mov flg_eof,0
|
||||
; handle for symbol
|
||||
read_sym: ; default
|
||||
call ck_space ; check for space
|
||||
test CX,CX
|
||||
jz read_en ; yes, jump
|
||||
cmp AL,CTRL_Z ; eof character?
|
||||
je read_en
|
||||
cmp AL,28h ; (
|
||||
je read_en
|
||||
cmp AL,29h ; )
|
||||
je read_en
|
||||
cmp AL,27h ; '
|
||||
je read_en
|
||||
cmp AL,60h ; `
|
||||
je read_en
|
||||
cmp AL,COM ; comment?
|
||||
je read_en
|
||||
cmp AL,2Ch ; ,
|
||||
je read_en
|
||||
cmp AL,22h ; "
|
||||
je read_en
|
||||
cmp AL,5Bh ; [
|
||||
je read_en
|
||||
cmp AL,5Dh ; ]
|
||||
je read_en
|
||||
cmp AL,7Bh ; {
|
||||
je read_en
|
||||
cmp AL,7Dh ; }
|
||||
je read_en
|
||||
push BX
|
||||
mov BX,offset hicases ; address of higher-case characters
|
||||
xlat
|
||||
pop BX
|
||||
cmp AL,7Ch ; |?
|
||||
jne read_210
|
||||
mov [BP].escaped,1
|
||||
push AX
|
||||
call delimby ; read the whole symbol
|
||||
mov SP,BP
|
||||
jmp read_250
|
||||
;
|
||||
read_210: cmp AL,BK_SLASH ; \?
|
||||
jne read_220
|
||||
mov [BP].escaped,1
|
||||
mov flg_eof,1
|
||||
call rcvchar
|
||||
mov flg_eof,0
|
||||
read_220: pushm <AX,BX>
|
||||
call addchar
|
||||
mov SP,BP
|
||||
inc BX
|
||||
read_250: call rcvchar ; get the next character
|
||||
jmp read_sym
|
||||
;
|
||||
read_en: xor AL,AL ; put null at end of token
|
||||
pushm <AX,BX>
|
||||
call addchar
|
||||
mov SP,BP
|
||||
; Check for single, unescaped dot
|
||||
cmp BX,1
|
||||
jne read_num
|
||||
cmp byte ptr [SI],2Eh ; check for .
|
||||
jne read_num
|
||||
cmp [BP].escaped,1
|
||||
je read_num
|
||||
jmp read_nor
|
||||
; At this point a token has been accumulated, check for number
|
||||
read_num: mov [BP].tmpreg,BX ; save BX register
|
||||
push [BP].num_base
|
||||
push SI
|
||||
call scannum ; scan number
|
||||
mov SP,BP
|
||||
mov SI,atomb ; restore SI register
|
||||
mov BX,[BP].tmpreg ; restore BX register
|
||||
test AX,AX ; number or not?
|
||||
jnz read_n05
|
||||
jmp read_500
|
||||
read_n05: cmp [BP].escaped,1
|
||||
jne read_n07
|
||||
jmp read_500
|
||||
read_n07: cmp AX,0
|
||||
jle read_300 ; negative for floating point number
|
||||
; integer of some size
|
||||
add AX,9 ; (AX + 9) / 2
|
||||
shr AX,1 ; AX = bytes needed for integer
|
||||
mov [BP].biglimit,AX ; save for later
|
||||
push AX
|
||||
C_call getmem ; allocate memory for bignum
|
||||
mov SP,BP
|
||||
cmp AX,0 ; memory available?
|
||||
jne read_n10
|
||||
jmp memerr ; no, error
|
||||
read_n10: mov BX,AX
|
||||
mov [BP].bignum,AX
|
||||
mov byte ptr [BX+3],0
|
||||
mov byte ptr [BX+4],0
|
||||
pushm <[BP].num_base, atomb, BX>
|
||||
call buildint ; form integer
|
||||
mov SP,BP
|
||||
mov DI,main_reg
|
||||
mov BX,[BP].bignum
|
||||
pushm <BX,DI>
|
||||
C_call alloc_in,,Load_ES ; alloc_int
|
||||
mov SP,BP
|
||||
pushm <[BP].biglimit,[BP].bignum>
|
||||
C_call rlsmem ; release memory for bignum
|
||||
mov SP,BP
|
||||
jmp read_rls
|
||||
; Floating point number
|
||||
read_300: lea DX,[BP].inflo
|
||||
pushm <[BP].num_base, DX, SI>
|
||||
C_call scanflo,,Load_ES ; scan the flonum
|
||||
mov SP,BP
|
||||
mov DI,main_reg
|
||||
lea BX,[BP].inflo
|
||||
pushm <[BX+6],[BX+4],[BX+2],[BX]> ; push flonum value
|
||||
push DI
|
||||
C_call alloc_fl,,Load_ES ; alloc_flonum
|
||||
mov SP,BP
|
||||
jmp read_rls
|
||||
; Allocate character or interned symbol
|
||||
read_500: cmp [BP].inputch,0 ; #\ macro?
|
||||
mov DI,main_reg
|
||||
jne read_510
|
||||
jmp read_600 ; no, symbol
|
||||
read_510: mov [DI].C_page,SPECCHAR*2
|
||||
cmp BX,1 ; only one character?
|
||||
jne read_mul ; no, jump
|
||||
xor AH,AH
|
||||
mov AL,byte ptr [SI]
|
||||
mov [DI].C_disp,AX ; return the character
|
||||
jmp read_rls
|
||||
; Check for a multichar character constant
|
||||
read_mul: mov AL,byte ptr [SI]
|
||||
mov BX,offset hicases ; address of higher-case characters
|
||||
xlat
|
||||
mov byte ptr [SI],AL
|
||||
xor BX,BX
|
||||
read_515: cmp BL,TEST_NUM ; finish the comparison?
|
||||
je read_580 ; yes, jump
|
||||
lea DI,t_array ; save BX register
|
||||
mov CX,BX
|
||||
shl BX,1 ; get the word offset
|
||||
mov DI,word ptr [DI+BX] ; address of special string
|
||||
xor BX,BX
|
||||
read_520: mov AL,byte ptr [DI+BX] ; get the character in string
|
||||
cmp AL,0 ; end of string
|
||||
je read_530 ; match
|
||||
cmp byte ptr [SI+BX],AL
|
||||
jne read_540
|
||||
inc BX
|
||||
jmp read_520
|
||||
read_530: mov BX,CX
|
||||
lea SI,test_ch ; address of special characters
|
||||
mov AL,byte ptr [SI+BX]
|
||||
mov DI,main_reg
|
||||
mov [DI].C_disp,AX ; return the special character
|
||||
jmp read_rls
|
||||
;
|
||||
read_540: mov BX,CX
|
||||
inc BX
|
||||
jmp read_515
|
||||
; For the unrecognized multi-char character constant, return #\?
|
||||
read_580: mov DI,main_reg
|
||||
mov [DI].C_disp,3Fh ; return '?' character
|
||||
;;; push SI
|
||||
;;; lea BX,tmp_reg
|
||||
;;; push BX
|
||||
;;; C_call alloc_st,,Load_ES ; alloc_string for error message
|
||||
;;; mov SP,BP
|
||||
;;; lea BX,tmp_reg
|
||||
;;; push BX
|
||||
;;; lea BX,inv_char
|
||||
;;; push BX
|
||||
;;; xor BX,BX
|
||||
;;; push BX
|
||||
;;; C_call set_erro,,Load_ES ; set_error
|
||||
;;; mov SP,BP
|
||||
mov CXFERR_s,-1 ; error status
|
||||
jmp read_rls
|
||||
; Not a character, but a symbol
|
||||
read_600: push BX ; length of symbol
|
||||
push SI ; address of symbol
|
||||
push DI ; register
|
||||
C_call intern,,Load_ES ; intern the symbol
|
||||
mov SP,BP
|
||||
jmp read_rls
|
||||
;
|
||||
read_sp: pushm <BX, SI, DI>
|
||||
C_call intern,,Load_ES ; intern the symbol
|
||||
mov SP,BP
|
||||
lea BX,nil_reg
|
||||
mov DI,main_reg
|
||||
pushm <BX, DI, DI>
|
||||
call cons ; encase in a list
|
||||
mov SP,BP
|
||||
jmp read_bye
|
||||
;
|
||||
read_nor: pushm <BX, SI, DI>
|
||||
C_call intern,,Load_ES ; intern the symbol
|
||||
mov SP,BP
|
||||
lea BX,nil_reg
|
||||
mov DI,main_reg
|
||||
pushm <BX, DI, DI>
|
||||
call cons ; encase in a list
|
||||
mov SP,BP
|
||||
read_rls: cmp char,CTRL_Z ; EOF character?
|
||||
je read_bye
|
||||
call pushchar ; put post-atom char back to buffer
|
||||
;
|
||||
read_bye: mov AX,limit
|
||||
pushm <AX, atomb>
|
||||
C_call rlsmem ; release memory
|
||||
mov SP,BP
|
||||
mov flg_eof,1 ; reset flags
|
||||
mov limit,0
|
||||
;
|
||||
read_end: mov AX,CXFERR_s ; return status
|
||||
read_ret: add SP,offset read_BP ; release local storage
|
||||
pop BP
|
||||
pop ES
|
||||
ret
|
||||
read_ato endp
|
||||
|
||||
;;;************************************************************************
|
||||
;;; DELIMBY(c)
|
||||
;;; DELIMBY takes characters from the input stream and places them
|
||||
;;; in the buffer ATOMB, starting at offset stored in BX register, and
|
||||
;;; ending when the delimiting character C is reached.
|
||||
;;; Note: SI = address of atomb
|
||||
;;; BX = number of characters in atomb
|
||||
;;;************************************************************************
|
||||
deliarg struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's return address
|
||||
cha dw ? ; character
|
||||
deliarg ends
|
||||
|
||||
delimby proc near
|
||||
push BP ; get the return address
|
||||
mov BP,SP
|
||||
mov flg_eof,1 ; signal the EOF error
|
||||
call rcvchar
|
||||
deli_10: mov CX,[BP].cha
|
||||
cmp AL,CL ; reach the end?
|
||||
je deli_50 ; yes, return
|
||||
cmp AL,RETURN ; carriage return?
|
||||
je deli_40 ; yes, ignore
|
||||
cmp AL,BK_SLASH ; check for \
|
||||
jne deli_30
|
||||
call rcvchar ; yes, ignore
|
||||
deli_30: pushm <AX,BX>
|
||||
call addchar
|
||||
mov SP,BP
|
||||
inc BX
|
||||
deli_40: call rcvchar ; get the next character
|
||||
jmp deli_10
|
||||
deli_50: mov flg_eof,0
|
||||
pop BP
|
||||
ret
|
||||
delimby endp
|
||||
|
||||
;;;************************************************************************
|
||||
;;; ADDCHAR (i, c)
|
||||
;;; ADDCHAR takes the character c and places it in the dynamic
|
||||
;;; atom buffer atomb, at offset i. If the buffer can not contain
|
||||
;;; any more characters, additional space is allocated, and limit
|
||||
;;; is adjusted accordingly.
|
||||
;;;************************************************************************
|
||||
addarg struc
|
||||
add_tmp dw ?
|
||||
add_BP dw ? ; caller's BP
|
||||
dw ? ; caller's return address
|
||||
index dw ?
|
||||
chara dw ?
|
||||
addarg ends
|
||||
|
||||
addchar proc near
|
||||
push BP
|
||||
sub SP,offset add_BP ; allocate local storage
|
||||
mov BP,SP
|
||||
mov BX,[BP].index
|
||||
cmp BX,limit ; room for character?
|
||||
jge add_10 ; no, jump
|
||||
add_01: mov AX,[BP].chara
|
||||
mov byte ptr [SI+BX],AL
|
||||
add_ret: add SP,offset add_BP
|
||||
pop BP
|
||||
ret
|
||||
add_10: mov AX,limit
|
||||
add AX,BUFSIZE
|
||||
push AX
|
||||
C_call getmem ; allocate memory
|
||||
mov SP,BP
|
||||
cmp AX,0 ; memory available?
|
||||
jne add_20
|
||||
mov AX,HEAPERR ; no, error
|
||||
push AX
|
||||
call abortrea
|
||||
mov SP,BP
|
||||
jmp add_ret
|
||||
add_20: mov DI,AX ; address of new buffer
|
||||
mov SI,atomb
|
||||
mov CX,limit
|
||||
rep movsb ; copy characters
|
||||
mov [BP].add_tmp,AX ; save buffer pointer
|
||||
pushm <limit, atomb>
|
||||
C_call rlsmem ; discard the old buffer
|
||||
mov SP,BP
|
||||
mov SI,[BP].add_tmp
|
||||
mov atomb,SI
|
||||
mov CX,limit
|
||||
add CX,BUFSIZE ; increase the limit
|
||||
mov limit,CX
|
||||
mov BX,[BP].index
|
||||
jmp add_01
|
||||
addchar endp
|
||||
|
||||
;;;************************************************************************
|
||||
;;; ABORTREAD(code)
|
||||
;;; Cancels the entire read operation via ABORT, after
|
||||
;;; resetting some vital registers.
|
||||
;;; Note: DI = address of main register
|
||||
;;;************************************************************************
|
||||
abortarg struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's return address
|
||||
errcode dw ? ; error code
|
||||
abortarg ends
|
||||
|
||||
abortrea proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov DI,main_reg ; main register
|
||||
cmp [BP].errcode,EOFERR ; EOF error?
|
||||
jne ab_010
|
||||
mov [DI].C_page,EOF_PAGE*2 ; return eof indicator
|
||||
mov [DI].C_disp,EOF_DISP
|
||||
jmp ab_020
|
||||
;
|
||||
ab_010: xor AX,AX
|
||||
mov [DI].C_page,AX ; NUL main register
|
||||
mov [DI].C_disp,AX
|
||||
;
|
||||
ab_020: push [BP].errcode
|
||||
call abort
|
||||
pop BP
|
||||
ret
|
||||
abortrea endp
|
||||
|
||||
;;;**********************************************************************
|
||||
;;; Local support to check the character in AX is space or not
|
||||
;;; Note: CX = 0 iff the character is whitespace
|
||||
;;;**********************************************************************
|
||||
ck_space proc near
|
||||
pop DX ; get the return address
|
||||
xor CX,CX
|
||||
cmp AL,SPACE ; space?
|
||||
je is
|
||||
cmp AL,9
|
||||
jb isnot
|
||||
cmp AL,0Dh
|
||||
jbe is
|
||||
isnot: inc CX
|
||||
is: jmp DX ; return to caller
|
||||
ck_space endp
|
||||
prog ends
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,548 @@
|
|||
; =====> PROWIN.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* Window I/O support *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 24 March 1986 *
|
||||
;* Last Modification: 24 March 1986 *
|
||||
;* 7 Jan 1987 - dbs *
|
||||
;* added random I/O *
|
||||
;***************************************
|
||||
page 60,132
|
||||
include scheme.equ
|
||||
include sinterp.arg
|
||||
include screen.equ
|
||||
|
||||
BUFFSIZE equ 256 ; input/output buffer
|
||||
WINDSIZE equ 32-BLK_OVHD
|
||||
PORTATTR equ 62
|
||||
LABEL equ 32+BUFFSIZE ; window label field
|
||||
P_FLAGS equ 6
|
||||
W_FLAGS equ 26
|
||||
WINDOW equ 4
|
||||
B_ATTR equ 22
|
||||
T_ATTR equ 24
|
||||
CUR_LINE equ 10
|
||||
CUR_COL equ 12
|
||||
UL_LINE equ 14
|
||||
UL_COL equ 16
|
||||
N_LINES equ 18
|
||||
N_COLS equ 20
|
||||
NUM_FLDS equ 12
|
||||
CHUNK equ 14
|
||||
STR_PTR equ 3
|
||||
OPEN equ 8
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
extrn port_pg:word,port_ds:word
|
||||
public MAX_ROWS,MAX_COLS
|
||||
|
||||
bad_port db "[VM INTERNAL ERROR] Bad port for window output",CR,LF,0
|
||||
mk_win_st db "%MAKE_WINDOW",0
|
||||
sv_win_st db "WINDOW-SAVE-CONTENTS",0
|
||||
rt_win_st db "WINDOW-RESTORE-CONTENTS",0
|
||||
gt_win_st db "%REIFY-PORT",0
|
||||
cl_win_st db "WINDOW_CLEAR",0
|
||||
|
||||
defaults dw 0,0,0,0 ; default values of window object
|
||||
max_rows db DEFAULT_NUM_ROWS,0
|
||||
max_cols db DEFAULT_NUM_COLS,0
|
||||
dw -1,15,1,0,0
|
||||
|
||||
wnlines dw 0 ; number of lines
|
||||
wncols dw 0 ; number of columns
|
||||
wulline dw 0 ; upper-left line number
|
||||
wulcol dw 0 ; upper-left column number
|
||||
branchtab dw setw_20 ; [0] : cursor line
|
||||
dw setw_20 ; [1] : cursor column
|
||||
dw setw_30 ; [2] : upper left corner line
|
||||
dw setw_40 ; [3] : upper left corner column
|
||||
dw setw_50 ; [4] : number of lines
|
||||
dw setw_60 ; [5] : number of columns
|
||||
dw setw_100 ; [6] : border attribute
|
||||
dw setw_100 ; [7] : text attribute
|
||||
dw setw_100 ; [8] : flags
|
||||
dw setw_100 ; [9] : buffer position
|
||||
dw setw_100 ; [10] : buffer end
|
||||
dw setw_100 ; [11] : port flag
|
||||
dw setw_70 ; [12] : # of chunks
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
extrn rest_scr:near
|
||||
extrn save_scr:near
|
||||
|
||||
win_proc proc near
|
||||
;;;************************************************************************
|
||||
;;; Allocate a window object
|
||||
;;;************************************************************************
|
||||
extrn zero_blk:near
|
||||
extrn next_SP:near
|
||||
extrn src_err:near
|
||||
extrn adj4bord:near
|
||||
public make_win
|
||||
make_win: lods byte ptr ES:[SI] ; load the operand register
|
||||
save <SI>
|
||||
add AX,offset reg0 ; compute register address
|
||||
mov BX,AX
|
||||
mov SI,[BX].C_disp ; get displacement
|
||||
mov BX,[BX].C_page ; get page number
|
||||
mov tmp_disp,SI ; save window label pointer
|
||||
mov tmp_page,BX
|
||||
cmp byte ptr ptype+[BX],STRTYPE*2 ; check string type
|
||||
jne make_err
|
||||
jmp short make_020
|
||||
|
||||
make_err: test BX,BX
|
||||
jz make_020 ; null window label
|
||||
lea BX,mk_win_st ; load address of text
|
||||
jmp src_err ; display error message
|
||||
|
||||
make_020: mov BX,BUFFSIZE+WINDSIZE ; get object length
|
||||
mov CX,PORTTYPE ; port type
|
||||
pushm <BX,CX,AX>
|
||||
C_call alloc_bl,,Load_ES ; allocate block for window object
|
||||
pop BX
|
||||
mov DI,[BX].C_disp ; get displacement
|
||||
save <DI>
|
||||
mov BX,[BX].C_page ; get page numbe of window object
|
||||
LoadPage ES,BX ; get page address
|
||||
shr BX,1
|
||||
pushm <DI, BX>
|
||||
call zero_blk ; zero window object
|
||||
restore <DI>
|
||||
mov word ptr ES:[DI+6],PORTATTR ; store port attribute
|
||||
mov AX,DI
|
||||
add DI,10 ; position to move default values
|
||||
lea SI,defaults ; address of default values
|
||||
mov CX,NUM_FLDS-1 ; length of defaults
|
||||
rep movsw ; move defaults into object
|
||||
mov DI,AX
|
||||
mov AX,tmp_page
|
||||
mov BX,tmp_disp
|
||||
mov byte ptr ES:[DI+STR_PTR],AL ; store window label pointer
|
||||
mov word ptr ES:[DI+STR_PTR+1],BX
|
||||
jmp next_SP
|
||||
;;;************************************************************************
|
||||
;;; Get Window Attributes
|
||||
;;; Get Window Attributes was translated from C. The following C comments
|
||||
;;; show the mappings of the arguments to get-window-attributes to their
|
||||
;;; actual locations within the port object.
|
||||
;;;
|
||||
;;;
|
||||
;;;#define NUM_FIELDS 12
|
||||
;;;static int defaults[NUM_FIELDS] = {0, /* cursor line number */
|
||||
;;; 0, /* cursor column number */
|
||||
;;; 0, /* upper left corner line number */
|
||||
;;; 0, /* upper left corner column number */
|
||||
;;; 25, /* number of lines */
|
||||
;;; 80, /* number of columns */
|
||||
;;; -1, /* no border */
|
||||
;;; 15, /* text high intensity, enable */
|
||||
;;; 1, /* wrap enabled */
|
||||
;;; 0, /* current buffer position */
|
||||
;;; 0, /* current buffer end */
|
||||
;;;TRANSCRIPT+BINARY+WINDOW+OPEN+READ_WRITE}; /* port attributes */
|
||||
;;;static int map_attr[NUM_FIELDS] = {10,12,14,16,18,20,22,24,26,28,30,6};
|
||||
;;;
|
||||
;;;************************************************************************
|
||||
public get_wind
|
||||
get_wind: lods word ptr ES:[SI] ; load register operand
|
||||
save <SI> ; save the location pointer
|
||||
xor BX,BX
|
||||
mov BL,AH
|
||||
add BX,offset reg0 ; compute address of register
|
||||
xor AH,AH
|
||||
add AX,offset reg0
|
||||
save <AX> ; save registers
|
||||
save <BX>
|
||||
mov CX,1
|
||||
pushm <CX, AX>
|
||||
C_call get_port,,Load_ES ; get the port object
|
||||
mov SP,BP
|
||||
mov SI,tmp_page
|
||||
cmp byte ptr ptype+[SI],PORTTYPE*2
|
||||
jne get_err
|
||||
restore <BX>
|
||||
cmp [BX].C_page,SPECFIX*2
|
||||
jne get_err
|
||||
mov BX,word ptr [BX].C_disp ; get the value
|
||||
shl BX,1
|
||||
sar BX,1
|
||||
cmp BX,0
|
||||
jl get_err
|
||||
cmp BX,NUM_FLDS
|
||||
jg get_err ; used to be jge - dbs
|
||||
LoadPage ES,SI ; get page address
|
||||
mov SI,tmp_disp
|
||||
restore <AX>
|
||||
mov DI,AX
|
||||
mov word ptr [DI].C_page,SPECFIX*2
|
||||
cmp BX,12
|
||||
jne get_05
|
||||
mov AX,word ptr ES:[SI+CHUNK]; get chunk number
|
||||
jmp get_20
|
||||
get_05: cmp BX,11
|
||||
jne get_10
|
||||
mov AX,word ptr ES:[SI+6]
|
||||
jmp get_20
|
||||
get_10: shl BX,1 ; get the word offset
|
||||
mov AX,word ptr ES:[SI+10+BX]
|
||||
get_20:
|
||||
test word ptr ES:[SI+P_FLAGS],WINDOW ; Port a window?
|
||||
jz get_25 ; No, jump
|
||||
and AX,07FFFh ; Yes, return integer
|
||||
mov word ptr [DI].C_disp,AX
|
||||
jmp next_SP ; Return to interpreter
|
||||
get_25:
|
||||
xor BX,BX
|
||||
push BX ; push long integer value
|
||||
push AX
|
||||
push DI ; register to store value
|
||||
C_call long2int,,Load_ES ; convert to scheme integer
|
||||
mov SP,BP
|
||||
jmp next_SP
|
||||
get_err: lea BX,gt_win_st
|
||||
jmp src_err ; link to error handler
|
||||
;;;************************************************************************
|
||||
;;; Modify Transcript File Status
|
||||
;;;************************************************************************
|
||||
public trns_chg
|
||||
trns_chg: lods byte ptr ES:[SI] ; load register operand
|
||||
save <SI>
|
||||
add AX,offset reg0 ; compute address of register
|
||||
mov BX,AX
|
||||
mov SI,[BX].C_disp
|
||||
mov BX,[BX].C_page
|
||||
cmp byte ptr ptype+[BX],PORTTYPE*2 ; check type
|
||||
jne trns_10
|
||||
LoadPage ES,BX ; get page address
|
||||
mov AX,word ptr ES:[SI+P_FLAGS]
|
||||
mov CX,AX
|
||||
and AX,OPEN ; open?
|
||||
jz trns_10
|
||||
and CX,3 ; read and write?
|
||||
jz trns_10
|
||||
mov TRNS_pag,BX
|
||||
mov TRNS_dis,SI
|
||||
jmp next_SP
|
||||
trns_10: xor AX,AX
|
||||
mov TRNS_pag,AX
|
||||
mov TRNS_dis,AX
|
||||
jmp next_SP
|
||||
;;;************************************************************************
|
||||
;;; Save Window Contents
|
||||
;;;************************************************************************
|
||||
public save_win
|
||||
save_win: lods byte ptr ES:[SI] ; load register operand
|
||||
save <SI>
|
||||
add AX,offset reg0 ; compute address of register
|
||||
xor BX,BX
|
||||
pushm <BX, AX>
|
||||
save <AX>
|
||||
C_call get_port,,Load_ES ; get port object
|
||||
mov SP,BP
|
||||
mov BX,tmp_page
|
||||
cmp byte ptr ptype+[BX],PORTTYPE*2 ; check port type
|
||||
je save_01
|
||||
save_err: lea BX,sv_win_st
|
||||
jmp src_err ; link to error handler
|
||||
save_01: LoadPage ES,BX ; get page address
|
||||
mov DI,tmp_disp
|
||||
mov AX,word ptr ES:[DI+P_FLAGS]
|
||||
and AX,WINDOW ; window object?
|
||||
jz save_err
|
||||
mov AX,word ptr ES:[DI+UL_LINE]
|
||||
mov BX,word ptr ES:[DI+UL_COL]
|
||||
mov CX,word ptr ES:[DI+N_LINES]
|
||||
mov DX,word ptr ES:[DI+N_COLS]
|
||||
mov wulline,AX
|
||||
mov wulcol,BX
|
||||
mov wnlines,CX
|
||||
mov wncols,DX
|
||||
mov AX,word ptr ES:[DI+B_ATTR] ; border attribute
|
||||
cmp AX,-1 ; bordered?
|
||||
je save_10 ; no, jump
|
||||
lea AX,wulline
|
||||
lea BX,wulcol
|
||||
lea CX,wnlines
|
||||
lea DX,wncols
|
||||
pushm <DX, BX, CX, AX>
|
||||
call adj4bord ; adjust window region
|
||||
save_10: mov AX,wnlines
|
||||
mov BX,wncols
|
||||
; compute the length of string to save window contents
|
||||
mul BL
|
||||
shl AX,1 ; * 2
|
||||
add AX,2 ; + 2
|
||||
push AX
|
||||
restore <AX>
|
||||
mov CX,STRTYPE ; string type
|
||||
pushm <CX, AX>
|
||||
C_call alloc_bl,,Load_ES ; alloc_block
|
||||
mov SP,BP
|
||||
pushm <wncols,wnlines,wulcol,wulline>
|
||||
restore <AX>
|
||||
push AX
|
||||
call save_scr ; save screen
|
||||
jmp next_SP ; return to interpreter
|
||||
;;;************************************************************************
|
||||
;;; Restore Window Contents
|
||||
;;;************************************************************************
|
||||
public rest_win
|
||||
rest_win: lods word ptr ES:[SI] ; load register operand
|
||||
save <SI> ; save the location pointer
|
||||
xor BX,BX
|
||||
mov BL,AH
|
||||
add BX,offset reg0 ; compute address of register
|
||||
xor AH,AH
|
||||
add AX,offset reg0
|
||||
save <BX>
|
||||
xor CX,CX
|
||||
pushm <CX, AX>
|
||||
C_call get_port,,Load_ES ; get the port object
|
||||
mov SP,BP
|
||||
restore <BX> ; BX = data to be restored
|
||||
mov SI,[BX].C_page
|
||||
cmp byte ptr ptype+[SI],STRTYPE*2 ; check type
|
||||
jne rest_err
|
||||
mov DI,tmp_page
|
||||
cmp byte ptr ptype+[DI],PORTTYPE*2 ; check type
|
||||
jne rest_err
|
||||
LoadPage ES,DI ; get page address
|
||||
mov DI,tmp_disp
|
||||
mov AX,word ptr ES:[DI+P_FLAGS]
|
||||
and AX,WINDOW ; window object?
|
||||
jz rest_err
|
||||
mov AX,word ptr ES:[DI+UL_LINE]
|
||||
mov BX,word ptr ES:[DI+UL_COL]
|
||||
mov CX,word ptr ES:[DI+N_LINES]
|
||||
mov DX,word ptr ES:[DI+N_COLS]
|
||||
mov wulline,AX
|
||||
mov wulcol,BX
|
||||
mov wnlines,CX
|
||||
mov wncols,DX
|
||||
mov AX,word ptr ES:[DI+B_ATTR] ; border attribute
|
||||
cmp AX,-1
|
||||
je rest_10
|
||||
lea AX,wulline
|
||||
lea BX,wulcol
|
||||
lea CX,wnlines
|
||||
lea DX,wncols
|
||||
pushm <DX, BX, CX, AX>
|
||||
call adj4bord ; adjust window region
|
||||
rest_10: pushm <wncols, wnlines, wulcol, wulline>
|
||||
restore <BX>
|
||||
push BX
|
||||
call rest_scr ; restore screen
|
||||
jmp next_SP ; return to interpreter
|
||||
rest_err: lea BX,rt_win_st
|
||||
jmp src_err ; link to error handler
|
||||
win_proc endp
|
||||
;;;************************************************************************
|
||||
;;; Set Window Attribute
|
||||
;;;************************************************************************
|
||||
setw_arg struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; caller's return address
|
||||
setw_reg dw ?
|
||||
setw_att dw ?
|
||||
setw_val dw ?
|
||||
setw_arg ends
|
||||
public set_wind
|
||||
set_wind proc near
|
||||
push ES
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov AX,1
|
||||
pushm <AX, [BP].setw_reg>
|
||||
C_call get_port,,Load_ES ; get port address
|
||||
mov SP,BP
|
||||
mov BX,tmp_page
|
||||
cmp byte ptr ptype+[BX],PORTTYPE*2 ; check type
|
||||
jne setw_err
|
||||
mov SI,[BP].setw_att
|
||||
cmp word ptr [SI].C_page,SPECFIX*2 ; check attribute type
|
||||
jne setw_err
|
||||
mov AX,[SI].C_disp ; get attribute value
|
||||
shl AX,1
|
||||
sar AX,1
|
||||
cmp AX,0 ; check attribute value
|
||||
jl setw_err
|
||||
cmp AX,NUM_FLDS
|
||||
jge setw_err
|
||||
mov SI,[BP].setw_val ; get the value pointer
|
||||
cmp word ptr [SI].C_page,SPECFIX*2 ; check type
|
||||
je setw_10
|
||||
setw_err: lea BX,gt_win_st ; address of error message
|
||||
pushm <[BP].setw_val, [BP].setw_att, [BP].setw_reg>
|
||||
mov AX,3
|
||||
pushm <AX, BX>
|
||||
C_call set_src_,,Load_ES ; set_src_err
|
||||
mov SP,BP
|
||||
mov AX,-1 ; return error status
|
||||
jmp setw_ret
|
||||
setw_10: mov CX,[SI].C_disp ; get the value
|
||||
shl CX,1
|
||||
sar CX,1
|
||||
LoadPage ES,BX ; get page address of port
|
||||
mov SI,tmp_disp ; displacement of port object
|
||||
mov BX,AX
|
||||
shl BX,1 ; get the word offset
|
||||
jmp branchtab+[BX]
|
||||
; cursor line/cursor column
|
||||
setw_20: cmp CX,0
|
||||
jl setw_err ; negative value, error
|
||||
jmp setw_100
|
||||
; upper left hand corner line number
|
||||
setw_30: xor AX,AX
|
||||
xor DH,DH
|
||||
mov DL,MAX_ROWS
|
||||
dec DX ; MAX_ROWS - 1
|
||||
call fit_in_r
|
||||
mov AX,word ptr ES:[SI+N_LINES]
|
||||
inc DX
|
||||
sub DX,CX ; MAX_ROWS - value
|
||||
cmp AX,DX
|
||||
jle setw_35
|
||||
mov word ptr ES:[SI+N_LINES],DX
|
||||
setw_35: jmp setw_100
|
||||
; upper left hand corner column number
|
||||
setw_40: xor AX,AX
|
||||
xor DH,DH
|
||||
mov DL,MAX_COLS
|
||||
dec DX ; MAX_COLUMNS - 1
|
||||
call fit_in_r
|
||||
mov AX,word ptr ES:[SI+N_COLS]
|
||||
inc DX
|
||||
sub DX,CX ; MAX_COLUMNS - value
|
||||
cmp AX,DX
|
||||
jle setw_35
|
||||
mov word ptr ES:[SI+N_COLS],DX
|
||||
jmp setw_35
|
||||
; number of lines
|
||||
setw_50: mov AX,word ptr ES:[SI+UL_LINE]
|
||||
xor DH,DH
|
||||
mov DL,MAX_ROWS
|
||||
sub DX,AX ; MAX_ROWS - UL_LINE
|
||||
mov AX,1
|
||||
call fit_in_r
|
||||
jmp setw_100
|
||||
; number of columns
|
||||
setw_60: mov AX,word ptr ES:[SI+P_FLAGS]
|
||||
and AX,WINDOW ; window?
|
||||
jz setw_100 ; no, jump
|
||||
mov AX,word ptr ES:[SI+UL_COL]
|
||||
xor DH,DH
|
||||
mov DL,MAX_COLS
|
||||
sub DX,AX ; MAX_COLUMNS - UL_COL
|
||||
mov AX,1
|
||||
call fit_in_r
|
||||
jmp setw_100
|
||||
; chunk#
|
||||
setw_70: mov BX,CHUNK
|
||||
jmp setw_120
|
||||
; store the value
|
||||
setw_100: sar BX,1
|
||||
cmp BX,11
|
||||
jne setw_110
|
||||
mov BX,6
|
||||
jmp setw_120
|
||||
setw_110: shl BX,1 ; word offset
|
||||
add BX,10
|
||||
setw_120: mov word ptr ES:[SI+BX],CX ; store the value
|
||||
xor AX,AX
|
||||
setw_ret: pop BP
|
||||
pop ES
|
||||
ret
|
||||
set_wind endp
|
||||
;;;************************************************************************
|
||||
;;; Force Value into Range
|
||||
;;; Purpose: To test a value (in CX) to determine if it falls within a
|
||||
;;; range of values, as specified by an lower (in AX) and
|
||||
;;; upper (in DX) bounds. If the value is within the range,
|
||||
;;; the value is returned (in CX) unchanged. If it is outside
|
||||
;;; the range, the value of the endpoint nearest its value
|
||||
;;; is returned (in CX).
|
||||
;;;************************************************************************
|
||||
fit_in_r proc near
|
||||
pop DI ; get the return address
|
||||
cmp CX,AX ; value < lower?
|
||||
jge fit_10
|
||||
mov CX,AX ; yes, return lower
|
||||
fit_01: jmp DI ; return to caller
|
||||
fit_10: cmp CX,DX ; value > upper?
|
||||
jle fit_01 ; no, return
|
||||
mov CX,DX ; yes, return upper
|
||||
jmp DI ; return to caller
|
||||
fit_in_r endp
|
||||
;;;************************************************************************
|
||||
;;; Write message to the who-line
|
||||
;;;************************************************************************
|
||||
who_arg struc
|
||||
pg dw ?
|
||||
dis dw ?
|
||||
who_BP dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; caller's return address
|
||||
str dw ? ; pointer to message string
|
||||
who_arg ends
|
||||
extrn ssetadr:near
|
||||
extrn printtxt:near
|
||||
public who_writ
|
||||
who_writ proc near
|
||||
push ES
|
||||
push BP
|
||||
sub SP,offset who_BP ; allocate local storage
|
||||
mov BP,SP
|
||||
|
||||
mov ax,port_pg ;save current port address
|
||||
mov [BP].pg,ax
|
||||
mov ax,port_ds
|
||||
mov [BP].dis,ax
|
||||
|
||||
mov AX,WHO_DISP
|
||||
mov BX,WHO_PAGE*2
|
||||
pushm <AX, BX>
|
||||
call ssetadr ;get new port address
|
||||
mov SP,BP
|
||||
xor BX,BX ;compute length of string
|
||||
mov SI,[BP].str
|
||||
who_010: cmp byte ptr [SI+BX],0 ;string end?
|
||||
je who_020 ; yes, exit loop
|
||||
inc BX
|
||||
jmp who_010
|
||||
; Write message to the who line
|
||||
who_020: push BX ;bx = strlen(str)
|
||||
push SI ;si = address of string
|
||||
call printtxt
|
||||
mov SP,BP
|
||||
mov BX,[BP].pg ;restore original port
|
||||
cmp byte ptr ptype+[BX],PORTTYPE*2 ;check port type
|
||||
jne who_ret
|
||||
LoadPage ES,BX ;get page address
|
||||
mov SI,[BP].dis
|
||||
cmp byte ptr ES:[SI],PORTTYPE ;check port type
|
||||
jne who_ret
|
||||
pushm <SI, BX>
|
||||
call ssetadr ;set port address
|
||||
mov SP,BP
|
||||
who_ret: add SP,offset who_BP ;release local storage
|
||||
pop BP
|
||||
pop ES
|
||||
ret
|
||||
who_writ endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,90 @@
|
|||
;*******************************************************************************
|
||||
; *
|
||||
; Macros and equates for i/o and graphics which are performed in real mode. *
|
||||
; *
|
||||
; *
|
||||
;*******************************************************************************
|
||||
|
||||
IFNDEF DOS
|
||||
DOS equ 021h ; Dos Function Request
|
||||
ENDIF
|
||||
|
||||
IFNDEF RPC
|
||||
RPC equ 0E1h ; Real Procedure Call
|
||||
ENDIF
|
||||
|
||||
IFNDEF BLOCK_XFER
|
||||
BLOCK_XFER equ 0EC00h ; Block Transfer
|
||||
ENDIF
|
||||
|
||||
;
|
||||
; Entry points within realio.asm for performing text I/O.
|
||||
;
|
||||
|
||||
REAL_BELL equ 0 ;ring the bell
|
||||
REAL_CLEAR equ 1 ;clear the screen
|
||||
REAL_BORDER equ 2 ;draw window borders
|
||||
REAL_SAVESCR equ 3 ;save screen contents
|
||||
REAL_RESTSCR equ 4 ;restore screen contents
|
||||
REAL_CURON equ 5 ;turn cursor on
|
||||
REAL_CUROFF equ 6 ;turn cursor off
|
||||
REAL_PUTCUR equ 7 ;position cursor
|
||||
REAL_PUTC equ 8 ;write character
|
||||
REAL_SCROLLUP equ 9 ;scroll up
|
||||
REAL_SCROLLDN equ 10 ;scroll down
|
||||
REAL_EGACURS equ 11 ;ega cursor
|
||||
REAL_CHGVMODE equ 12 ;change video mode
|
||||
REAL_WRTSTRNG equ 13 ;write string to port
|
||||
REAL_WRTBLOCK equ 14 ;write string to display
|
||||
|
||||
;
|
||||
; The following macro creates the code to call all of the real mode I/O
|
||||
; routines. The arguments (which reside on the stack) are moved to the
|
||||
; a buffer which resides in real mode, along with one of the above defined
|
||||
; function indicators. Then an rpc call is performed, such that the correct
|
||||
; real mode xli routine is envoked.
|
||||
;
|
||||
|
||||
REALIO MACRO FUNCTION,ARGSTART,ARGEND,CONTINUE
|
||||
; address arguments
|
||||
push es
|
||||
push si
|
||||
push di
|
||||
mov si,bp
|
||||
add si,(ARGSTART - 2) ;ds:si => arguments
|
||||
; move arguments to real mode buffer
|
||||
push word ptr [si] ;save word at this location
|
||||
mov word ptr [si],FUNCTION ;and replace with function opcode
|
||||
IFDIF <ARGSTART>,<ARGEND> ;cx = length
|
||||
mov cx,((ARGEND + 2) - (ARGSTART - 2))
|
||||
ELSE
|
||||
mov cx,(ARGEND - (ARGSTART - 2))
|
||||
ENDIF
|
||||
mov di,word ptr REAL_BUF_SELECTOR ;get real buffer selector
|
||||
mov es,di
|
||||
mov di,word ptr REAL_BUF_TOP ;get top address of buffer
|
||||
sub di,cx ;es:di => real mode buffer
|
||||
mov ax,BLOCK_XFER ;xfer block to real memory
|
||||
int DOS
|
||||
pop [si] ;restore word at this location
|
||||
; issue call to real mode handler
|
||||
mov al,rpc_handle ;real procedure handle
|
||||
mov ah,RPC ;rpc function call
|
||||
push di ;stack pointer
|
||||
push XLI_REALIO ;real i/o function designator
|
||||
mov dx,sp
|
||||
mov cx,4 ;cx = # bytes in rpc buffer
|
||||
IFNB <CONTINUE>
|
||||
mov bx,2 ;bx = number return bytes
|
||||
ELSE
|
||||
xor bx,bx ;bx = number return bytes
|
||||
ENDIF
|
||||
int DOS
|
||||
add sp,4
|
||||
pop di
|
||||
pop si
|
||||
pop es
|
||||
ENDM
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,290 @@
|
|||
/* =====> SCHEME.H */
|
||||
/* TIPC Scheme Data Declarations for Lattice C */
|
||||
/* Last Modification: 01 January 1986 */
|
||||
|
||||
extern char *rtn_name;
|
||||
#define ASSERT(arg) if(!(arg))asrt$(rtn_name,"arg")
|
||||
#define ENTER(xyz) static char *rtn_name = "xyz"
|
||||
|
||||
/* Data conversion macros */
|
||||
/* Adjust page number- this macro converts a logical page number to
|
||||
the representation which is stored in the interpreter's registers
|
||||
and pointers. "CORRPAGE" performs the reverse transformation */
|
||||
#define ADJPAGE(x) ((x)<<1)
|
||||
/* Correct page number- this macro converts the interpreter's encoding
|
||||
of a page number into the logical page number. "ADJPAGE" performs
|
||||
the reverse transformation. */
|
||||
#define CORRPAGE(x) ((x)>>1)
|
||||
|
||||
/* Fetch value for Fixnum (immediate) from pointer */
|
||||
#define get_fix(pg,ds) (((ds)<<1)>>1)
|
||||
/* Fetch value for Character (immediate) from pointer */
|
||||
#define get_char(pg,ds) ((ds) & 0x00ff)
|
||||
|
||||
/* define truth */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NULL 0 /* null pointer */
|
||||
|
||||
/* Position of page/displacement values in "registers" */
|
||||
#define C_DISP 0
|
||||
#define C_PAGE 1
|
||||
|
||||
/* Page Management Table Definitions */
|
||||
#define NUMPAGES 128 /* maximum number of pages */
|
||||
#define DEDPAGES 8 /* Number of dedicated pages */
|
||||
|
||||
#define MIN_PAGESIZE 0x0C00 /* minimum page size in bytes (fixed size) */
|
||||
#define PTRMASK MIN_PAGESIZE-1 /* mask to isolate a pointer displacement */
|
||||
|
||||
#define PAGEINCR 2 /* increment to get to next page */
|
||||
#define PAGEMASK 0x00FE /* mask to isolate a page number */
|
||||
#define WORDSIZE 16 /* computer's word size (bits/word) */
|
||||
#define WORDINCR 2 /* number of address units/word */
|
||||
#define HT_SIZE 211 /* the oblist's hash table size */
|
||||
#define STKSIZE 900 /* the stack's length (bytes) */
|
||||
#define BLK_OVHD 3 /* number of overhead bytes in a block header */
|
||||
#define NUM_REGS 64 /* number of registers in the Scheme VM */
|
||||
|
||||
/* Data Type Equates */
|
||||
#define NUMTYPES 15 /* the number of data types */
|
||||
#define LISTTYPE 0
|
||||
#define FIXTYPE 1
|
||||
#define FLOTYPE 2
|
||||
#define BIGTYPE 3
|
||||
#define SYMTYPE 4
|
||||
#define STRTYPE 5
|
||||
#define ARYTYPE 6
|
||||
#define VECTTYPE ARYTYPE
|
||||
#define CONTTYPE 7
|
||||
#define CLOSTYPE 8
|
||||
#define FREETYPE 9
|
||||
#define CODETYPE 10
|
||||
#define REFTYPE 11
|
||||
#define PORTTYPE 12
|
||||
#define CHARTYPE 13
|
||||
#define ENVTYPE 14
|
||||
|
||||
#define EOFERR 1 /* Codes for function ERRMSG */
|
||||
#define DOTERR 2
|
||||
#define QUOTERR 3
|
||||
#define RPARERR 4
|
||||
#define OVERERR 5
|
||||
#define DIV0ERR 6
|
||||
#define SHARPERR 7
|
||||
#define FULLERR -1
|
||||
#define PORTERR -2
|
||||
#define HEAPERR -3
|
||||
|
||||
#define BUFSIZE 80
|
||||
#define SYM_OVHD 7
|
||||
|
||||
#define PTRSIZE 3
|
||||
#define LISTSIZE 6
|
||||
#define FIXSIZE 2
|
||||
#define FLOSIZE 9
|
||||
#define SMALL_SIZE 1024 /* a "small" length for a block */
|
||||
|
||||
#define SPECCHAR 1 /* special page of characters */
|
||||
#define SPECFIX 3 /* special page of fixnums */
|
||||
#define SFIXLEN 0 /* length (bytes) of special fixnum page */
|
||||
#define SPECFLO 4 /* special page of flonums */
|
||||
#define SFLOLEN 24 /* length (bytes) of special flonum page */
|
||||
#define SPECSYM 5 /* special page of symbols */
|
||||
#define SSYMLEN 0x51 /* length (bytes) of special symbol page */
|
||||
#define SPECSTK 6
|
||||
#define SPECPOR 6 /* special page of ports */
|
||||
#define SPORLEN 92 /* length (bytes) of special port page */
|
||||
#define SPECCODE 7 /* code page for the bootstrap loader */
|
||||
|
||||
#define END_LIST 0x7FFF /* end of linked list marker */
|
||||
|
||||
#define NIL_PAGE 0 /* Location of "nil" */
|
||||
#define NIL_DISP 0
|
||||
#define T_PAGE SPECSYM /* Location of "t" (for true) */
|
||||
#define T_DISP 0x0000
|
||||
#define UN_PAGE SPECSYM /* Location of "#!unassigned" */
|
||||
#define UN_DISP 0x0009
|
||||
#define NTN_PAGE SPECSYM /* Location of "#!not-a-number" */
|
||||
#define NTN_DISP 0x001C
|
||||
#define OVR_PAGE SPECSYM /* Location of overflow designator */
|
||||
#define OVR_DISP 0x001C /* (same as "not a number" for now) */
|
||||
#define DIV0_PAGE SPECSYM /* Location of divide-by-zero designator */
|
||||
#define DIV0_DISP 0x001C /* (same as "not a number" for now) */
|
||||
#define IN_PAGE SPECPOR /* Location of standard input port */
|
||||
#define IN_DISP 0
|
||||
#define OUT_PAGE SPECPOR /* Location of standard output port */
|
||||
/* #define OUT_DISP 0x011f */
|
||||
#define OUT_DISP 0 /* input=output for standard console device */
|
||||
#define WHO_PAGE SPECPOR /* Location of "who-line" port */
|
||||
#define WHO_DISP 0x0123
|
||||
#define EOF_PAGE SPECSYM /* Location of non-interned "**eof**" symbol */
|
||||
#define EOF_DISP 0x0031
|
||||
#define NPR_PAGE SPECSYM /* Location of "#!unprintable" */
|
||||
#define NPR_DISP 0x003D
|
||||
|
||||
#define ADD_OP 0 /* addition */
|
||||
#define SUB_OP 1 /* subtraction */
|
||||
#define MUL_OP 2 /* multiplication */
|
||||
#define DIV_OP 3 /* divide */
|
||||
#define MOD_OP 4 /* modulo */
|
||||
#define AND_OP 5 /* bitwise and */
|
||||
#define OR_OP 6 /* bitwise or */
|
||||
#define MINUS_OP 7 /* minus */
|
||||
#define EQ_OP 8 /* equal comparison */
|
||||
#define NE_OP 9 /* not equal comparison */
|
||||
#define LT_OP 10 /* less than comparison */
|
||||
#define GT_OP 11 /* greater than comparison */
|
||||
#define LE_OP 12 /* less than or equal comparison */
|
||||
#define GE_OP 13 /* greater than or equal comparison */
|
||||
#define ABS_OP 14 /* absolute value */
|
||||
#define QUOT_OP 15 /* quotient */
|
||||
#define TRUNC_OP 16 /* truncate */
|
||||
#define FLOOR_OP 17 /* floor */
|
||||
#define CEIL_OP 18 /* ceiling */
|
||||
#define ROUND_OP 19 /* round */
|
||||
#define FLOAT_OP 20 /* float */
|
||||
#define ZERO_OP 21 /* zero? */
|
||||
#define POS_OP 22 /* positive? */
|
||||
#define NEG_OP 23 /* negative? */
|
||||
|
||||
/* Numeric Error Codes */
|
||||
#define REF_GLOBAL_ERROR 1 /* reference of unbound global variable */
|
||||
#define SET_GLOBAL_ERROR 2 /* SET! error-- global not defined */
|
||||
#define REF_LEXICAL_ERROR 3 /* reference of unbound lexical variable */
|
||||
#define SET_LEXICAL_ERROR 4 /* SET! error-- lexical variable not defined */
|
||||
#define REF_FLUID_ERROR 5 /* reference of unbound fluid variable */
|
||||
#define SET_FLUID_ERROR 6 /* SET-FLUID! error-- fluid not bound */
|
||||
#define VECTOR_OFFSET_ERROR 7 /* vector index out of range */
|
||||
#define STRING_OFFSET_ERROR 8 /* string index out of range */
|
||||
#define SUBSTRING_RANGE_ERROR 9 /* invalid substring range */
|
||||
#define INVALID_OPERAND_ERROR 10 /* invalid operand to VM instruction */
|
||||
#define SHIFT_BREAK_CONDITION 11 /* SHFT-BRK key was depressed by user */
|
||||
#define NON_PROCEDURE_ERROR 12 /* attempted to call non-procedural object */
|
||||
#define TIMEOUT_CONDITION 13 /* timer interrupt */
|
||||
#define WINDOW_FAULT_CONDITION 14 /* attempt to do I/O to a de-exposed window */
|
||||
#define FLONUM_OVERFLOW_ERROR 15 /* flonum overflow/underflow */
|
||||
#define ZERO_DIVIDE_ERROR 16 /* division by zero */
|
||||
#define NUMERIC_OPERAND_ERROR 17 /* non-numeric operand */
|
||||
#define APPLY_ARG_LIMIT_ERROR 18 /* too many arguments for APPLY to handle */
|
||||
#define VECTOR_SIZE_LIMIT_ERROR 19 /* vector too big */
|
||||
#define STRING_SIZE_LIMIT_ERROR 20 /* string too big */
|
||||
#define DOS_FATAL_ERROR 21 /* DOS fatal i/o error (24H INT) */
|
||||
|
||||
/* Scheme VM Control Flags */
|
||||
extern int PC_MAKE; /* variable denoting PC's manufacturer & type */
|
||||
extern int VM_debug; /* VM debug mode flag */
|
||||
extern int s_break; /* shift-break indicator */
|
||||
|
||||
extern int QUOTE_PAGE; /* Location of "quote" */
|
||||
extern int QUOTE_DISP;
|
||||
|
||||
extern unsigned PAGESIZE;
|
||||
extern unsigned pagetabl[NUMPAGES]; /* Paragraph Address (bases) */
|
||||
extern struct {
|
||||
unsigned atom:1;
|
||||
unsigned listcell:1;
|
||||
unsigned fixnums:1;
|
||||
unsigned flonums:1;
|
||||
unsigned bignums:1;
|
||||
unsigned symbols:1;
|
||||
unsigned strings:1;
|
||||
unsigned arrays:1;
|
||||
unsigned nomemory:1;
|
||||
unsigned readonly:1;
|
||||
unsigned continu:1;
|
||||
unsigned closure:1;
|
||||
unsigned refs:1;
|
||||
unsigned ports:1;
|
||||
unsigned code:1;
|
||||
unsigned characters:1;
|
||||
} attrib[NUMPAGES]; /* Page Attribute Bits */
|
||||
extern int w_attrib[NUMPAGES]; /* Re-define attribute bits as integer */
|
||||
extern int nextcell[NUMPAGES]; /* Next Available Cell Pointers */
|
||||
extern int pagelink[NUMPAGES]; /* Next Page of Same Type */
|
||||
extern int ptype[NUMPAGES]; /* Page Type Index */
|
||||
extern unsigned psize[NUMPAGES]; /* Page Size Table */
|
||||
|
||||
extern int pageattr[NUMTYPES]; /* Page attribute initialization table */
|
||||
extern int pagelist[NUMTYPES]; /* Page allocation table (by types) */
|
||||
|
||||
extern int listpage; /* Page for List Cell allocation */
|
||||
extern int fixpage; /* Page for Fixnum allocation */
|
||||
extern int flopage; /* Page for Flonum allocation */
|
||||
extern int bigpage; /* Page for Bignum allocation */
|
||||
extern int sympage; /* Page for Symbol allocation */
|
||||
extern int strpage; /* Page for String allocation */
|
||||
extern int arypage; /* Page for Array allocation */
|
||||
extern int contpage; /* Page for Continuation allocation */
|
||||
extern int clospage; /* Page for Closure allocation */
|
||||
extern int freepage; /* Free page allocation list header */
|
||||
extern int codepage; /* Page for Code Block allocation */
|
||||
extern int refpage; /* Ref cell page allocation list header */
|
||||
|
||||
extern int nextpage; /* Next Page Number for Allocation in the
|
||||
Logical Address Space */
|
||||
extern unsigned nextpara; /* Next Paragraph Address for Allocation */
|
||||
|
||||
/* Scheme's Virtual Registers */
|
||||
extern long reg0, regs[NUM_REGS];
|
||||
extern int nil_reg[2];
|
||||
extern int reg0_page, reg0_disp, tmp_reg[2], tmp_page, tmp_disp;
|
||||
extern int tm2_reg[2], tm2_page, tm2_disp;
|
||||
extern int FNV_reg[2], GNV_reg[2], CB_reg[2], PREV_reg[2];
|
||||
extern int FNV_pag, FNV_dis, GNV_pag, GNV_dis, CB_pag, CB_dis;
|
||||
extern int PREV_pag, PREV_dis, FP, BASE;
|
||||
extern int CONSOLE_[2], CON_PAGE, CON_DISP;
|
||||
extern int TRNS_reg[2], TRNS_pag, TRNS_dis; /* transcript file pointer */
|
||||
extern int condcode, S_pc;
|
||||
|
||||
/* Stack */
|
||||
extern int TOS; /* top of stack pointer (displacement in bytes */
|
||||
extern char S_stack[STKSIZE]; /* the stack itself */
|
||||
|
||||
/* Hash Table */
|
||||
extern char hash_page[HT_SIZE];
|
||||
extern int hash_disp[HT_SIZE];
|
||||
|
||||
/* Property List Hash Table */
|
||||
extern char prop_page[HT_SIZE];
|
||||
extern int prop_disp[HT_SIZE];
|
||||
|
||||
/* State Variables for (reset) and (scheme-reset) */
|
||||
extern int FP_save, RST_ent;
|
||||
extern int FNV_save[2];
|
||||
extern int STL_save[2];
|
||||
|
||||
/* Port fields */
|
||||
#define pt_direc 6
|
||||
#define pt_lnlen 20
|
||||
#define pt_csrcol 12
|
||||
#define dtaoffs 32
|
||||
|
||||
/* Error message text strings */
|
||||
extern char m_error[], m_src[], m_dest[], m_first[], m_second[], m_third[];
|
||||
|
||||
/* Macros Normally Found in STDIO.H */
|
||||
#define abs(x) ((x)<0?-(x):(x))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define min(a,b) ((a)<=(b)?(a):(b))
|
||||
|
||||
/* Scheme Function Macros */
|
||||
#define alloc_sym(dest,len) alloc_block(dest,SYMTYPE,len+PTRSIZE+1)
|
||||
|
||||
/* International Case Conversion Macros */
|
||||
extern char locases[256];
|
||||
extern char hicases[256];
|
||||
#undef tolower
|
||||
#define tolower(c) locases[(c)]
|
||||
#undef toupper
|
||||
#define toupper(c) hicases[(c)]
|
||||
#undef islower
|
||||
#define islower(c) ((c)!=hicases[(c)])
|
||||
#undef isupper
|
||||
#define isupper(c) ((c)!=locases[(c)])
|
||||
#undef isspace
|
||||
#undef isdigit
|
||||
#define isdigit(c) isdig((c),10)
|
||||
#undef isxdigit
|
||||
#define isxdigit(c) isdig((c),16)
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
;
|
||||
; Dos function requests provided by AIA for performing real procedure calls
|
||||
;
|
||||
|
||||
RPC_INIT equ 0E0h ; Initialize RPC
|
||||
RPC equ 0E1h ; Issue RPC
|
||||
|
||||
;
|
||||
; Real procedure entry points.
|
||||
;
|
||||
; REALSCHM.ASM is a real procedure which is loaded upon initialization of
|
||||
; Scheme and accessed via real procedure calls. It currently contains a
|
||||
; table of 25 entries (0-24) which contain routines accessable from our
|
||||
; protected mode code. The first 20 entries will contain addresses to
|
||||
; code within realschm.asm, primarily for things like xli support which
|
||||
; can't be provided in protected mode. The next 5 entries are for system
|
||||
; xli routines. An xli routine is distinguished as a system xli routine by
|
||||
; having the FB_SYSINT flag in the file block set non-zero. Note that the
|
||||
; system xli routines must be in a specified order, as defined in
|
||||
; PRO2REAL.ASM.
|
||||
;
|
||||
;
|
||||
RPCINIT equ 0 ;Initialize real procedure
|
||||
RPCRETBUF equ 0 ;Return real procedure buffer address
|
||||
RPCTYPE equ 1 ;Return pc type and graphics info
|
||||
RPCLDEXE equ 2 ;Load an XLI file
|
||||
RPCUNLDALL equ 3 ;Unload all XLI files
|
||||
RPCXESC equ 4 ;Perform XESC to an XLI function
|
||||
RPCXLISSR equ 5 ;XESC Special Services Return
|
||||
RPCTAKCRT equ 6 ;takeover real mode crt interrupt
|
||||
RPCRSTCRT equ 7 ;restore real mode system crt interrupt
|
||||
; order dependent system xli files (see table in pro2real.asm & realschm.asm)
|
||||
XLI_REALIO equ 20 ;Perform text I/O
|
||||
XLI_GRAPH equ 21 ;Perform Graphics
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
; =====> SAPROP.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Property List Support *
|
||||
;* *
|
||||
;* (C) Copyright 1986 by *
|
||||
;* Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 7 May 1986 *
|
||||
;* Last Modification: 11 May 1986 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;************************************************************************
|
||||
;* Search for Property in Property List *
|
||||
;* *
|
||||
;* Calling Sequence: found? = prop_search(list,prop); *
|
||||
;* *
|
||||
;* Input Parameters: list - the property list for a symbol. *
|
||||
;* prop - the property for which to search. *
|
||||
;* *
|
||||
;* Output Parameters: found? - if the property was found in the list, *
|
||||
;* found?=1; else found?=0. *
|
||||
;* list - a pointer to the property/value pair *
|
||||
;* for the specified property. If not found, NIL. *
|
||||
;* *
|
||||
;* Note: This routine is an assembly language version of the following *
|
||||
;* C source: *
|
||||
;* prop_search(list, prop) *
|
||||
;* int list[2],prop[2]; *
|
||||
;* { *
|
||||
;* int search[2]; /* current search entry in list */ *
|
||||
;* int temp[2]; /* temporary "register" */ *
|
||||
;* ENTER(prop_search); *
|
||||
;* *
|
||||
;* mov_reg(search, list); *
|
||||
;* take_cdr(search); *
|
||||
;* while(search[C_PAGE]) *
|
||||
;* { *
|
||||
;* mov_reg(temp, search); *
|
||||
;* take_car(temp); *
|
||||
;* if (eq(temp,prop)) *
|
||||
;* { *
|
||||
;* mov_reg(list, search); *
|
||||
;* return(FOUND); *
|
||||
;* } *
|
||||
;* take_cddr(search); *
|
||||
;* } /* end: while(search[C_PAGE]) */ *
|
||||
;* return(NOT_FOUND); *
|
||||
;* } /* end of function: prop_search(list, prop) */ *
|
||||
;************************************************************************
|
||||
p_arg struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; return address
|
||||
p_list dw ? ; addr of reg containing list to search
|
||||
p_prop dw ? ; the property for which we're searching
|
||||
p_arg ends
|
||||
|
||||
public prop_sea
|
||||
prop_sea proc near
|
||||
push ES ; save caller's ES register
|
||||
push BP ; save caller's BP register
|
||||
mov BP,SP ; establish addressability
|
||||
; Load up the property for which we're searching into CL:DX
|
||||
mov BX,[BP].p_prop
|
||||
mov CL,byte ptr [BX].C_page
|
||||
mov DX,[BX].C_disp
|
||||
; Load up a pointer to the beginning of the property list
|
||||
mov SI,[BP].p_list
|
||||
xor BX,BX
|
||||
mov BL,byte ptr [SI].C_page
|
||||
mov DI,[SI].C_disp
|
||||
jmp short start
|
||||
; Property didn't match-- keep searching list
|
||||
no_match: mov BL,ES:[DI].cdr_page
|
||||
mov DI,ES:[DI].cdr
|
||||
; Take CDR to get to first property/value pair or to follow list
|
||||
start: cmp BL,0
|
||||
je p_nf
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne p_nf
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov BL,ES:[DI].cdr_page
|
||||
mov DI,ES:[DI].cdr
|
||||
; Test for valid list cell
|
||||
cmp BL,0
|
||||
je p_nf
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne p_nf
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
cmp DX,ES:[DI].car
|
||||
jne no_match
|
||||
cmp CL,ES:[DI].car_page
|
||||
jne no_match
|
||||
; Property found!-- return pointer to it
|
||||
mov byte ptr [SI].C_page,BL ; move pointer to property entry
|
||||
mov [SI].C_disp,DI ; into the "list" operand register
|
||||
pop BP ; restore caller's BP register
|
||||
pop ES ; restore caller's ES register
|
||||
mov AX,1 ; indicate property found
|
||||
ret ; return
|
||||
; End of property list-- return not found
|
||||
p_nf: xor AX,AX ; indicate no match found
|
||||
pop BP ; restore caller's BP register
|
||||
pop ES ; restore caller's ES register
|
||||
ret ; return
|
||||
prop_sea endp
|
||||
|
||||
;************************************************************************
|
||||
;* Search for Symbol in Property List *
|
||||
;* *
|
||||
;* Calling Sequence: sym_search(sym) *
|
||||
;* *
|
||||
;* Input Parameters: sym - a register containing a symbol who's *
|
||||
;* property list is to be located. *
|
||||
;* *
|
||||
;* Output Parameters: sym - the register is updated to point to the *
|
||||
;* property list for the symbol. If no property *
|
||||
;* list exists, it is set to NIL. *
|
||||
;* *
|
||||
;* Note: This routine is an assembly language version of the following *
|
||||
;* C source: *
|
||||
;* sym_search(sym) *
|
||||
;* int sym[2]; *
|
||||
;* { *
|
||||
;* int hash_value; /* symbol's hash value */ *
|
||||
;* int sym_save[2]; /* initial value of symbol argument */ *
|
||||
;* int temp[2]; /* temporary "register" */ *
|
||||
;* ENTER(sym_search); *
|
||||
;* *
|
||||
;* if (ptype[CORRPAGE(sym[C_PAGE])] == SYMTYPE*2) *
|
||||
;* { *
|
||||
;* /* save symbol's page and displacement for testing purposes */ *
|
||||
;* mov_reg(sym_save, sym); *
|
||||
;* *
|
||||
;* /* obtain hash chain to search */ *
|
||||
;* hash_value = sym_hash(sym); *
|
||||
;* sym[C_PAGE] = prop_page[hash_value]; *
|
||||
;* sym[C_DISP] = prop_disp[hash_value]; *
|
||||
;* *
|
||||
;* while(sym[C_PAGE]) *
|
||||
;* { *
|
||||
;* mov_reg(temp, sym); *
|
||||
;* take_caar(temp); *
|
||||
;* if (eq(temp, sym_save)) *
|
||||
;* { *
|
||||
;* /* symbol found-- return pointer to symbol's property list */*
|
||||
;* take_car(sym); *
|
||||
;* break; *
|
||||
;* } *
|
||||
;* else *
|
||||
;* { *
|
||||
;* take_cdr(sym); *
|
||||
;* } *
|
||||
;* } /* end: while(sym[C_PAGE]) */ *
|
||||
;* } *
|
||||
;* } /* end of function: sym_search(sym) */ *
|
||||
;* *
|
||||
;************************************************************************
|
||||
sym_args struc
|
||||
dw ? ; caller's ES register
|
||||
dw ? ; caller's BP register
|
||||
dw ? ; return address
|
||||
s_sym dw ? ; address of symbol/result register
|
||||
sym_args ends
|
||||
|
||||
public sym_sear
|
||||
sym_sear proc near
|
||||
push BP ; save the caller's BP register
|
||||
push ES ; save the caller's ES register
|
||||
mov BP,SP ; establish addressability
|
||||
; Load a pointer to the symbol and get its hash value
|
||||
mov SI,[BP].s_sym ; load symbol register's address
|
||||
mov BX,[SI].C_page ; load symbol's page number
|
||||
cmp byte ptr ptype+[BX],SYMTYPE*2 ; it is a symbol, isn't it?
|
||||
jne s_nf ; if not a symbol, return NIL
|
||||
mov SI,[SI].C_disp ; load symbol's displacement and
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; paragraph address
|
||||
mov CX,BX ; copy the symbol into CL:DX
|
||||
mov DX,SI
|
||||
mov BL,ES:[SI].sym_hkey ; load hash key
|
||||
mov DI,BX ; copy hash key into DI and
|
||||
shl DI,1 ; multiply by two for word index
|
||||
mov BL,prop_pag+[BX] ; load property list header for this
|
||||
mov DI,prop_dis+[DI] ; symbol's bucket
|
||||
jmp short go
|
||||
; Search the next entry in the bucket
|
||||
s_next: mov BX,AX
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,AX ; restore ES register for bucket entry
|
||||
s_next1: mov BL,ES:[DI].cdr_page ; load pointer to next bucket entry from
|
||||
mov DI,ES:[DI].cdr ; the CDR field
|
||||
go: cmp BL,0 ; end of bucket?
|
||||
je s_nf ; if so, jump
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; list cell?
|
||||
jne s_nf ; if not a pair (?), jump
|
||||
LoadPage ES,BX
|
||||
mov AX,BX ; Save Bucket entry page number
|
||||
;;; mov ES,pagetabl+[BX] ; load list cell's paragraph address
|
||||
; Fetch the property list from the CAR field of the bucket entry
|
||||
mov BL,ES:[DI].car_page
|
||||
mov SI,ES:[DI].car
|
||||
cmp BL,0 ; no property list for this bucket entry?
|
||||
je s_next1 ; if not (?), ignore it
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; it is a pair, isn't it?
|
||||
jne s_next1 ; if not (?), ignore it
|
||||
;;; mov AX,ES ; save ES register for bucket entry
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load the paragraph addr of prop list entry
|
||||
cmp DX,ES:[SI].car ; entry for our symbol?
|
||||
jne s_next ; if not, jump
|
||||
cmp CL,ES:[SI].car_page ; entry for our symbol?
|
||||
jne s_next ; if not, jump
|
||||
; Symbol's property list found-- return in symbol register (or return NIL)
|
||||
mov DI,[BP].s_sym ; reload source/destination register address
|
||||
mov byte ptr [DI].C_page,BL ; store prop list pointer into
|
||||
mov [DI].C_disp,SI ; the register
|
||||
pop ES ; restore the caller's ES register
|
||||
pop BP ; restore the caller's BP register
|
||||
ret ; return
|
||||
; Invalid list structure-- return NIL
|
||||
s_nf: xor AX,AX ; create a NIL pointer
|
||||
mov DI,[BP].s_sym
|
||||
mov byte ptr [DI].C_page,AL
|
||||
mov [DI].C_disp,AX
|
||||
pop ES
|
||||
pop BP
|
||||
ret
|
||||
sym_sear endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,564 @@
|
|||
; =====> SASM.MAC
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Assembler Macros *
|
||||
;* (C) Copyright 1984,1984 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 14 May 1984 *
|
||||
;* Last Modification: 1 April 1985 *
|
||||
;***************************************
|
||||
; Register equates
|
||||
R0 equ 0
|
||||
R1 equ 4
|
||||
R2 equ 8
|
||||
R3 equ 12
|
||||
R4 equ 16
|
||||
R5 equ 20
|
||||
R6 equ 24
|
||||
R7 equ 28
|
||||
R8 equ 32
|
||||
R9 equ 36
|
||||
R10 equ 40
|
||||
R11 equ 44
|
||||
R12 equ 48
|
||||
R13 equ 52
|
||||
R14 equ 56
|
||||
R15 equ 60
|
||||
R16 equ 64
|
||||
R17 equ 68
|
||||
R18 equ 72
|
||||
R19 equ 76
|
||||
R20 equ 80
|
||||
R21 equ 84
|
||||
R22 equ 88
|
||||
R23 equ 92
|
||||
R24 equ 96
|
||||
R25 equ 100
|
||||
R26 equ 104
|
||||
R27 equ 108
|
||||
R28 equ 112
|
||||
R29 equ 116
|
||||
R30 equ 120
|
||||
R31 equ 124
|
||||
R32 equ 128
|
||||
R33 equ 132
|
||||
R34 equ 136
|
||||
R35 equ 140
|
||||
R36 equ 144
|
||||
R37 equ 148
|
||||
R38 equ 152
|
||||
R39 equ 156
|
||||
R40 equ 160
|
||||
R41 equ 164
|
||||
R42 equ 168
|
||||
R43 equ 172
|
||||
R44 equ 176
|
||||
R45 equ 180
|
||||
R46 equ 184
|
||||
R47 equ 188
|
||||
R48 equ 192
|
||||
R49 equ 196
|
||||
R50 equ 200
|
||||
R51 equ 204
|
||||
R52 equ 208
|
||||
R53 equ 212
|
||||
R54 equ 216
|
||||
R55 equ 220
|
||||
R56 equ 224
|
||||
R57 equ 228
|
||||
R58 equ 232
|
||||
R59 equ 236
|
||||
R60 equ 240
|
||||
R61 equ 244
|
||||
R62 equ 248
|
||||
R63 equ 252
|
||||
|
||||
; Instruction macros
|
||||
COPY_ macro dest,src
|
||||
db 0,dest,src
|
||||
endm
|
||||
|
||||
LD_CON_ macro dest,numb
|
||||
db 1,dest,numb
|
||||
endm
|
||||
|
||||
LD_IMM_ macro dest,val
|
||||
db 2,dest,val
|
||||
endm
|
||||
|
||||
LD_NIL_ macro dest
|
||||
db 3,dest
|
||||
endm
|
||||
|
||||
LD_LCL_ macro dest,entry
|
||||
db 4,dest,entry
|
||||
endm
|
||||
|
||||
LD_GLOBAL_ macro dest,src
|
||||
db 7,dest,src
|
||||
endm
|
||||
|
||||
LD_FLUID_ macro dest,src ; load fluid
|
||||
db 8,dest,src
|
||||
endm
|
||||
|
||||
LD_S_ macro dest,src,off
|
||||
temp_ld = offset off
|
||||
temp_ld = temp_ld/3
|
||||
db 9,dest,src,temp_ld
|
||||
endm
|
||||
|
||||
LD_L_ macro dest,src,off
|
||||
temp_ld = offset off
|
||||
temp_ld = temp_ld/3
|
||||
db 10,dest,src
|
||||
dw temp_ld
|
||||
endm
|
||||
|
||||
LD_R_ macro dest,src,off
|
||||
db 11,dest,src,off
|
||||
endm
|
||||
|
||||
LD_GL_R_ macro dest,src
|
||||
db 27,dest,src
|
||||
endm
|
||||
|
||||
BIND_FL_ macro const,src ; bind fluid variable
|
||||
db 29,const,src
|
||||
endm
|
||||
|
||||
DEFINE_ macro dest,const
|
||||
db 31,dest,const
|
||||
endm
|
||||
|
||||
DEF_ENV_ macro sym,val,env
|
||||
db 220,sym,val,env
|
||||
endm
|
||||
|
||||
CLOSE_ macro dest,lbl,nargs
|
||||
local x
|
||||
db 60,dest
|
||||
dw lbl-x
|
||||
db nargs
|
||||
x equ $
|
||||
endm
|
||||
|
||||
LD_FL_R_ macro dest,src ; load fluid from symbol in register
|
||||
db 63,dest,src ; temporary instruction?
|
||||
endm
|
||||
|
||||
LD_CAR_ macro dest,src
|
||||
db 64,dest,src
|
||||
endm
|
||||
|
||||
LD_CDR_ macro dest,src
|
||||
db 65,dest,src
|
||||
endm
|
||||
|
||||
LD_CAAR_ macro dest,src
|
||||
db 66,dest,src
|
||||
endm
|
||||
|
||||
LD_CADR_ macro dest,src
|
||||
db 67,dest,src
|
||||
endm
|
||||
|
||||
LD_CDAR_ macro dest,src
|
||||
db 68,dest,src
|
||||
endm
|
||||
|
||||
LD_CDDR_ macro dest,src
|
||||
db 69,dest,src
|
||||
endm
|
||||
|
||||
LD_CAAAR_ macro dest,src
|
||||
db 70,dest,src
|
||||
endm
|
||||
|
||||
LD_CAADR_ macro dest,src
|
||||
db 71,dest,src
|
||||
endm
|
||||
|
||||
LD_CADAR_ macro dest,src
|
||||
db 72,dest,src
|
||||
endm
|
||||
|
||||
LD_CADDR_ macro dest,src
|
||||
db 73,dest,src
|
||||
endm
|
||||
|
||||
LD_CDAAR_ macro dest,src
|
||||
db 74,dest,src
|
||||
endm
|
||||
|
||||
LD_CDADR_ macro dest,src
|
||||
db 75,dest,src
|
||||
endm
|
||||
|
||||
LD_CDDAR_ macro dest,src
|
||||
db 76,dest,src
|
||||
endm
|
||||
|
||||
LD_CDDDR_ macro dest,src
|
||||
db 77,dest,src
|
||||
endm
|
||||
|
||||
LD_CADDDR_ macro dest,src
|
||||
db 78,dest,src
|
||||
endm
|
||||
|
||||
CONS_ macro dest,car,cdr
|
||||
db 79,dest,car,cdr
|
||||
endm
|
||||
|
||||
SETCAR_ macro dest,src
|
||||
db 20,dest,src
|
||||
endm
|
||||
|
||||
SETCDR_ macro dest,src
|
||||
db 21,dest,src
|
||||
endm
|
||||
|
||||
ST_S_ macro dest,src,off
|
||||
db 17,dest,src,offset off
|
||||
endm
|
||||
|
||||
ST_L_ macro dest,src,off
|
||||
db 18,dest,src
|
||||
dw offset off
|
||||
endm
|
||||
|
||||
ST_R_ macro dest,src,off
|
||||
db 19,dest,src,off
|
||||
endm
|
||||
|
||||
SETREF_ macro val,ref
|
||||
db 22,val,ref
|
||||
endm
|
||||
|
||||
JMP_S_ macro label
|
||||
db 32,label-$-1
|
||||
endm
|
||||
|
||||
JMP_L_ macro label
|
||||
db 33
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
JNIL_S_ macro reg,label
|
||||
db 34,reg,label-$-1
|
||||
endm
|
||||
|
||||
JNIL_L_ macro reg,label
|
||||
db 35,reg
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
JNNIL_S_ macro reg,label
|
||||
db 36,reg,label-$-1
|
||||
endm
|
||||
|
||||
JNNIL_L_ macro reg,label
|
||||
db 37,reg
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
JATOM_S_ macro reg,label
|
||||
db 38,reg,label-$-1
|
||||
endm
|
||||
|
||||
JATOM_L_ macro reg,label
|
||||
db 39,reg
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
JNATOM_S_ macro reg,label
|
||||
db 40,reg,label-$-1
|
||||
endm
|
||||
|
||||
JNATOM_L_ macro reg,label
|
||||
db 41,reg
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
DEREF_ macro dest ; (deref x)
|
||||
db 46,dest
|
||||
endm
|
||||
|
||||
REF_ macro dest ; (ref x)
|
||||
db 47,dest
|
||||
endm
|
||||
|
||||
CALL_ macro label,dl_lvl,dl_heap
|
||||
db 48
|
||||
dw label-$-4
|
||||
db dl_lvl,dl_heap
|
||||
endm
|
||||
|
||||
CALL_TR_ macro label,dl_lvl,dl_heap
|
||||
db 49
|
||||
dw label-$-4
|
||||
db dl_lvl,dl_heap
|
||||
endm
|
||||
|
||||
CALL_CC_ macro label,dl_lvl,dl_heap
|
||||
db 50
|
||||
dw label-$-4
|
||||
db dl_lvl,dl_heap
|
||||
endm
|
||||
|
||||
CALL_CT_ macro label,dl_lvl,dl_heap
|
||||
db 51
|
||||
dw label-$-4
|
||||
db dl_lvl,dl_heap
|
||||
endm
|
||||
|
||||
CALL_CL_ macro reg,nargs
|
||||
db 52,reg,nargs
|
||||
endm
|
||||
|
||||
CLOSURP_ macro dest ; (closure? obj)
|
||||
db 129,dest
|
||||
endm
|
||||
|
||||
FLUID_P_ macro dest ; (fluid-bound? obj)
|
||||
db 134,dest
|
||||
endm
|
||||
|
||||
STRINGP_ macro dest ; (string? obj)
|
||||
db 143,dest
|
||||
endm
|
||||
|
||||
SYMBOLP_ macro dest ; (symbol? obj)
|
||||
db 144,dest
|
||||
endm
|
||||
|
||||
MINUS_ macro dest ; (minus n)
|
||||
db 151,dest
|
||||
endm
|
||||
|
||||
A_S_ macro dest ; (ascii->symbol n)
|
||||
db 160,dest
|
||||
endm
|
||||
|
||||
S_A_ macro dest ; (symbol->ascii sym)
|
||||
db 161,dest
|
||||
endm
|
||||
|
||||
ADD_ macro dest,src
|
||||
db 80,dest,src
|
||||
endm
|
||||
|
||||
ADDI_ macro dest,imm
|
||||
db 81,dest,imm
|
||||
endm
|
||||
|
||||
SUB_ macro dest,src
|
||||
db 82,dest,src
|
||||
endm
|
||||
|
||||
MUL_ macro dest,src
|
||||
db 83,dest,src
|
||||
endm
|
||||
|
||||
MULI_ macro dest,imm
|
||||
db 84,dest,imm
|
||||
endm
|
||||
|
||||
DIV_ macro dest,src
|
||||
db 85,dest,src
|
||||
endm
|
||||
|
||||
DIVI_ macro dest,imm
|
||||
db 86,dest,imm
|
||||
endm
|
||||
|
||||
MOD_ macro dest,src
|
||||
db 88,dest,src
|
||||
endm
|
||||
|
||||
JEQ_S_ macro reg1,reg2,label
|
||||
db 42,reg1,reg2,label-$-1
|
||||
endm
|
||||
|
||||
JEQ_L_ macro reg1,reg2,label
|
||||
db 43,reg1,reg2
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
JNEQ_S_ macro reg1,reg2,label
|
||||
db 44,reg1,reg2,label-$-1
|
||||
endm
|
||||
|
||||
JNEQ_L_ macro reg1,reg2,label
|
||||
db 45,reg1,reg2
|
||||
dw label-$-2
|
||||
endm
|
||||
|
||||
EQ_ macro n1,n2
|
||||
db 94,n1,n2
|
||||
endm
|
||||
|
||||
NE_ macro n1,n2
|
||||
db 97,n1,n2
|
||||
endm
|
||||
|
||||
LT_ macro n1,n2
|
||||
db 92,n1,n2
|
||||
endm
|
||||
|
||||
GT_ macro n1,n2
|
||||
db 95,n1,n2
|
||||
endm
|
||||
|
||||
LE_ macro n1,n2
|
||||
db 93,n1,n2
|
||||
endm
|
||||
|
||||
GE_ macro n1,n2
|
||||
db 96,n1,n2
|
||||
endm
|
||||
|
||||
EQ_Z_ macro dest ; (=0 n)
|
||||
db 146,dest
|
||||
endm
|
||||
|
||||
LT_Z_ macro dest ; (<0 n)
|
||||
db 147,dest
|
||||
endm
|
||||
|
||||
GT_Z_ macro dest ; (>0 n)
|
||||
db 148,dest
|
||||
endm
|
||||
|
||||
ABS_ macro dest ; (abs n)
|
||||
db 149,dest
|
||||
endm
|
||||
|
||||
FLOOR_ macro dest ; (floor n)
|
||||
db 152,dest
|
||||
endm
|
||||
|
||||
FLOAT_ macro dest ; (float n)
|
||||
db 150,dest
|
||||
endm
|
||||
|
||||
GENSYM_ macro dest ; (gensym sym)
|
||||
db 162,dest
|
||||
endm
|
||||
|
||||
EXPLODE_ macro dest ; (explode sym)
|
||||
db 163,dest
|
||||
endm
|
||||
|
||||
IMPLODE_ macro dest ; (implode list)
|
||||
db 164,dest
|
||||
endm
|
||||
|
||||
LENGTH_ macro dest ; (length list)
|
||||
db 165,dest
|
||||
endm
|
||||
|
||||
LAST_PR_ macro dest ; (last-pair list)
|
||||
db 166,dest
|
||||
endm
|
||||
|
||||
POP_ macro dest
|
||||
db 24,dest
|
||||
endm
|
||||
|
||||
PUSH_ macro dest
|
||||
db 25,dest
|
||||
endm
|
||||
|
||||
DROP_ macro count
|
||||
db 26,count
|
||||
endm
|
||||
|
||||
EXECUTE_ macro code
|
||||
db 58,code
|
||||
endm
|
||||
|
||||
|
||||
EXIT_ macro ; restore (return from call)
|
||||
db 59
|
||||
endm
|
||||
|
||||
APPLY_ macro ftn,arg ; apply funtion to args
|
||||
db 56,ftn,arg
|
||||
endm
|
||||
|
||||
APPLYTR_ macro ftn,arg ; apply funtion to args-tail recursive
|
||||
db 57,ftn,arg
|
||||
endm
|
||||
|
||||
CB_ALLOC_ macro dest ; allocate code block
|
||||
db 172,dest
|
||||
endm
|
||||
|
||||
ST_CONST_ macro src,cb,offset ; store constant
|
||||
db 173,src,cb,offset
|
||||
endm
|
||||
|
||||
ST_BYTE_ macro src,cb,offset ; store code byte
|
||||
db 174,src,cb,offset
|
||||
endm
|
||||
|
||||
OPEN_ macro file,mode ; open I/O port
|
||||
db 176,file,mode
|
||||
endm
|
||||
|
||||
CLOSEP_ macro file ; close I/O port
|
||||
db 177,file
|
||||
endm
|
||||
|
||||
PRIN1_ macro dest,port ; print s-expression
|
||||
db 178,dest,port
|
||||
endm
|
||||
|
||||
PRINC_ macro dest,port ; print s-expression
|
||||
db 179,dest,port
|
||||
endm
|
||||
|
||||
PRINT_ macro dest,port ; print s-expression
|
||||
db 180,dest,port
|
||||
endm
|
||||
|
||||
NEWLINE_ macro port ; print newline
|
||||
db 181,port
|
||||
endm
|
||||
|
||||
READ_ macro dest ; read s-expression
|
||||
db 182,dest
|
||||
endm
|
||||
|
||||
FASL_ macro dest ; fast load
|
||||
db 191,dest
|
||||
endm
|
||||
|
||||
HALT_ macro ; return to MS-DOS
|
||||
db 248
|
||||
endm
|
||||
|
||||
GC_ macro ; garbage collect
|
||||
db 249
|
||||
endm
|
||||
|
||||
PTIME_ macro ; display current time
|
||||
db 250
|
||||
endm
|
||||
|
||||
S_RESET_ macro ; scheme-reset
|
||||
db 252
|
||||
endm
|
||||
|
||||
CLR_REG_ macro ; clear registers
|
||||
db 253
|
||||
endm
|
||||
|
||||
DEBUG_ macro ; begin debug mode
|
||||
db 255
|
||||
endm
|
||||
|
||||
|
|
@ -0,0 +1,512 @@
|
|||
;
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 5 June 1985 *
|
||||
;* Last Modification: 15 May 1986 *
|
||||
;***************************************
|
||||
page 60,132
|
||||
|
||||
MSDOS equ 021h ; MS-DOS service call interrupt
|
||||
FREEMEM equ 049h ; Free memory function identifier
|
||||
MODIFMEM equ 04Ah ; Modify allocated memory function id
|
||||
BIDTASK equ 04Bh ; Load and execute program function id
|
||||
PRSTRING equ 09h
|
||||
CREATE_FL equ 3Ch ; Create file function
|
||||
OPEN_FL equ 3Dh ; Open file function
|
||||
CLOSE_FL equ 3Eh ; Close file function
|
||||
READ_FL equ 3Fh ; Read file function
|
||||
WRITE_FL equ 40h ; Write file function
|
||||
DELETE_FL equ 41h ; Delete file function
|
||||
GET_DRIVE equ 19h ; Current disk function
|
||||
SET_DRIVE equ 0Eh ; Select disk function
|
||||
GET_DIR equ 47h ; Return text of current directory function
|
||||
SET_DIR equ 3Bh ; Change the current directory function
|
||||
TI_CRTINT equ 49h*4 ; CRT dsr interrupt - TI
|
||||
IBM_CRTINT equ 10h*4 ; CRT dsr interrupt - IBM
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
extrn _paras:word ; total number of paragraphs available
|
||||
extrn _psp:dword ; program segment prefix paragraph address
|
||||
; extrn first_pa:word ; seg addr of 1st page in Scheme heap
|
||||
extrn first_dos:word ; seg addr of memory allocated to Scheme heap
|
||||
extrn PC_MAKE:word ; type of machine
|
||||
drive db ? ; place holder for current drive number
|
||||
dir_path db ? ; Drive Letter (as part of the path name)
|
||||
db ":\" ; GET_DIR function doesn't prepend "root"
|
||||
path db 80 dup(?) ; dir path buffer, excluding drive
|
||||
sav_file db "pc__s.sav",00 ; ASCIZ save file pathname
|
||||
len_sav_name equ $-sav_file
|
||||
cmd_ db "COMSPEC="
|
||||
cmd_1 equ $
|
||||
ENVPTR dw 0 ; DOS EXEC parameter block
|
||||
CMDOFF dw 0 ; "
|
||||
CMDSEG dw 0 ; "
|
||||
FCB1OFF dw 5Ch ; "
|
||||
FCB1SEG dw 0 ; "
|
||||
FCB2OFF dw 6Ch ; "
|
||||
FCB2SEG dw 0 ; "
|
||||
data ends
|
||||
|
||||
XGROUP group PROGX
|
||||
PROGX segment byte public 'PROGX'
|
||||
assume CS:XGROUP
|
||||
public install
|
||||
public uninstall
|
||||
|
||||
;************************************************************************
|
||||
;* Bid another Task *
|
||||
;************************************************************************
|
||||
bid_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dd ? ; far return address to caller of bid_task
|
||||
dw ? ; near return address to caller of bid
|
||||
bid_file dw ? ; program's file name
|
||||
bid_parm dw ? ; parameters
|
||||
free_req dw ? ; requested # of free paragraphs
|
||||
bid_args ends
|
||||
|
||||
sav_SP dw 0 ; save area for current stack pointer
|
||||
sav_SS dw 0 ; save area for stack segment register
|
||||
|
||||
;
|
||||
; Paragraph Addresses
|
||||
;
|
||||
; _paras --> +--------------------+ <----
|
||||
; | /|\ | : Freed for bidded task,
|
||||
; | | | : Saved to disk save file
|
||||
; | | -- free_req | : start: _paras - free_req
|
||||
; | | | : length: free_req
|
||||
; | \|/ | : (free_req >= _paras - first_dos)
|
||||
; |~~~~~~~~~~~~~~~~~~~~| <----
|
||||
; | | :
|
||||
; | (heap) | : Allocated to stay resident
|
||||
; | | : # paras: _paras -
|
||||
; first_pa --> +--------------------+ : _psp -
|
||||
; | (unused area) | : free_req
|
||||
; first_dos --> +--------------------+ :
|
||||
; | | :
|
||||
; | (PCS) | :
|
||||
; | | :
|
||||
; | | :
|
||||
; _psp --> +--------------------+ <----
|
||||
; | |
|
||||
;
|
||||
|
||||
close proc near ; Closes the file whose handle is in BX
|
||||
mov AH,CLOSE_FL
|
||||
int MSDOS
|
||||
ret
|
||||
close endp
|
||||
|
||||
delete proc near ; Deletes the save file
|
||||
assume DS:DGROUP
|
||||
mov DX,offset dir_path
|
||||
mov AH,DELETE_FL
|
||||
int MSDOS
|
||||
ret
|
||||
delete endp
|
||||
|
||||
|
||||
bid_task proc far
|
||||
push ES
|
||||
push BP
|
||||
mov BP,SP ; establish local addressability
|
||||
|
||||
; Check if requested # of free paragraphs within bounds
|
||||
cmp [BP].free_req,0 ; default to free max?
|
||||
je free_all ; yes, branch
|
||||
mov AX,_paras ; compute requested base of free area
|
||||
sub AX,[BP].free_req ;
|
||||
jb free_all ; request greater than all memory? branch
|
||||
cmp AX,first_dos ; below base of free-able area?
|
||||
jnb req_ok ; no, ok -- jump
|
||||
free_all: mov AX,_paras ; compute max # of free-able paras
|
||||
sub AX,first_dos ;
|
||||
mov [BP].free_req,AX ; update # of paras to free
|
||||
req_ok:
|
||||
|
||||
; Save Scheme's user memory
|
||||
; First create save file
|
||||
; Save current drive and directory path
|
||||
mov AH,GET_DRIVE ; get current drive number (0=A,1=B,...,4=E)
|
||||
int MSDOS
|
||||
mov drive,AL ; and save it
|
||||
inc AL ; "correct" current drive number
|
||||
mov DL,AL ; put current drive into DL
|
||||
add AL,40h ; (make it a capital letter)
|
||||
mov dir_path,AL ; put the drive letter into dir_path
|
||||
mov SI,offset path ; point DS:SI to path buffer
|
||||
mov AH,GET_DIR ; get current path
|
||||
int MSDOS
|
||||
; Append save file's name to end of directory path
|
||||
find_end: mov BX,offset path ; point to beginning of path name
|
||||
mov CX,64 ; maximum length of path name
|
||||
findloop: cmp byte ptr [BX],0
|
||||
je name_end
|
||||
inc BX
|
||||
loop findloop
|
||||
|
||||
name_end: cmp byte ptr [BX-1],'\' ; was last character a backslash?
|
||||
je add_save ; if so then don't append another one (jump!)
|
||||
mov byte ptr [BX],'\' ; else append a backslash then the filename
|
||||
inc BX
|
||||
add_save: push SI ; Now add concat'nate filename (PC__S.SAV)
|
||||
mov AX,DS
|
||||
mov ES,AX
|
||||
mov DI,BX ; load destination address
|
||||
mov SI,offset sav_file
|
||||
mov CX,len_sav_name
|
||||
rep movsb ; appending the save file name + NULL
|
||||
pop SI
|
||||
|
||||
; Now open the save file...
|
||||
mov DX,offset dir_path ; point DS:DX to ASCIZ save file path
|
||||
mov CX,20h ; file attribute
|
||||
mov AH,CREATE_FL
|
||||
int MSDOS ; do it
|
||||
jnb crt_ok ; branch if create ok
|
||||
jmp exit ; quit now if unable to create save file
|
||||
crt_ok:
|
||||
|
||||
; Now dump memory to the file (file handle in AX)
|
||||
mov BX,AX ; put file handle into BX
|
||||
mov DI,[BP].free_req ; DI = number of paras to write
|
||||
mov AX,_paras ; compute base of area to free
|
||||
sub AX,[BP].free_req ;
|
||||
push DS ; save DS
|
||||
mov DS,AX ; init DS:DX to base of area to save
|
||||
xor DX,DX ;
|
||||
wrt_para: cmp DI,0FFFh ; can write all paras in one shot?
|
||||
jbe wrt_last ; yes, jump
|
||||
sub DI,0FFFh ; dec paras-to-write count
|
||||
mov CX,0FFF0h ; write FFF0 bytes
|
||||
mov AH,WRITE_FL
|
||||
int MSDOS ; do it
|
||||
jb wrt_err ; branch if error
|
||||
cmp AX,CX ; wrote all bytes?
|
||||
je wrt_ok1 ; yes, branch
|
||||
mov AX,20 ; indicate write count error
|
||||
jmp short wrt_err
|
||||
wrt_ok1: mov AX,DS ; inc buffer pointer
|
||||
add AX,0FFFh
|
||||
mov DS,AX
|
||||
jmp wrt_para ; write out next FFF paras
|
||||
wrt_last: mov CL,4 ; shift para count to byte count
|
||||
shl DI,CL
|
||||
mov CX,DI ; put byte count into CX
|
||||
mov AH,WRITE_FL
|
||||
int MSDOS ; do it
|
||||
jb wrt_err ; branch if error
|
||||
cmp AX,CX ; wrote all bytes?
|
||||
je wrt_ok2
|
||||
mov AX,20 ; indicate write count error
|
||||
wrt_err: pop DS ; restore DS
|
||||
push AX ; save error code
|
||||
call close ; close and delete save file
|
||||
call delete
|
||||
pop AX ; restore error code
|
||||
jmp exit ; and quit
|
||||
wrt_ok2: pop DS ; restore DS
|
||||
call close ; close up file for safe keeping
|
||||
jnb wrt_ok3 ; branch if all ok
|
||||
jmp exit ; quit if can't close file
|
||||
wrt_ok3:
|
||||
|
||||
; Free up Scheme's user memory
|
||||
mov ES,first_dos ; point ES to base of allocated area
|
||||
mov BX,_paras ; compute # paras to remain allocated
|
||||
sub BX,first_dos ;
|
||||
sub BX,[BP].free_req ;
|
||||
mov AH,MODIFMEM ; load modify memory function id
|
||||
int MSDOS ; change PCS memory allocation
|
||||
jnc mem_ok
|
||||
memerr: push AX ; save error code
|
||||
call delete ; delete save file
|
||||
pop AX ; restore error code
|
||||
jmp exit ; and quit
|
||||
mem_ok:
|
||||
|
||||
; Bid up specified program
|
||||
; Set up parameter block
|
||||
mov AX,[BP].bid_parm ; Set up dword pointer to command line
|
||||
mov CMDOFF,AX
|
||||
mov CMDSEG,DS
|
||||
|
||||
mov AX,word ptr _psp+2 ; Point to FCBs in program segment prefix
|
||||
mov FCB1SEG,AX
|
||||
mov FCB2SEG,AX
|
||||
|
||||
mov ES,AX
|
||||
mov AX,ES:[02Ch] ; copy current environment ptr to
|
||||
mov ENVPTR,AX ; parameter area
|
||||
|
||||
; Set ES:BX to address of parameter block
|
||||
mov AX,DS
|
||||
mov ES,AX
|
||||
mov BX,offset ENVPTR
|
||||
|
||||
; Set DS:DX to address of ASCIZ pathname (of file to be loaded)
|
||||
push DS ; save DS segment register
|
||||
mov DX,[BP].bid_file
|
||||
mov DI,DX
|
||||
cmp byte ptr [di],0 ; check if pt'ed to string is empty
|
||||
jne bid_it
|
||||
|
||||
; No filename-- bid up a new command interpreter;
|
||||
; have to search environment for COMSPEC= string
|
||||
mov ES,ENVPTR ; ES:DI points to 1st string in environment
|
||||
xor DI,DI
|
||||
|
||||
; Test for end of environment
|
||||
get_plop: cmp byte ptr ES:[DI],0 ; last entry in environment?
|
||||
je cmd_err ; if so, COMSPEC= not found
|
||||
mov SI,offset cmd_ ; load address of comparison string
|
||||
mov CX,cmd_1-cmd_ ; and length of same
|
||||
repe cmps cmd_,ES:[DI] ; does this entry begin "COMSPEC="?
|
||||
je found ; if so, found it! (jump)
|
||||
xor AX,AX ; clear AX for search
|
||||
mov CX,-1 ; set CX for maximum length
|
||||
repne scas byte ptr ES:[DI] ; find \0 which terminates string
|
||||
jmp get_plop ; loop
|
||||
|
||||
; No command interpreter found
|
||||
cmd_err: mov AX,10 ; treat as bad-environment error
|
||||
jmp short bid_err
|
||||
|
||||
; Found COMSPEC=
|
||||
found: mov DX,DI ; DS:DX is ptr to command interpreter
|
||||
push DS ; (swap DS and ES)
|
||||
push ES
|
||||
pop DS
|
||||
pop ES
|
||||
|
||||
; issue load task function call
|
||||
bid_it: push BP ; Old IBM-PCs & XTs destroy BP on func 4B.
|
||||
mov CS:sav_SP,SP ; save current stack pointer
|
||||
mov CS:sav_SS,SS ; save stack segment register
|
||||
xor AL,AL ; load and execute condition
|
||||
mov AH,BIDTASK ; load "load and execute" ftn id
|
||||
int MSDOS ; perform service call
|
||||
cli ; disable all interrupts
|
||||
mov SS,CS:sav_SS ; restore stack base pointer
|
||||
mov SP,CS:sav_SP ; restore stack pointer
|
||||
sti ; enable interrupts
|
||||
pop BP ; restore BP (Thanks IBM) :-(
|
||||
pop DS ; restore DS segment register
|
||||
jb bid_err ; branch if error in bidding task
|
||||
xor AX,AX ; indicate no error
|
||||
bid_err: push AX ; save error code
|
||||
|
||||
; ReAllocate Scheme's user memory
|
||||
mov ES,first_dos ; point ES to base of allocated area
|
||||
mov BX,_paras ; compute # of all available paras
|
||||
sub BX,first_dos ;
|
||||
mov AH,MODIFMEM ; load modify memory function id
|
||||
int MSDOS ; change PCS memory allocation
|
||||
jnc read_mem
|
||||
fatal: pop AX ; throw away bid error code
|
||||
call delete ; delete save file
|
||||
mov AX,0FFFFh ; indicate cannot continue, -1
|
||||
jmp exit
|
||||
|
||||
; Restore Scheme's user memory
|
||||
; First open save file
|
||||
read_mem: mov DX,offset dir_path ; point DS:DX to ASCIZ save file path
|
||||
mov AL,00 ; access code for reading
|
||||
mov AH,OPEN_FL
|
||||
int MSDOS ; do it
|
||||
jb fatal ; abort if cannot open save file
|
||||
|
||||
; Now read memory from the file (file handle in AX)
|
||||
mov BX,AX ; put file handle into BX
|
||||
mov DI,[BP].free_req ; DI = number of paras to read
|
||||
mov AX,_paras ; compute base of area to restore from disk
|
||||
sub AX,[BP].free_req ;
|
||||
push DS ; save DS
|
||||
mov DS,AX ; init DS:DX to base of area to restore
|
||||
xor DX,DX
|
||||
rd_para: cmp DI,0FFFh ; can read all paras in one shot?
|
||||
jbe rd_last ; yes, jump
|
||||
sub DI,0FFFh ; dec paras-to-read count
|
||||
mov CX,0FFF0h ; read FFF0 bytes
|
||||
mov AH,READ_FL
|
||||
int MSDOS ; do it
|
||||
jb read_err ; branch if read error
|
||||
cmp AX,CX ; read all bytes?
|
||||
jne read_err ; no, branch
|
||||
read_ok1: mov AX,DS ; inc buffer pointer
|
||||
add AX,0FFFh
|
||||
mov DS,AX
|
||||
jmp rd_para ; read in next FFF paras
|
||||
rd_last: mov CL,4 ; shift para count to byte count
|
||||
shl DI,CL
|
||||
mov CX,DI ; put byte count into CX
|
||||
mov AH,READ_FL
|
||||
int MSDOS ; do it
|
||||
jb read_err ; branch if error reading file
|
||||
cmp AX,CX ; read all bytes?
|
||||
je read_ok2 ; yes, branch
|
||||
read_err: pop DS ; restore DS
|
||||
call close ; close save file
|
||||
jmp fatal ; and abort
|
||||
read_ok2: pop DS ; restore DS
|
||||
call close ; close save file
|
||||
call delete ; and delete it
|
||||
pop AX ; restore bid error code
|
||||
|
||||
exit: pop BP ; restore caller's BP
|
||||
pop ES ; restore ES segment register
|
||||
ret ; return to caller
|
||||
bid_task endp
|
||||
|
||||
;------------------------------------------------------------------------
|
||||
; The following routines will inhibit text display to the screen for
|
||||
; the duration of the dos-call.
|
||||
;
|
||||
; Note: Programs such as Lotus 1-2-3 which write directly to the
|
||||
; screen memory will still be visible.
|
||||
;
|
||||
;------------------------------------------------------------------------
|
||||
|
||||
exec_args struc
|
||||
dw ? ; caller's BP
|
||||
dd ? ; far return address to caller of install
|
||||
dw ? ; near return address to caller of exec
|
||||
file dw ? ; program's file name
|
||||
parm dw ? ; parameters
|
||||
fre_req dw ? ; requested # of free paragraphs
|
||||
display dw ? ; Indicates if screen should be disturbed
|
||||
exec_args ends
|
||||
|
||||
CRTSAV dd ?
|
||||
CRTINT dw ?
|
||||
DSSAV dw ?
|
||||
INSTALLED dw ?
|
||||
|
||||
install proc far
|
||||
; This routine installs a routine at the CRT DSR interrupt
|
||||
;
|
||||
push bp
|
||||
mov bp,sp
|
||||
push bx
|
||||
mov cs:INSTALLED,0 ; Assume routine won't be installed
|
||||
mov bx,[BP].display ; Indicates if commands will be sent
|
||||
cmp bx,0 ; Screen can be disturbed?
|
||||
pop bx
|
||||
jne non_null ; Install new interrupt routine
|
||||
jmp xinstall ; exit
|
||||
non_null:
|
||||
mov cs:INSTALLED,1
|
||||
push ds
|
||||
push es
|
||||
push ax
|
||||
push bx
|
||||
push dx
|
||||
push si
|
||||
push di
|
||||
mov ax,ds
|
||||
mov cs:DSSAV,ax
|
||||
;
|
||||
; Install new routine at the CRT DSR interrupt
|
||||
;
|
||||
mov ax,0 ; Save off routine adr of CRT DSR
|
||||
mov ds,ax
|
||||
mov si,offset xgroup:CRTSAV
|
||||
mov word ptr cs:[CRTINT],IBM_CRTINT ; Assume its IBM
|
||||
mov es,cs:DSSAV
|
||||
cmp word ptr es:PC_MAKE,1 ; Is it a TI?
|
||||
jne is_IBM
|
||||
mov word ptr cs:[CRTINT],TI_CRTINT
|
||||
is_IBM:
|
||||
mov di,cs:CRTINT
|
||||
mov ax,ds:[di]
|
||||
mov cs:[si],ax
|
||||
mov ax,ds:[di+2]
|
||||
mov cs:[si+2],ax
|
||||
cli ; Clear interrupts
|
||||
mov ax,offset xgroup:crtdsr
|
||||
mov ds:[di],ax
|
||||
mov ds:[di+2],cs
|
||||
sti ; Enable interrupts
|
||||
pop di
|
||||
pop si
|
||||
pop dx
|
||||
pop bx
|
||||
pop ax
|
||||
pop es
|
||||
pop ds
|
||||
xinstall:
|
||||
pop bp
|
||||
ret
|
||||
install endp
|
||||
; **************************************************************************
|
||||
; This routine restores the original routine for the CRT DSR interrupt
|
||||
;
|
||||
uninstall proc far
|
||||
cmp cs:INSTALLED,1 ; Was an int routine installed?
|
||||
je non_null2
|
||||
jmp xuninstall
|
||||
non_null2:
|
||||
push ds
|
||||
push ax
|
||||
push si
|
||||
push di
|
||||
mov ax,0
|
||||
mov ds,ax
|
||||
mov si,offset xgroup:CRTSAV ; Restore CRT DSR routine
|
||||
mov ax,cs:[si]
|
||||
mov di,cs:CRTINT
|
||||
mov ds:[di],ax
|
||||
mov ax,cs:[si+2]
|
||||
mov ds:[di+2],ax
|
||||
pop di
|
||||
pop si
|
||||
pop ax
|
||||
pop ds
|
||||
xuninstall:
|
||||
ret
|
||||
uninstall endp
|
||||
;
|
||||
; This is the do-nothing routine installed at the CRT DSR interrupt
|
||||
;
|
||||
crtproc proc far
|
||||
crtdsr:
|
||||
sti
|
||||
mov ax,0
|
||||
iret
|
||||
crtproc endp
|
||||
|
||||
|
||||
PROGX ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
extrn unfixint:near
|
||||
extrn zcuron:near
|
||||
extrn zcuroff:near
|
||||
extrn fix_intr:near
|
||||
public bid
|
||||
bid proc near
|
||||
call unfixint ; reset shift-break vector
|
||||
call zcuron ; turn the cursor back on
|
||||
call install
|
||||
call bid_task
|
||||
push AX ; save error code
|
||||
call uninstall
|
||||
call zcuroff ; turn the cursor back off
|
||||
call fix_intr ; set shift-break vector
|
||||
pop AX ; restore error code
|
||||
ret
|
||||
bid endp
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,707 @@
|
|||
; =====> SBIGMATH.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Bignum Math Utilities *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: June 1984 *
|
||||
;* Last Modification: 27 May 1986 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
data ends
|
||||
|
||||
XGROUP GROUP PROGX
|
||||
PROGX segment byte public 'PROGX'
|
||||
assume CS:XGROUP,DS:DGROUP
|
||||
|
||||
; Convert a bignum to a flonum
|
||||
; Calling sequence: big2flo(bigptr,floptr)
|
||||
; Where: bigptr ---- pointer to bignum workspace
|
||||
; floptr ---- pointer to flonum
|
||||
b2fargs struc
|
||||
dw ? ;Caller's BP
|
||||
dd ? ;Return address
|
||||
dw ? ;Another return address
|
||||
big dw ? ;Pointer to bignum
|
||||
flo dw ? ;Pointer to flonum
|
||||
b2fargs ends
|
||||
|
||||
%big2flo proc far
|
||||
push BP
|
||||
mov BP,SP
|
||||
cld ;Direction forward
|
||||
mov SI,[BP].big ;Point DS:SI to working bignum
|
||||
mov CX,[SI] ;Get size
|
||||
cmp CX,3
|
||||
ja all64 ;Jump if at least 64 bits
|
||||
add SI,3 ;Point to bignum proper
|
||||
xor BX,BX
|
||||
xor DI,DI
|
||||
lodsw ;Fetch least sig. word
|
||||
mov DX,AX ;Store in DX
|
||||
dec CX
|
||||
jcxz smljust ;Jump if no more bignum words
|
||||
lodsw ;Else get next least sig. word
|
||||
mov DI,AX
|
||||
dec CX
|
||||
jcxz smljust ;Jump if no more bignum words
|
||||
lodsw ;Get 3rd least sig. word
|
||||
mov BX,AX
|
||||
smljust: xor AX,AX ;Clear most sig. word
|
||||
jmp short justify ;Left-justify the number
|
||||
all64: shl CX,1 ;Point SI to 4th most sig. word
|
||||
add SI,CX
|
||||
sub SI,5
|
||||
lodsw ;Load bignum into registers
|
||||
mov DX,AX
|
||||
lodsw
|
||||
mov DI,AX
|
||||
lodsw
|
||||
mov BX,AX
|
||||
lodsw
|
||||
;JUSTIFY: At this stage, the 64 most significant bignum bits are in
|
||||
; AX:BX:DI:DX respectively, AX most significant
|
||||
justify: mov SI,[BP].big ;Fetch pointer to bignum again
|
||||
mov CX,[SI] ;Get size (words)
|
||||
cmp CX,40h
|
||||
ja toobig ;Jump if bignum too big
|
||||
cmp CX,4 ;Skip if not a small bignum
|
||||
jae enough
|
||||
mov CX,4 ;Otherwise, start with constant
|
||||
enough: shl CX,1 ;Multiply by 16 (size in bits)
|
||||
shl CX,1
|
||||
shl CX,1
|
||||
shl CX,1
|
||||
justflp: dec CX ;Reduce exponent
|
||||
shl DX,1 ;Shift bignum left
|
||||
rcl DI,1
|
||||
rcl BX,1
|
||||
rcl AX,1
|
||||
jnc justflp ;Until most significant 1 vanishes
|
||||
add CX,3ffh ;Add flonum exponent constant
|
||||
mov SI,DI ;Now use SI for num, DI for address
|
||||
shftrt: shr CX,1 ;Shift CX:AX:BX:SI:DX as one
|
||||
rcr AX,1
|
||||
rcr BX,1
|
||||
rcr SI,1
|
||||
rcr DX,1
|
||||
cmp CX,80h ;Until most sig. exponent bit is in 2nd
|
||||
jae shftrt ; most sig. bit of CL
|
||||
mov DI,[BP].big ;Get pointer to bignum again
|
||||
test byte ptr[DI]+2,1 ;Negative?
|
||||
jz posskip ;No, skip
|
||||
or CL,80h ;Set sign bit
|
||||
posskip: mov DI,[BP].flo ;Point ES:DI to flonum
|
||||
push AX ;Save part of new flonum
|
||||
mov AL,DH ;Write to flonum space
|
||||
stosb
|
||||
mov AX,SI
|
||||
stosw
|
||||
mov AX,BX
|
||||
stosw
|
||||
pop AX
|
||||
stosw
|
||||
mov AL,CL
|
||||
stosb
|
||||
xor AX,AX ;Return 0 if all well
|
||||
pop BP ;Restore BP
|
||||
ret
|
||||
toobig: mov AX,1 ;Return 1 if conversion impossible
|
||||
pop BP
|
||||
ret
|
||||
%big2flo endp
|
||||
|
||||
; Convert fixnum to bignum
|
||||
; Calling sequence: fix2big(fixnum,bigptr)
|
||||
; Where: fixnum ---- Integer of small absolute value
|
||||
; bigptr ---- Pointer to bignum space
|
||||
f2bargs struc
|
||||
dw ? ;Caller's BP
|
||||
dd ? ;Return address
|
||||
dw ? ;Another return address
|
||||
fix dw ? ;Fixnum
|
||||
bigp dw ? ;Pointer to bignum
|
||||
f2bargs ends
|
||||
|
||||
%fix2big proc far
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov DI,[BP].bigp ;Point ES:DI to bignum
|
||||
mov AX,1 ;Fill size field
|
||||
stosw
|
||||
xor AL,AL ;Clear AL
|
||||
mov BX,[BP].fix ;Fetch fixnum value
|
||||
shl BX,1 ;Put sign bit in AL
|
||||
rcl AL,1
|
||||
stosb ;Fill sign field
|
||||
sar BX,1 ;Restore fixnum
|
||||
or AL,AL ;Negative fixnum?
|
||||
jz posfx ;Skip if positive
|
||||
neg BX ;Otherwise, find absolute value
|
||||
posfx: mov [DI],BX ;Store magnitude of fixnum
|
||||
pop BP ;Restore BP
|
||||
ret
|
||||
%fix2big endp
|
||||
|
||||
;;;; Decrement bignum
|
||||
;;;; Calling sequence: sub1big(buf)
|
||||
;;;; Where: buf ---- pointer to bignum
|
||||
;;;unibig struc
|
||||
;;; dw ? ;Return address
|
||||
;;;bbuf dw ? ;Pointer to working bignum
|
||||
;;;unibig ends
|
||||
;;; public sub1big
|
||||
;;;sub1big proc far
|
||||
;;; mov BX,SP ;Get bignum pointer
|
||||
;;; mov SI,SS:[BX].bbuf
|
||||
;;; test byte ptr[SI]+2,1 ;Is bignum negative?
|
||||
;;; jnz incbig ;If so, increase magnitude
|
||||
;;; jmp short decbig ;Else decrease magnitude
|
||||
;;;sub1big endp
|
||||
|
||||
;;;; Increment bignum
|
||||
;;;; Calling sequence: add1big(buf)
|
||||
;;; public add1big
|
||||
;;;add1big proc far
|
||||
;;; mov BX,SP ;Get bignum pointer
|
||||
;;; mov SI,SS:[BX].bbuf
|
||||
;;; test byte ptr[SI]+2,1 ;Is bignum negative?
|
||||
;;; jnz decbig ;Yes, decrease magnitude
|
||||
;;;;INCBIG increments magnitude of working bignum at DS:SI
|
||||
;;;incbig: mov DI,SI ;Save bignum pointer
|
||||
;;; mov CX,[SI] ;Get length (words)
|
||||
;;; add SI,3 ;Point to bignum proper
|
||||
;;;carrylp: inc word ptr[SI] ;Increment bignum
|
||||
;;; jnz done ;If no carry, finished
|
||||
;;; inc SI ;Else go to next word
|
||||
;;; inc SI
|
||||
;;; loop carrylp ;Loop while not end of bignum
|
||||
;;; mov word ptr[SI],1 ;Else place final 1
|
||||
;;; inc word ptr[DI] ;Lengthen bignum
|
||||
;;;done: ret
|
||||
;;;;DECBIG decrements magnitude of working bignum at DS:SI
|
||||
;;;decbig: mov DI,SI ;Save pointer
|
||||
;;; mov CX,[SI] ;Get length
|
||||
;;; add SI,3 ;Point to bignum proper
|
||||
;;; dec CX ;CX = (length - 1)
|
||||
;;;borrowlp: lodsw ;Load current word
|
||||
;;; sub AX,1 ;Decrement and store
|
||||
;;; mov [SI-2],AX
|
||||
;;; jnc done ;Jump if no borrow
|
||||
;;; loop borrowlp ;Loop if not on last word
|
||||
;;; dec word ptr[SI] ;Else decrement last word
|
||||
;;; jnz done ;Jump if bignum not to be shortened
|
||||
;;; dec word ptr[DI] ;Else shorten
|
||||
;;; ret
|
||||
;;;add1big endp
|
||||
|
||||
; set up big1's index for comparison, used with %magcomp
|
||||
%pbig1 proc near
|
||||
shl CX,1
|
||||
dec SI
|
||||
add SI,CX
|
||||
shr CX,1
|
||||
ret
|
||||
%pbig1 endp
|
||||
|
||||
; set up big1's index for comparison, used with %magcomp
|
||||
%pbig2 proc near
|
||||
shl CX,1
|
||||
dec DI
|
||||
add DI,CX
|
||||
shr CX,1
|
||||
ret
|
||||
%pbig2 endp
|
||||
|
||||
; Compare magnitudes of two bignums
|
||||
; Calling sequence: data = magcomp(big1,big2)
|
||||
; Where: big1,big2 -- pointers to bignum buffers
|
||||
; data ------- a positive integer as follows:
|
||||
; Bit 0 set iff |BIG1| < |BIG2|
|
||||
; Bit 1 set iff |BIG1| > |BIG2|
|
||||
; Bit 2 set iff BIG1 < BIG2
|
||||
; Bit 3 set iff BIG1 > BIG2
|
||||
; Bit 4 set iff BIG1,BIG2 have same sign
|
||||
twobigs struc
|
||||
dd ? ;Return address
|
||||
dw ? ;Another return address
|
||||
big1 dw ? ;First bignum
|
||||
big2 dw ? ;Second bignum
|
||||
twobigs ends
|
||||
|
||||
%magcomp proc far
|
||||
xor AL,AL ;Clear AL
|
||||
xor DX,DX ; clear DX
|
||||
mov BX,SP ;Fetch bignum pointers
|
||||
mov SI,[BX].big1
|
||||
mov DI,[BX].big2
|
||||
mov AH,[SI]+2 ;Get sign bits
|
||||
mov DH,[DI]+2
|
||||
xor DH,AH ;Put XOR of signs into carry
|
||||
shr DH,1
|
||||
jc sgnskp ;Jump if different signs
|
||||
or AL,16 ;Else set proper bit in AL
|
||||
sgnskp: rcl AH,1
|
||||
mov CX,[SI] ;Get BIG1's length
|
||||
mov DX,[DI] ; get BIG2's length
|
||||
cld ;Direction forward
|
||||
cmpsw ;Compare lengths
|
||||
jb bigr2 ;Jump if BIG2 longer
|
||||
ja bigr1 ;Jump if BIG1 longer
|
||||
same_ln: call %pbig1 ;If same size, point SI,DI to last words
|
||||
call %pbig2 ; (most significant)
|
||||
std ;Direction backward
|
||||
repe cmpsw ;Repeat until unequal
|
||||
jb rbig2
|
||||
ja rbig1
|
||||
test AH,1 ;Signs same?
|
||||
jz compend ;Yes, exit
|
||||
difsign: test AH,2 ;Is BIG1 positive?
|
||||
jnz grtr2 ;No, BIG2 is greater
|
||||
jz grtr1 ;Else BIG1 is greater
|
||||
bigr1: call %pbig1
|
||||
cmp word ptr [SI],0 ; check high word,
|
||||
jne rbig1 ; big1 is really bigger
|
||||
mov SI,[BX].big1 ; restore SI
|
||||
inc SI
|
||||
inc SI
|
||||
dec CX ; high order word is empty
|
||||
cmp CX,DX ; compare length's again
|
||||
je same_ln ; same length
|
||||
jmp bigr1 ; repeat until unequal or same lengths
|
||||
|
||||
rbig1: or AL,2 ;Set the |BIG1|>|BIG2| bit
|
||||
test AH,1 ;Signs same?
|
||||
jnz difsign ;No, different signs
|
||||
test AH,2 ;Both positive?
|
||||
jnz grtr2 ;No, so BIG2 is greater
|
||||
grtr1: or AL,8 ;Set the BIG1>BIG2 bit
|
||||
cld ; Set direction forward (JCJ-12/6/84)
|
||||
ret
|
||||
bigr2: push CX
|
||||
mov CX,DX ; swap CX and DX
|
||||
pop DX
|
||||
call %pbig2 ; Set up big2's pointers
|
||||
cmp word ptr [DI],0 ; check high word
|
||||
jne rbig2 ; big2 really is bigger
|
||||
mov DI,[BX].big2 ; restore DI
|
||||
inc DI
|
||||
inc DI
|
||||
dec CX ; high order word is empty
|
||||
cmp DX,CX ; compare length's again
|
||||
je same_ln ;
|
||||
jmp bigr2 ; repeat until unequal or same lengths
|
||||
|
||||
rbig2: or AL,1 ;Set the |BIG1|<|BIG2| bit
|
||||
test AH,1 ;Signs same?
|
||||
jnz difsign ;No, different signs
|
||||
test AH,2 ;Both positive?
|
||||
jnz grtr1 ;No, BIG1 is greater
|
||||
grtr2: or AL,4 ;Set the BIG1<BIG2 bit
|
||||
compend: cld ; Set direction forward (JCJ-12/6/84)
|
||||
ret
|
||||
%magcomp endp
|
||||
|
||||
; Add magnitudes of bignums
|
||||
; Calling sequence: bigadd(big1,big2)
|
||||
; Where: big1 ---- bignum of lesser magnitude
|
||||
; big2 ---- bignum of greater magnitude
|
||||
; When done, BIG2 will hold the sum
|
||||
|
||||
%bigadd proc far
|
||||
mov BX,SP ;Fetch bignum pointers
|
||||
mov SI,[BX].big1
|
||||
mov DI,[BX].big2
|
||||
cld ;Direction forward
|
||||
lodsw ;Get length of smaller bignum
|
||||
mov CX,AX ;Save length
|
||||
sub AX,[DI] ;Find and push difference in lengths
|
||||
neg AX
|
||||
push AX
|
||||
inc SI ;Point SI,DI to bignums proper
|
||||
add DI,3
|
||||
clc ;Prepare to add
|
||||
addlp: lodsw ;Fetch source addend
|
||||
adc [DI],AX ;Add to destination addend
|
||||
inc DI ;Point DI to next word
|
||||
inc DI
|
||||
loop addlp ;Do until smaller bignum exhausted
|
||||
pop CX ;Fetch length difference (CF unchanged)
|
||||
jnc doneadd ;Stop if no carry
|
||||
mov SI,[BX].big2 ;Point SI to destination bignum
|
||||
jcxz samlen ;Jump if bignums the same length
|
||||
adclp: inc word ptr[DI] ;Otherwise, add carry
|
||||
jnz doneadd ;Jump if no resultant carry
|
||||
add DI,2 ;Point DI to next word
|
||||
loop adclp ;Do until whole number is done or no carry
|
||||
samlen: mov word ptr[DI],1 ;Store last carry
|
||||
inc word ptr[SI] ;Note bignum's size increase
|
||||
doneadd: ret
|
||||
%bigadd endp
|
||||
|
||||
; Subtract magnitudes of bignums
|
||||
; Calling sequence: bigsub(big1,big2)
|
||||
; Where: big1 ---- bignum of lesser magnitude
|
||||
; big2 ---- bignum of greater magnitude
|
||||
; When done, BIG2 will hold the difference
|
||||
; When done, BIG2 will hold the sum
|
||||
|
||||
%bigsub proc far
|
||||
mov BX,SP ;Fetch pointers to bignums
|
||||
mov SI,[BX].big1
|
||||
mov DI,[BX].big2
|
||||
cld ;Direction forward
|
||||
lodsw ;Get length of smaller bignum
|
||||
mov CX,AX
|
||||
inc SI ;Point SI,DI to bignums proper
|
||||
add DI,3
|
||||
clc ;Prepare to subtract
|
||||
sublp: lodsw ;Fetch subtrahend
|
||||
sbb [DI],AX ;Subtract
|
||||
inc DI ;Point DI to next word
|
||||
inc DI
|
||||
loop sublp ;Do until smaller bignum exhausted
|
||||
jnc pack ;Jump if no borrow
|
||||
borlp: mov AX,[DI] ;Fetch word
|
||||
sub AX,1 ;Decrement and store
|
||||
stosw
|
||||
jc borlp ;Jump if further borrowing needed
|
||||
pack: mov DI,[BX].big2 ;Fetch pointer to 2nd bignum
|
||||
mov SI,DI ;Save pointer in SI
|
||||
mov AX,[SI] ;Fetch bignum length
|
||||
mov CX,AX ;Save (length-1) in CX
|
||||
dec CX
|
||||
shl AX,1 ;Point DI to last word of bignum
|
||||
inc AX
|
||||
add DI,AX
|
||||
std ;Direction backward
|
||||
xor AX,AX ;Find number of leading 0-words
|
||||
repe scasw ; (not counting least sig. word)
|
||||
jz smlskp ;Jump if only one non-0 word
|
||||
inc CX ;Else, at least 2 non-0 words
|
||||
smlskp: inc CX ;Form (length - # of leading 0-words)
|
||||
mov [SI],CX ;Save in bignum size field
|
||||
cld ;Clear the direction flag
|
||||
ret
|
||||
%bigsub endp
|
||||
|
||||
; Multiply two bignums
|
||||
; Calling sequence: bigmul(big1,big2,big3)
|
||||
; Where: big1,big2 -- factors
|
||||
; big3 ------- destination of product
|
||||
mulargs struc
|
||||
carry dw ? ;Multiplication carry
|
||||
dw ? ;Caller's BP
|
||||
dd ? ;Return address
|
||||
dw ? ;Another return address
|
||||
mbig1 dw ? ;Factor of greater magnitude
|
||||
mbig2 dw ? ;Factor of lesser magnitude
|
||||
mbig3 dw ? ;Product destination
|
||||
mulargs ends
|
||||
; When done, BIG2 will hold the sum
|
||||
|
||||
%bigmul proc far
|
||||
push BP ;Save BP
|
||||
dec SP ;Create space for multiplication carry
|
||||
dec SP
|
||||
mov BP,SP ;Point BP to args
|
||||
cld ;Direction forward
|
||||
mov SI,[BP].mbig1 ;Fetch factor pointers
|
||||
mov DI,[BP].mbig2
|
||||
lodsw ;Fetch BIG1's length
|
||||
mov CX,AX ;Put sum of lengths in CX
|
||||
add CX,[DI]
|
||||
scasw ;Which has greater magnitude?
|
||||
jae xchgskp ;Jump if BIG1 is not smaller
|
||||
xchg DI,SI
|
||||
xchgskp: lodsb ;Fetch one factor's sign
|
||||
xor AL,[DI] ;XOR with the other factor's sign
|
||||
inc DI ;Point DI to bignum proper
|
||||
mov BX,DI ;And store in BX
|
||||
mov DI,[BP].mbig3 ;Store length into product
|
||||
xchg AX,CX
|
||||
stosw
|
||||
push AX ;Save total length of product
|
||||
xchg AX,CX ;Store sign byte into product
|
||||
stosb
|
||||
push DI ;Set product to 0 over whole length
|
||||
xor AX,AX
|
||||
rep stosw
|
||||
pop DI
|
||||
xchg DI,BX ;Restore BX and DI
|
||||
mov CX,[DI]-3 ;Fetch length of BIG2
|
||||
sub BX,SI ;Point [BX+SI-2] to product
|
||||
dec BX
|
||||
dec BX
|
||||
mov [BP].mbig1,SI ;Store pointer to data of BIG1
|
||||
mullp2: push CX ;Save counter of BIG2 words
|
||||
;Add (BIG1*part of BIG2) to current product
|
||||
mov word ptr[BP].carry,0 ;Clear carry in
|
||||
mov SI,[BP].mbig1 ;Fetch bignum pointer
|
||||
mov CX,[SI]-3 ;Get number of words in bignum
|
||||
mullp: lodsw ;Get factor part from BIG1
|
||||
mul word ptr[DI] ;Multiply by factor part from BIG2
|
||||
add AX,[BP].carry ;Add carry in
|
||||
adc DX,0
|
||||
add [BX+SI],AX ;Add product part into BIG3
|
||||
adc DX,0 ;Adjust and store carry
|
||||
mov [BP].carry,DX
|
||||
loop mullp ;Continue for all BIG1
|
||||
mov [BX+SI+2],DX ;Store carry remaining
|
||||
;
|
||||
pop CX ;Restore BIG2 counter
|
||||
inc DI ;Point DI to next word in BIG2
|
||||
inc DI
|
||||
inc BX ;Point BX to next word in BIG3
|
||||
inc BX
|
||||
loop mullp2 ;Continue for all BIG2
|
||||
mov BX,[BP].mbig3 ;Fetch pointer to BIG3 (beginning)
|
||||
pop SI ;Point SI to last word of product
|
||||
shl SI,1
|
||||
inc SI
|
||||
add SI,BX
|
||||
cmp word ptr[SI],0 ;Test last word for zero
|
||||
jnz muldone ;Done if not zero
|
||||
dec word ptr[BX] ;Decrement bignum length
|
||||
muldone: inc SP ;Discard temporary carry variable
|
||||
inc SP
|
||||
pop BP ;Restore BP
|
||||
ret
|
||||
%bigmul endp
|
||||
|
||||
; Divide one bignum by another
|
||||
; Calling sequence: bigdiv(dvdnd,dvsr,quot)
|
||||
; Where: dvdnd ----- dividend
|
||||
; dvsr ------ divisor
|
||||
; quot ------ quotient
|
||||
divargs struc
|
||||
dw ? ;Caller's BP
|
||||
dvsrsz dw ? ;Size of divisor (words)
|
||||
bitcount dw ? ;Estimated bits in quotient
|
||||
align dw ? ;Alignment of dividend to divisor
|
||||
ldvsr dw ? ;Pointer to last word of divisor
|
||||
dd ? ;Return address
|
||||
dw ? ;Another return address
|
||||
dvdnd dw ? ;Dividend
|
||||
dvsr dw ? ;Divisor
|
||||
quot dw ? ;Quotient
|
||||
divargs ends
|
||||
; When done, BIG2 will hold the sum
|
||||
|
||||
%bigdiv proc far
|
||||
sub SP,8 ;Room for local variables
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov DI,[BP].quot ;Get pointers to arguments
|
||||
mov SI,[BP].dvdnd
|
||||
mov BX,[BP].dvsr
|
||||
cld ;Direction forward
|
||||
lodsw ;Get dividend length
|
||||
mov CX,[BX] ;Fetch divisor length
|
||||
cmp CX,1 ;Check divisor for 0
|
||||
jne dvsrok
|
||||
cmp word ptr[BX]+3,0 ;Check divisor data word
|
||||
jnz dvsrok
|
||||
mov AX,CX ;Put nonzero value in AX
|
||||
pop BP
|
||||
add SP,8 ;Restore stack
|
||||
ret ;Exit
|
||||
dvsrok: inc BX ;Point BX+1 to divisor sign
|
||||
mov DX,CX ;Find & store pointer to last divisor word
|
||||
shl DX,1
|
||||
add DX,BX
|
||||
mov [BP].ldvsr,DX
|
||||
sub AX,CX ;Find dividend-divisor length difference
|
||||
mov DX,AX ;Save in DX for now
|
||||
inc AX ;Store maximum quotient length (words)
|
||||
stosw
|
||||
inc CX ;Save length of working divisor
|
||||
mov [BP].dvsrsz,CX
|
||||
dec AX ;Find and store quotient bit count
|
||||
shl AX,1
|
||||
shl AX,1
|
||||
shl AX,1
|
||||
shl AX,1
|
||||
inc AX
|
||||
mov [BP].bitcount,AX
|
||||
lodsb ;Get dividend sign
|
||||
xor AL,[BX]+1 ;Find and store quotient sign
|
||||
stosb
|
||||
mov [BP].dvdnd,SI ;Save pointer to dividend proper
|
||||
mov [BP].quot,DI ;Save pointer to quotient proper
|
||||
xor AX,AX ;Zero first two words of quotient
|
||||
stosw
|
||||
std
|
||||
stosw
|
||||
dec DX ;Account for extra divisor word
|
||||
shl DX,1 ;Store divisor-dividend alignment
|
||||
add DX,SI
|
||||
mov [BP].align,DX
|
||||
mov word ptr[BX],0 ;Put 0-word at start of divisor
|
||||
mov [BP].dvsr,BX ;Save pointer to working divisor
|
||||
bigdivlp: call divcmp ;Dividend less than aligned divisor?
|
||||
jb divbit0 ;Yes, perform division
|
||||
test word ptr[BX],8000h ;Can divisor be shifted left?
|
||||
jnz divbit1 ;No, perform division
|
||||
mov SI,[BP].dvsr ;Otherwise, shift entire divisor left
|
||||
mov CX,[BP].dvsrsz
|
||||
clc ;Start by shifting in 0
|
||||
shllp: rcl word ptr[SI],1 ;Shift through divisor word
|
||||
inc SI ;Point SI to next word
|
||||
inc SI
|
||||
loop shllp ;Do for entire divisor
|
||||
inc [BP].bitcount ;Increase bit count
|
||||
jmp bigdivlp ;See if divisor is big enough yet
|
||||
divlp: call divcmp ;Dividend less than aligned divisor?
|
||||
cld ; (Direction forward)
|
||||
jb divbit0 ;Yes, rotate 0 into quotient
|
||||
mov SI,[BP].align ;Otherwise, subtract divisor
|
||||
mov DI,SI
|
||||
mov BX,[BP].dvsr
|
||||
sub BX,SI
|
||||
dec BX
|
||||
dec BX
|
||||
mov CX,[BP].dvsrsz
|
||||
clc ;No carry in
|
||||
divsublp: lodsw
|
||||
sbb AX,[SI+BX]
|
||||
stosw
|
||||
loop divsublp
|
||||
divbit1: clc ;Clear carry (to rotate 1 in)
|
||||
divbit0: cmc
|
||||
mov SI,[BP].quot ;Fetch pointer to quotient
|
||||
mov CX,[SI]-3 ;Fetch quotient length
|
||||
quotlp: rcl word ptr[SI],1 ;Rotate bit in
|
||||
inc SI
|
||||
inc SI
|
||||
loop quotlp ;Rotate bits through whole quotient
|
||||
dec [BP].bitcount ;Last quotient bit rotated in?
|
||||
jz divdone ;Yes, stop
|
||||
mov SI,[BP].ldvsr ;Otherwise realign divisor (shr)
|
||||
mov CX,[BP].dvsrsz
|
||||
std ;Direction backward
|
||||
cmp word ptr[SI],0 ;Time to shift divisor words?
|
||||
jnz wshftskp ;No, don't bother
|
||||
mov BX,SI ;Save last word pointer
|
||||
mov DX,CX ;Save word count
|
||||
mov DI,SI ;Destination = source+2
|
||||
dec SI
|
||||
dec SI
|
||||
dec CX ;Shift significant divisor words
|
||||
rep movsw
|
||||
xor AX,AX ;Clear least significant word
|
||||
stosw
|
||||
mov SI,BX ;Restore last word pointer
|
||||
mov CX,DX ;Restore count
|
||||
sub [BP].align,2 ;Reset divisor alignment
|
||||
wshftskp: clc ;Shift 0 in
|
||||
shrlp: rcr word ptr[SI],1 ;Shift
|
||||
dec SI
|
||||
dec SI
|
||||
loop shrlp ;Shift entire divisor
|
||||
jmp divlp ;After all this, loop 'til division done
|
||||
divdone: mov BX,[BP].dvdnd ;Fetch dividend pointer
|
||||
mov DI,[BX]-3 ;Fetch former length of dividend
|
||||
dec DI ;Put length-1 in CX
|
||||
mov CX,DI
|
||||
shl DI,1 ;Point DI to last dividend word
|
||||
add DI,BX
|
||||
std ;Direction backward
|
||||
xor AX,AX ;Pack as in BIGSUB
|
||||
repe scasw
|
||||
jz smlskp2
|
||||
inc CX
|
||||
smlskp2: inc CX
|
||||
mov [BX]-3,CX ;Save in bignum size field
|
||||
mov BX,[BP].quot ;Fetch quotient pointer
|
||||
mov DI,[BX]-3 ;Point BX+DI to last quotient word
|
||||
dec DI
|
||||
shl DI,1
|
||||
cmp word ptr[BX+DI],0 ;If last word is 0, decrease length
|
||||
jnz divex
|
||||
dec word ptr[BX]-3
|
||||
divex: pop BP ;Restore stack
|
||||
add SP,8
|
||||
xor AX,AX ;Return 0
|
||||
cld ;Clear direction flag
|
||||
ret
|
||||
%bigdiv endp
|
||||
|
||||
;Compare working divisor to dividend
|
||||
divcmp proc near
|
||||
mov DI,[BP].ldvsr ;Get pointer to last divisor word
|
||||
mov CX,[BP].dvsrsz ;Fetch number of compares to do
|
||||
mov SI,[BP].align ;Get dividend pointer
|
||||
mov AX,CX ;Save # of wrods for pointer adjust
|
||||
cmp SI,[BP].dvdnd ;Dividend longer than divisor?
|
||||
jae adjskp ;Yes, jump
|
||||
dec CX ;Don't compare first divisor word
|
||||
adjskp: dec AX ;Adjust pointer into dividend
|
||||
shl AX,1
|
||||
add SI,AX
|
||||
mov BX,DI ;Save pointer to last divisor byte
|
||||
std ;Direction backward
|
||||
repz cmpsw ;Compare until unequal
|
||||
ret
|
||||
divcmp endp
|
||||
|
||||
PROGX ends
|
||||
|
||||
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
public big2flo
|
||||
big2flo proc near
|
||||
call %big2flo
|
||||
ret
|
||||
big2flo endp
|
||||
|
||||
public fix2big
|
||||
fix2big proc near
|
||||
call %fix2big
|
||||
ret
|
||||
fix2big endp
|
||||
|
||||
public magcomp
|
||||
magcomp proc near
|
||||
call %magcomp
|
||||
ret
|
||||
magcomp endp
|
||||
|
||||
public bigadd
|
||||
bigadd proc near
|
||||
call %bigadd
|
||||
ret
|
||||
bigadd endp
|
||||
|
||||
public bigsub
|
||||
bigsub proc near
|
||||
call %bigsub
|
||||
ret
|
||||
bigsub endp
|
||||
|
||||
public bigmul
|
||||
bigmul proc near
|
||||
call %bigmul
|
||||
ret
|
||||
bigmul endp
|
||||
|
||||
public bigdiv
|
||||
bigdiv proc near
|
||||
call %bigdiv
|
||||
ret
|
||||
bigdiv endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,453 @@
|
|||
; =====> SCANNUM.ASM
|
||||
;****************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Numeric I/O Support *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 12 June 1985 *
|
||||
;* Last Modification: 22 July 1985 *
|
||||
;****************************************
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
public decpoint
|
||||
decpoint db '.'
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
; Classify numeric string ending with a control character
|
||||
; Calling sequence: scannum(s,base)
|
||||
; Where ---- s: pointer to start of character string
|
||||
; base: default base
|
||||
; This function returns 0 if not a number, -1 if a flonum, and n>0
|
||||
; if an integer, where n is the number of digits in the integer.
|
||||
;
|
||||
; NOTE : DS is not guaranteed to point to the local data segment
|
||||
;
|
||||
scanargs struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
sptr dw ? ;Pointer to string
|
||||
scanbase dw ? ;Default base
|
||||
scanargs ends
|
||||
public scannum
|
||||
scannum proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
cld ;Direction forward
|
||||
mov SI,[BP].sptr ;Point DS:SI to characters
|
||||
mov BX,[BP].scanbase ;Set default base
|
||||
xor CX,CX ;Initialize digit count
|
||||
baselp: lodsb ;Fetch first char
|
||||
cmp AL,'#' ;Skip over the base macros
|
||||
jne nomac
|
||||
lodsb ;Get base argument
|
||||
sub AL,40h
|
||||
js nonnum ;If not a base designator, not a number
|
||||
and AL,0dfh ;Shift to upper case
|
||||
xor BL,BL ;Zero current base
|
||||
cmp AL,5 ;Check for #E,#I,#L,#S macros
|
||||
je baselp ; (legal, but don't affect base)
|
||||
cmp AL,9
|
||||
je baselp
|
||||
cmp AL,12
|
||||
je baselp
|
||||
cmp AL,19
|
||||
je baselp
|
||||
cmp AL,2 ;Jump if binary (#B)
|
||||
je bbin
|
||||
cmp AL,4 ;Jump if decimal (#D)
|
||||
je bdec
|
||||
cmp AL,15 ;Jump if octal (#O)
|
||||
je boct
|
||||
cmp AL,24 ;Jump if hexadecimal (#X)
|
||||
je bhex
|
||||
cmp AL,8 ;Jump if not #H (the only legal one left)
|
||||
jne nonnum
|
||||
bhex: mov BL,6
|
||||
bdec: add BL,2
|
||||
boct: add BL,6
|
||||
bbin: add BL,2
|
||||
jmp baselp ;Check for another switch
|
||||
nomac: cmp AL,'+' ;If +, note its presence
|
||||
je wassign
|
||||
cmp AL,'-' ;If not -, skip next char fetch
|
||||
jne notsign
|
||||
wassign: lodsb ;Fetch next char
|
||||
notsign: cmp AL,ss:decpoint ;Decimal point already?
|
||||
je point1 ;Jump if so... must be a flonum
|
||||
call isdg ;Otherwise, there must be a digit
|
||||
jnc nonnum ;If not, not a number
|
||||
wholelp: lodsb ;Else get next character
|
||||
call isdg
|
||||
jc wholelp ;Keep reading digits in whole part
|
||||
cmp AL,32 ;End of string?
|
||||
jb intnum ;Yes, we have an integer
|
||||
cmp AL,ss:decpoint ;Jump on decimal point
|
||||
je point
|
||||
call ismarker ;Jump if exponent marker (E or L valid)
|
||||
je expon
|
||||
nonnum: xor AX,AX ;Return 0, forget all else
|
||||
pop BP
|
||||
ret
|
||||
intnum: mov AX,CX ;Return digit count
|
||||
pop BP
|
||||
ret
|
||||
point1: lodsb ;We must have digit here
|
||||
call isdg
|
||||
jnc nonnum
|
||||
point: lodsb ;Get characters up to non-digit
|
||||
call isdg
|
||||
jc point
|
||||
cmp AL,32 ;If end of string, we have flonum
|
||||
jb flonum
|
||||
call ismarker ;Otherwise, check for exponent marker
|
||||
je expon
|
||||
jne nonnum
|
||||
expon: mov BL,10 ;Exponents are in base 10
|
||||
lodsb ;Get next char
|
||||
cmp AL,'-' ;Valid exponent sign
|
||||
jne edig ;Jump if not signed
|
||||
lodsb ;Else get next char
|
||||
edig: call isdg ;We must end with a nonempty string
|
||||
jnc nonnum ; of base 10 digits
|
||||
exponlp: lodsb
|
||||
call isdg
|
||||
jc exponlp
|
||||
cmp AL,32 ;If not end of string, nonnum
|
||||
jae nonnum
|
||||
flonum: mov AX,-1 ;Return -1 (flonum code)
|
||||
pop BP
|
||||
ret
|
||||
;ISDG: CF is set iff the char in AL is a digit in base BX
|
||||
; Also, if a digit, the digit count in CX is incremented
|
||||
isdg: cmp AL,'0' ;Not if below 0
|
||||
jl nodig
|
||||
cmp AL,'1' ;0 or 1 anytime
|
||||
jbe yesdig
|
||||
cmp BL,2 ;Nothing else for base 2
|
||||
je nodig
|
||||
cmp AL,'7' ;2-7 for base 8,10,16
|
||||
jbe yesdig
|
||||
cmp BL,8 ;Nothing else for base 8
|
||||
je nodig
|
||||
cmp AL,'9' ;8 or 9 for bases 10 or 16
|
||||
jbe yesdig
|
||||
cmp BL,10 ;Nothing else for base 10
|
||||
je nodig
|
||||
and AL,0dfh ;Convert to upper case
|
||||
cmp AL,'A' ;Base 16... Check for A-F
|
||||
jb nodig
|
||||
cmp AL,'F'
|
||||
jbe yesdig
|
||||
nodig: clc
|
||||
ret
|
||||
yesdig: inc CX ;Increment digit count
|
||||
stc
|
||||
ret
|
||||
;ISMARKER: ZF is set iff the character in AL is an exponent marker
|
||||
ismarker: cmp AL,'e'
|
||||
je mark
|
||||
cmp AL,'l'
|
||||
je mark
|
||||
cmp AL,'E'
|
||||
je mark
|
||||
cmp AL,'L'
|
||||
je mark
|
||||
mark: ret
|
||||
scannum endp
|
||||
|
||||
; Check character for digit status in a given base
|
||||
; Calling sequence: isdig(c,base)
|
||||
; Where ---- c: character to check
|
||||
; base: base in which to check
|
||||
isdargs struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
charg dw ? ;Character
|
||||
barg dw ? ;Base
|
||||
isdargs ends
|
||||
public isdig
|
||||
isdig proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov AL,byte ptr[BP].charg ;Fetch character
|
||||
mov BX,[BP].barg ;Fetch base
|
||||
call isdg ;Determine digitness
|
||||
jc wasdg ;Was a digit...don't zero AX
|
||||
xor AX,AX ;Otherwise return 0
|
||||
wasdg: pop BP
|
||||
ret
|
||||
isdig endp
|
||||
|
||||
; Convert digit character to its value
|
||||
; Calling sequence: digval(c)
|
||||
; Where ---- c: assumed to be a digit character
|
||||
digargs struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
carg dw ? ;Character
|
||||
digargs ends
|
||||
public digval
|
||||
digval proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov AL,byte ptr[BP].carg ;Fetch character
|
||||
xor AH,AH
|
||||
and AL,01fh ;Reduce bits
|
||||
cmp AL,16 ;Number or letter?
|
||||
jb hexdig ;Jump if letter
|
||||
and AL,0fh ;Zero the high nibble
|
||||
pop BP
|
||||
ret
|
||||
hexdig: add AL,9 ;Raise the lower nibble
|
||||
pop BP
|
||||
ret
|
||||
digval endp
|
||||
|
||||
; Convert flonum in interval [1.0e15,1.0e16) to bignum
|
||||
; Calling sequence: flo2big(flo,buf)
|
||||
; Where ---- flo: flonum in interval [1e15,1e16)
|
||||
; buf: bignum math buffer, minimum size 11 bytes
|
||||
flo2args struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
num dw ?,?,?,? ;Flonum (4 words)
|
||||
big dw ? ;Pointer to math buffer
|
||||
flo2args ends
|
||||
public flo2big
|
||||
flo2big proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov DI,[BP].big ;Point DI to math buffer
|
||||
cld ;Direction forward
|
||||
mov AX,4 ;Store bignum size (words) in buffer
|
||||
stosw
|
||||
mov AX,[BP+6].num ;Fetch exponent
|
||||
mov CX,AX ;Save exponent in CX
|
||||
rol AX,1 ;Store sign in buffer
|
||||
and AL,1
|
||||
stosb
|
||||
mov AX,CX ;Restore exponent to AX
|
||||
xor CH,CH ;Put (433h-exponent) in CX
|
||||
shr CL,1
|
||||
shr CL,1
|
||||
shr CL,1
|
||||
shr CL,1
|
||||
sub CL,3
|
||||
neg CL
|
||||
and AX,0fh ;Remove exponent from word in AX
|
||||
or AL,10h
|
||||
lea SI,[BP].num ;Point SI to flonum
|
||||
movsw
|
||||
movsw
|
||||
movsw
|
||||
stosw ;Word that used to have exponent
|
||||
sub DI,8 ;Point DI back to start of bignum
|
||||
cmp CL,-1 ;Branch if mantissa to be shifted left
|
||||
je manleft
|
||||
or CL,CL ;Branch if not to be shifted right
|
||||
jz shifted
|
||||
manright: shr word ptr[DI+6],1 ;Shift bignum right
|
||||
rcr word ptr[DI+4],1
|
||||
rcr word ptr[DI+2],1
|
||||
rcr word ptr[DI],1
|
||||
loop manright ;Loop until done
|
||||
jmp short shifted
|
||||
manleft: shl word ptr[DI],1 ;Shift bignum left
|
||||
rcl word ptr[DI+2],1
|
||||
rcl word ptr[DI+4],1
|
||||
rcl word ptr[DI+6],1
|
||||
shifted: pop BP
|
||||
ret
|
||||
flo2big endp
|
||||
|
||||
; Form floating-point ASCII representation from 16 digits and scale
|
||||
; Calling sequence: formflo(digs,chars,scale,prec,exp)
|
||||
; Where ---- digs: the digit characters of the flonum
|
||||
; chars: buffer to store the formed flonum
|
||||
; scale: flonum exponent part
|
||||
; prec: desired precision
|
||||
; exp: whether to use exponential format
|
||||
; Returns the length of the formed flonum string
|
||||
formargs struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
digptr dw ? ;Pointer to digits
|
||||
chrptr dw ? ;Pointer to result string
|
||||
scale dw ? ;Exponent part
|
||||
fprec dw ? ;Precision
|
||||
fexp dw ? ;Exponential format specifier
|
||||
formargs ends
|
||||
public formflo
|
||||
formflo proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov SI,[BP].digptr ;Point SI to digit string
|
||||
mov DI,[BP].chrptr ;Point DI to destination
|
||||
cld ;Direction forward
|
||||
mov DX,[BP].fexp ;Fetch form specifier
|
||||
mov AL,[SI] ;Fetch first digit
|
||||
cmp AL,'0'
|
||||
je toosmall ;Jump if zero
|
||||
cmp AL,'-' ;Negative sign?
|
||||
jne nonsign ;Jump if not signed
|
||||
signed: stosb ;Put sign in return buffer
|
||||
inc [BP].digptr ;Adjust pointer to first digit
|
||||
inc SI
|
||||
nonsign: mov BX,14 ;Round off the last digit
|
||||
call round
|
||||
mov BX,[BP].fprec ;Fetch precision
|
||||
or BX,BX
|
||||
jz putspace ;Jump if arbitrary precision
|
||||
;Determine location at which to begin rounding
|
||||
cmp BX,14 ;If precision out of range, replace
|
||||
jbe precok ; with highest possible
|
||||
mov BX,14
|
||||
precok: or DX,DX
|
||||
jnz doround ;If exponential, round now
|
||||
add BX,[BP].scale ;Add scale to precision
|
||||
jns notsmall ;Jump unless number rounds to 0
|
||||
cmp BX,-1
|
||||
jne toosmall ;Jump if num definitely rounds to 0
|
||||
cmp byte ptr[SI],'5' ;Check sigfig
|
||||
jb toosmall ;Jump if too small
|
||||
mov word ptr[SI],2031h ;Else round up and adjust scale
|
||||
inc [BP].scale
|
||||
jmp short spaced
|
||||
toosmall: mov AL,'0' ;Put (prec+1) 0's at start of input
|
||||
mov BX,[BP].fprec ; buffer
|
||||
toosmlp: mov [SI],AL
|
||||
inc SI
|
||||
dec BL
|
||||
jns toosmlp
|
||||
mov byte ptr[SI],' ' ;Follow by space
|
||||
mov DI,[BP].chrptr ;Start output over (wipe out any sign)
|
||||
jmp short spaced
|
||||
notsmall: cmp BX,16
|
||||
jae spaced ;Jump if no sense in rounding
|
||||
doround: call round ;Round the digits
|
||||
jmp short spaced
|
||||
;For arbitrary precision, change all trailing zeros to spaces
|
||||
; (there exists at least one nonzero digit)
|
||||
putspace: add SI,14 ;Point SI to last digit
|
||||
spacelp: cmp byte ptr[SI],'0'
|
||||
jne spaced
|
||||
and byte ptr[SI],0efh
|
||||
dec SI
|
||||
jmp spacelp
|
||||
;Now the spaces are in - start formatting
|
||||
spaced: mov SI,[BP].digptr ;Point SI to digit string
|
||||
mov BX,[BP].scale ;Fetch scale
|
||||
mov CX,[BP].fprec ;Fetch precision
|
||||
or DX,DX ;If exponent form desired
|
||||
jnz exform ; supply it
|
||||
cmp BX,-14 ;If scale>-15, check precision
|
||||
jge midscale
|
||||
or CL,CL ;If precision arbitrary, force expo-form
|
||||
jz exform
|
||||
midscale: cmp BX,0
|
||||
jl smallfix ;Branch if explicit form called for
|
||||
cmp BX,14
|
||||
jle largefix ;Branch if explicit, but >1
|
||||
;Form an exponential-format flonum
|
||||
exform: movsb ;Transfer first digit
|
||||
mov AL,decpoint ;Place decimal point
|
||||
placex: stosb ;Store character
|
||||
lodsb ;Transfer digits up to first space
|
||||
cmp AL,' '
|
||||
jne placex
|
||||
mov AL,'e' ;Place exponent marker
|
||||
stosb
|
||||
cmp BH,0 ;If scale negative, negate & store sign
|
||||
jge posscale
|
||||
neg BX
|
||||
mov AL,'-'
|
||||
stosb
|
||||
posscale: mov AX,BX ;Move scale to AX
|
||||
mov BH,10 ;Put divisor in BH
|
||||
mov DX,SP ;Save current stack pointer
|
||||
divlpf: div BH ;Divide
|
||||
mov BL,AH ;Push digit
|
||||
add BL,'0'
|
||||
push BX
|
||||
xor AH,AH ;Remove the remainder
|
||||
or AL,AL ;Loop until the quotient is zero
|
||||
jnz divlpf
|
||||
storelp: pop AX ;Restore exponent digit
|
||||
stosb ;Place it
|
||||
cmp SP,DX ;Loop until no more digits left
|
||||
jne storelp
|
||||
jmp short retlen
|
||||
;Form a fixed-decimal flonum magnitude greater than 1
|
||||
largefix: lodsb ;Fetch digit
|
||||
or AL,10h ;Turn ' ' to '0'
|
||||
stosb ;Store digit
|
||||
dec BL ;Loop until all pre-point digs done
|
||||
jns largefix
|
||||
mov AL,decpoint ;Place decimal point
|
||||
stosb
|
||||
digmrg: or CL,CL
|
||||
jnz preclp ;Jump if precision set
|
||||
arblp: lodsb ;Otherwise, arbitrary; do until space
|
||||
cmp AL,' '
|
||||
je retlen
|
||||
stosb
|
||||
jmp arblp
|
||||
llp: stosb
|
||||
preclp: dec CL ;Last digit done?
|
||||
js retlen ;Jump if so
|
||||
dodigs: lodsb ;Now do digits until precision reached
|
||||
cmp AL,' ' ;Space?
|
||||
jne llp ;If not, store it
|
||||
dec SI ;Restore SI
|
||||
mov AL,'0' ;Prepare to place 0
|
||||
jmp llp
|
||||
;Form a fixed-decimal flonum magnitude less than 1
|
||||
smallfix: mov CH,CL ;Copy precision to CH
|
||||
mov AL,'0' ;Place "0."
|
||||
stosb
|
||||
mov AL,decpoint
|
||||
slp: stosb
|
||||
inc BX
|
||||
jz digmrg ;If 0's done, do significant figures
|
||||
or CH,CH ;If precision was zero
|
||||
jz skpprec ; don't bother checking it
|
||||
dec CL
|
||||
js retlen ;If the precision is reached, stop
|
||||
skpprec: mov AL,'0' ;Otherwise, place 0's until scale=0
|
||||
jmp slp
|
||||
;Formation complete
|
||||
retlen: mov AX,DI ;Return length of string
|
||||
sub AX,[BP].chrptr
|
||||
pop BP
|
||||
ret
|
||||
;ROUND: Round the ASCII digits of a flonum, starting at [BX+SI]
|
||||
; SI->start of digits and is unchanged; BX destroyed
|
||||
round: mov AL,' ' ;Get digit after least-rounded and
|
||||
xchg AL,[BX+SI+1] ; replace it with a space
|
||||
cmp AL,'5'
|
||||
jb rounded ;Jump if rounded down
|
||||
roundlp: mov AL,[BX+SI] ;Otherwise, increment digit
|
||||
inc AL
|
||||
mov [BX+SI],AL ;Replace incremented digit
|
||||
cmp AL,'9'
|
||||
jbe rounded ;Jump if no carryover
|
||||
mov byte ptr[BX+SI],'0' ;Else replace digit
|
||||
dec BX ;Go to next digit
|
||||
jns roundlp
|
||||
mov byte ptr[BX+SI+1],'1' ;There are no more digits, place
|
||||
inc [BP].scale ; leading 1 and adjust scale
|
||||
rounded: ret
|
||||
formflo endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,651 @@
|
|||
; =====> SCAR_CDR.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;*Interpreter -- Car and Cdr operations*
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985,1986 by *
|
||||
;* Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 11 September 1984 *
|
||||
;* Last Modification: 26 February 1986*
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
; Modification History:
|
||||
; 26 Feb 86 - modified the "CONS" support to attempt a "short circuit"
|
||||
; (JCJ) allocation of a list cell, instead of calling the
|
||||
; "alloc_list_cell" support unconditionally.
|
||||
|
||||
include sinterp.mac
|
||||
include sinterp.arg
|
||||
|
||||
take_car macro
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne bad_car
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov BL,ES:[SI].car_page
|
||||
mov SI,ES:[SI].car
|
||||
endm
|
||||
|
||||
take_cdr macro
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne bad_cdr
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov BL,ES:[SI].cdr_page
|
||||
mov SI,ES:[SI].cdr
|
||||
endm
|
||||
|
||||
; load arguments for cxr
|
||||
load_arg macro
|
||||
lods word ptr ES:[SI] ; fetch source/destination register numbers
|
||||
save <SI> ; save the location pointer
|
||||
mov BL,AH ; copy the source register number
|
||||
mov SI,reg0_dis+[BX] ; load contents of the source register
|
||||
mov BL,byte ptr reg0_pag+[BX]
|
||||
endm
|
||||
|
||||
car_cdr2 macro arg1,arg2
|
||||
mov CX,offset PGROUP:arg1&_last
|
||||
mov DI,offset PGROUP:arg2&_CX
|
||||
jmp load_ops
|
||||
endm
|
||||
|
||||
car_cdr3 macro arg1,arg2,arg3
|
||||
mov DX,offset PGROUP:arg1&_last
|
||||
mov CX,offset PGROUP:arg2&_DX
|
||||
mov DI,offset PGROUP:arg3&_CX
|
||||
jmp load_ops
|
||||
endm
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
m_car db "CAR",0
|
||||
m_cdr db "CDR",0
|
||||
m_caar db "CAAR",0
|
||||
m_cadr db "CADR",0
|
||||
m_cdar db "CDAR",0
|
||||
m_cddr db "CDDR",0
|
||||
m_caaar db "CAAAR",0
|
||||
m_caadr db "CAADR",0
|
||||
m_cadar db "CADAR",0
|
||||
m_caddr db "CADDR",0
|
||||
m_cdaar db "CDAAR",0
|
||||
m_cdadr db "CDADR",0
|
||||
m_cddar db "CDDAR",0
|
||||
m_cdddr db "CDDDR",0
|
||||
m_cadddr db "CADDDR",0
|
||||
m_%car db "%CAR",0
|
||||
m_%cdr db "%CDR",0
|
||||
|
||||
m_table dw m_car,m_cdr,m_caar,m_cadr,m_cdar,m_cddr,m_caaar,m_caadr
|
||||
dw m_cadar,m_caddr,m_cdaar,m_cdadr,m_cddar,m_cdddr,m_cadddr
|
||||
|
||||
m_setcar db "SET-CAR!",0
|
||||
m_setcdr db "SET-CDR!",0
|
||||
m_apendb db "APPEND!",0
|
||||
m_ltail db "LIST_TAIL",0
|
||||
m_one dw 1 ; a constant "one" (1)
|
||||
m_two dw 2 ; a constant "two" (2)
|
||||
m_three dw 3 ; a constant "three" (3)
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
car_cdr proc near
|
||||
|
||||
; Entry points defined in "sinterp.asm"
|
||||
extrn next:near ; Top of interpreter
|
||||
extrn next_PC:near ; Reload ES,SI at top of interpreter
|
||||
extrn next_SP:near ; Reload SP,ES,SI at top of interpreter
|
||||
extrn src_err:near ; "source operand error" message display
|
||||
extrn sch_err:near ; "source operand error" message display
|
||||
extrn printf_c:near ; Error message print routine
|
||||
|
||||
;************************************************************************
|
||||
;* %car %CAR DEST *
|
||||
;* *
|
||||
;* Purpose: To obtain the first element of a list. This support is *
|
||||
;* similar to the usual "car" operation except that %car *
|
||||
;* returns #!unassigned if one tries to take the car of *
|
||||
;* nil. *
|
||||
;************************************************************************
|
||||
public ld_car1
|
||||
ld_car1: lods byte ptr ES:[SI] ; load operand
|
||||
save <SI> ; save the location pointer
|
||||
mov BX,AX ; copy operand register number to BX
|
||||
mov SI,reg0_dis+[BX] ; load the source operand
|
||||
mov BL,byte ptr reg0_pag+[BX]
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne bad_car1 ; if not a list cell, error (jump)
|
||||
cmp BL,0 ; is source operand nil?
|
||||
jne car_last ; if not nil, jump
|
||||
cxr_undf: mov BX,AX ; reload dest register number
|
||||
mov byte ptr reg0_pag+[BX],UN_PAGE*2 ; set destination reg
|
||||
mov reg0_dis+[BX],UN_DISP ; to #!unassigned
|
||||
jmp next_PC
|
||||
bad_car1: mov AX,offset m_%car
|
||||
jmp bad_one
|
||||
|
||||
;************************************************************************
|
||||
;* %cdr %CDR DEST *
|
||||
;* *
|
||||
;* Purpose: To obtain the rest of a list. This support is similar *
|
||||
;* to the usual "cdr" operation except that %cdr returns *
|
||||
;* #!unassigned if one tries to take the cdr of nil. *
|
||||
;************************************************************************
|
||||
public ld_cdr1
|
||||
ld_cdr1: lods byte ptr ES:[SI] ; load operand
|
||||
save <SI> ; save the location pointer
|
||||
mov BX,AX ; copy operand register number to BX
|
||||
mov SI,reg0_dis+[BX] ; load the source operand
|
||||
mov BL,byte ptr reg0_pag+[BX]
|
||||
cmp BL,0 ; is source operand nil?
|
||||
je cxr_undf ; if nil, return #!unassigned (jump)
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
je cdr_last ; if a list cell, continue processing (jump)
|
||||
jmp bad_cdr1 ; if not a list cell, error (jump)
|
||||
bad_cdr1: mov AX,offset m_%cdr
|
||||
jmp bad_one
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "car" of a list cell LD_CAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_car
|
||||
ld_car: load_arg
|
||||
car_last: cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne bad_car ; if not a list cell, error (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load para addr of page containing cell
|
||||
mov BL,AL ; copy destination register number
|
||||
mov AL,ES:[SI].car_page ; copy contents of car field into
|
||||
mov byte ptr reg0_pag+[BX],AL ; the destination register
|
||||
mov AX,ES:[SI].car
|
||||
mov reg0_dis+[BX],AX
|
||||
jmp next_PC ; return to the interpreter
|
||||
|
||||
car_CX: take_car
|
||||
jmp CX
|
||||
|
||||
car_DX: take_car
|
||||
jmp DX
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cdr" of a list cell LD_CDR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cdr
|
||||
ld_cdr: load_arg
|
||||
cdr_last: cmp byte ptr ptype+[BX],LISTTYPE*2
|
||||
jne bad_cdr ; if not a list cell, error (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load para addr of page containing cell
|
||||
mov BL,AL ; copy destination register number
|
||||
mov AL,ES:[SI].cdr_page ; copy contents of cdr field into
|
||||
mov byte ptr reg0_pag+[BX],AL ; the destination register
|
||||
mov AX,ES:[SI].cdr
|
||||
mov reg0_dis+[BX],AX
|
||||
jmp next_PC ; return to the interpreter
|
||||
|
||||
|
||||
; ***Error-- attempt to take "car" of non- list cell***
|
||||
bad_car:
|
||||
; ***Error-- attempt to take "cdr" of non- list cell***
|
||||
bad_cdr: les SI,dword ptr [BP].save_SI ; load next instruction's address
|
||||
xor BX,BX ; load opcode of failing instruction
|
||||
mov BL,ES:[SI]-3
|
||||
shl BX,1
|
||||
mov AX,m_table+[BX]-128
|
||||
bad_one: les SI,dword ptr [BP].save_SI ; load next instruction's address
|
||||
xor BX,BX
|
||||
mov BL,ES:[SI]-1 ; load register used as last operand
|
||||
add BX,offset reg0
|
||||
pushm <BX,m_one,AX>
|
||||
C_call set_src_,,Load_ES
|
||||
jmp sch_err ; display error message
|
||||
|
||||
cdr_CX: take_cdr
|
||||
jmp CX
|
||||
|
||||
cdr_DX: take_cdr
|
||||
jmp DX
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cadddr" of a list cell LD_CADDDR dest,src *
|
||||
;************************************************************************
|
||||
public ld_caddd
|
||||
ld_caddd: load_arg
|
||||
take_cdr
|
||||
mov DX,offset PGROUP:car_last
|
||||
mov CX,offset PGROUP:cdr_DX
|
||||
jmp cdr_CX
|
||||
|
||||
load_ops: load_arg
|
||||
jmp DI
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "caar" of a list cell LD_CAAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_caar
|
||||
ld_caar: car_cdr2 car,car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cadr" of a list cell LD_CADR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cadr
|
||||
ld_cadr: car_cdr2 car,cdr
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cdar" of a list cell LD_CDAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cdar
|
||||
ld_cdar: car_cdr2 cdr,car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cddr" of a list cell LD_CDDR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cddr
|
||||
ld_cddr: car_cdr2 cdr,cdr
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "caaar" of a list cell LD_CAAAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_caaar
|
||||
ld_caaar: car_cdr3 car,car,car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "caadr" of a list cell LD_CAADR dest,src *
|
||||
;************************************************************************
|
||||
public ld_caadr
|
||||
ld_caadr: car_cdr3 car,car,cdr
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cadar" of a list cell LD_CADAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cadar
|
||||
ld_cadar: car_cdr3 car,cdr,car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "caddr" of a list cell LD_CADDR dest,src *
|
||||
;************************************************************************
|
||||
public ld_caddr
|
||||
ld_caddr: car_cdr3 car,cdr,cdr
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cdaar" of a list cell LD_CDAAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cdaar
|
||||
ld_cdaar: car_cdr3 cdr,car,car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cdadr" of a list cell LD_CDADR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cdadr
|
||||
ld_cdadr: car_cdr3 cdr,car,cdr
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cddar" of a list cell LD_CDDAR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cddar
|
||||
ld_cddar: car_cdr3 cdr,cdr,car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Take "cdddr" of a list cell LD_CDDDR dest,src *
|
||||
;************************************************************************
|
||||
public ld_cdddr
|
||||
ld_cdddr: car_cdr3 cdr,cdr,cdr
|
||||
|
||||
;************************************************************************
|
||||
;* Macro support for set-car!/set-cdr! *
|
||||
;************************************************************************
|
||||
set_cc macro field
|
||||
local x
|
||||
lods word ptr ES:[SI] ; load register numbers
|
||||
mov DX,ES ; save TIPC register ES
|
||||
mov BL,AL
|
||||
mov DI,reg0_pag+[BX] ; load dest register page number
|
||||
cmp DI,0 ; are we trying to set car/cdr of nil?
|
||||
je x ; if (set-cxr nil v), error (jump)
|
||||
cmp byte ptr ptype+[DI],LISTTYPE*2 ; Is destination a list cell?
|
||||
jne x ; If not, set_field! not defined
|
||||
LoadPage ES,DI
|
||||
;;; mov ES,pagetabl+[DI] ; Load paragraph addr for dest page
|
||||
mov DI,reg0_dis+[BX] ; Load destination displacement
|
||||
mov BL,AH ; Copy src register number
|
||||
mov AL,byte ptr reg0_pag+[BX] ; redefine field's page number
|
||||
mov ES:[DI].&field&_page,AL
|
||||
mov AX,reg0_dis+[BX] ; redefine field's displacement
|
||||
mov ES:[DI].&field,AX
|
||||
mov ES,DX ; reload ES segment register
|
||||
jmp next
|
||||
x: mov BX,offset m_set&field ; load address of message text
|
||||
IFIDN <&field>,<car>
|
||||
bad_stcr: mov ES,DX
|
||||
bad_st1: xor AX,AX
|
||||
mov AL,ES:[SI]-1
|
||||
add AX,offset reg0
|
||||
push AX
|
||||
xor AX,AX
|
||||
mov AL,ES:[SI]-2
|
||||
add AX,offset reg0
|
||||
pushm <AX,m_two,BX>
|
||||
C_call set_src_,<SI>,Load_ES
|
||||
restore <SI>
|
||||
jmp sch_err
|
||||
ELSE
|
||||
jmp bad_stcr
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Side effect car field (set-car! dest src) SET-CAR! dest,src *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the set-car! operation. *
|
||||
;************************************************************************
|
||||
public set_car
|
||||
set_car: set_cc car
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Side effect cdr field (set-cdr! dest src) SET-CDR! dest,src *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the set-cdr! operation. *
|
||||
;************************************************************************
|
||||
public set_cdr
|
||||
set_cdr: set_cc cdr
|
||||
|
||||
purge set_cc
|
||||
|
||||
;************************************************************************
|
||||
;* DL DH AL *
|
||||
;* Cons - Create and define new list cell CONS dest,car,cdr *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the Scheme "cons" operation. *
|
||||
;************************************************************************
|
||||
public s_cons
|
||||
s_cons: lods word ptr ES:[SI] ; load destination/car register numbers
|
||||
mov DX,AX ; and save in DX
|
||||
xor AX,AX
|
||||
lods byte ptr ES:[SI] ; load cdr register number
|
||||
save <SI> ; save the location pointer
|
||||
; Attempt a "short circuit" list cell allocation
|
||||
mov DI,listpage
|
||||
;;; cmp DI,END_LIST
|
||||
;;; je cons_no
|
||||
shl DI,1
|
||||
mov SI,nextcell+[DI]
|
||||
cmp SI,END_LIST
|
||||
je cons_no
|
||||
LoadPage ES,DI
|
||||
;;; mov ES,pagetabl+[DI] ; load list cell page's segment address
|
||||
mov CX,ES:[SI].car
|
||||
mov nextcell+[DI],CX
|
||||
; Move contents of CDR register to CDR field of new list cell
|
||||
cons_ok: mov BX,AX ; copy register number to BX
|
||||
mov AL,byte ptr reg0_pag+[BX]
|
||||
mov ES:[SI].cdr_page,AL
|
||||
mov AX,reg0_dis+[BX]
|
||||
mov ES:[SI].cdr,AX
|
||||
; Move contents of CAR register to CAR field of new list cell
|
||||
mov BL,DH ; copy CAR register number to BX
|
||||
mov AL,byte ptr reg0_pag+[BX]
|
||||
mov ES:[SI].car_page,AL
|
||||
mov AX,reg0_dis+[BX]
|
||||
mov ES:[SI].car,AX
|
||||
; Update destination register number with pointer to new list cell
|
||||
mov BL,DL
|
||||
mov reg0_pag+[BX],DI
|
||||
mov reg0_dis+[BX],SI
|
||||
jmp next_SP
|
||||
|
||||
; "short circuit" list cell allocation failed-- go through channels
|
||||
cons_no: push tmp_adr
|
||||
C_call alloc_li,<AX,DX>,Load_ES
|
||||
add SP,WORDINCR
|
||||
restore <AX,DX>
|
||||
mov DI,tmp_page
|
||||
mov SI,tmp_disp
|
||||
LoadPage ES,DI
|
||||
;;; mov ES,pagetabl+[DI]
|
||||
jmp cons_ok
|
||||
|
||||
;************************************************************************
|
||||
;* List - Create and define new list cell w/ nil cdr LIST dest *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the Scheme "list" operation. *
|
||||
;************************************************************************
|
||||
public s_list
|
||||
s_list: lods byte ptr ES:[SI] ; load destination register number
|
||||
mov BX,offset tmp_reg ; load address of temporary register
|
||||
pushm <AX,BX> ; push dest reg number, temp_reg address
|
||||
C_call alloc_li,<SI>,Load_ES ; allocate list cell
|
||||
add SP,WORDINCR ; dump argument from TIPC's stack
|
||||
pop SI ; restore destination register pointer
|
||||
mov BX,tmp_page ; load page number of new list cell
|
||||
mov CX,BX
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load list cell's page table address
|
||||
mov DI,tmp_disp ; load displacement of new list cell
|
||||
; copy car field into newly allocated list cell
|
||||
mov AX,reg0_dis+[SI] ; load car's displacement, and
|
||||
mov ES:[DI].car,AX ; store into new list cell
|
||||
mov AL,byte ptr reg0_pag+[SI] ; load page number, and
|
||||
mov ES:[DI].car_page,AL ; store it, too
|
||||
; create nil cdr field into newly allocated list cell
|
||||
xor AX,AX
|
||||
mov ES:[DI].cdr,AX
|
||||
mov ES:[DI].cdr_page,AL
|
||||
; copy pointer to new list cell into destination register
|
||||
mov byte ptr reg0_pag+[SI],CL
|
||||
mov reg0_dis+[SI],DI
|
||||
jmp next_PC
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (list a b) LIST2 dest,src *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the (list a b) operation. *
|
||||
;* *
|
||||
;* Description: This operation: (list a b) *
|
||||
;* is equivalent to: (cons a (cons b nil)) *
|
||||
;************************************************************************
|
||||
public list2
|
||||
list2: lods word ptr ES:[SI] ; fetch operands
|
||||
mov BL,AL ; save the destination register number
|
||||
push BX
|
||||
mov BL,AH ; copy the source register number
|
||||
add BX,offset reg0 ; compute source register address
|
||||
mov AX,offset nil_reg ; load "nil_reg" address
|
||||
mov CX,offset tmp_reg ; load "tmp_reg" address
|
||||
pushm <AX,BX,CX> ; push arguments to cons
|
||||
C_call cons,<SI>,Load_ES ; call: cons(tmp_reg,src,nil_reg)
|
||||
pop CX ; restore tmp_reg address
|
||||
add SP,WORDINCR*2 ; drop arguments from TIPC's stack
|
||||
pop BX ; restore destination register number
|
||||
add BX,offset reg0 ; compute destination register address
|
||||
pushm <CX,BX,BX> ; push arguments to cons
|
||||
C_call cons ; call: cons(dest, dest, tmp_reg)
|
||||
jmp next_SP ; return to the interpreter
|
||||
|
||||
;************************************************************************
|
||||
;* (append! list obj) append! dest src *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the append! primitive *
|
||||
;************************************************************************
|
||||
public appendb
|
||||
appendb: lods word ptr ES:[SI] ; get args (AL=arg1, AH=arg2)
|
||||
save <SI> ; save the location pntr
|
||||
mov BL,AL
|
||||
lea DI,reg0+[BX] ; DI=address of dest reg
|
||||
mov BX,[DI].C_page ; load list header from dest reg
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; is arg1 a list?
|
||||
jne short not_list ; if not, error (jump)
|
||||
;
|
||||
cmp BL,NIL_PAGE*2 ; is arg1 == nil?
|
||||
jne short find_end ; if not, continue (jump)
|
||||
;
|
||||
mov BL,AH ; else get 2nd arg & return it in dest reg
|
||||
lea SI,reg0+[BX] ; SI=address of src reg
|
||||
mov BX,[SI].C_page ; Copy src reg to dest reg
|
||||
mov [DI].C_page,BX
|
||||
mov BX,[SI].C_disp
|
||||
mov [DI].C_disp,BX
|
||||
jmp next_PC ; RETURN
|
||||
;
|
||||
find_end label near
|
||||
mov CX,SB_CHECK ; load shift-break iteration count
|
||||
mov DI,[DI].C_disp
|
||||
next_cell label near
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load list cell page para address
|
||||
mov BL,ES:[DI].cdr_page ; load list cell's cdr's page
|
||||
cmp BL,NIL_PAGE*2 ; CDR == nil?
|
||||
je short eolist ; then end-of-list (jump)
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; still pointing to cons nodes?
|
||||
jne short weird_lst
|
||||
mov DI,ES:[DI].cdr ; load list cell's cdr's displacement
|
||||
loop next_cell
|
||||
; Every one in awhile, check for shift-break
|
||||
mov CX,SB_CHECK ; reload the shift-break iteration count
|
||||
cmp s_break,0 ; has the shift-break key been depressed?
|
||||
je next_cell ; if no shift-break, jump
|
||||
push m_three ; push instruction length = 3
|
||||
C_call restart ; link to Scheme debugger
|
||||
; Note: control does not return from "restart"
|
||||
;
|
||||
weird_lst label near ; possible error checking here
|
||||
; as list was non-nil terminated
|
||||
eolist label near
|
||||
mov BL,AH ; else get 2nd arg & return it in dest reg
|
||||
lea SI,reg0+[BX] ; SI=address of src reg
|
||||
mov BX,[SI].C_page ; Copy src reg to dest reg
|
||||
; check page # for src?
|
||||
mov ES:[DI].cdr_page,BL
|
||||
mov BX,[SI].C_disp
|
||||
mov ES:[DI].cdr,bx
|
||||
jmp next_PC ; return to interpreter
|
||||
|
||||
not_list label near
|
||||
mov BX,offset m_apendb
|
||||
jmp bad_st1
|
||||
|
||||
;************************************************************************
|
||||
;* (list_tail list count) l_tail list(dest) count *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the list_tail primitive *
|
||||
;************************************************************************
|
||||
|
||||
lt_args struc
|
||||
COUNT dw ? ; Long integer count of list element
|
||||
dw ?
|
||||
REGSAVE dw ?
|
||||
BP_SAVE dw ? ; Saved base pointer
|
||||
ES_SAVE dw ? ; Saved ES reg
|
||||
lt_args ends
|
||||
|
||||
public l_tail
|
||||
l_tail:
|
||||
lods word ptr ES:[SI] ; get register operands
|
||||
save <SI> ; save instruction pointer
|
||||
|
||||
push ES ; save local registers
|
||||
push BP
|
||||
sub SP,offset BP_SAVE ; allocate local storage
|
||||
mov BP,SP
|
||||
|
||||
xor BH,BH
|
||||
mov BL,AL
|
||||
add BX,offset reg0 ; reg holding list ptr
|
||||
mov [BP].REGSAVE,BX ; save for later
|
||||
|
||||
xor BH,BH
|
||||
mov BL,AH
|
||||
add BX,offset reg0 ; get register containing count
|
||||
push BX ; and push for call
|
||||
lea BX,[BP+COUNT] ; get location for return value
|
||||
push BX ; and push for call
|
||||
mov DX,DS
|
||||
mov ES,DX ; set ES for C routine
|
||||
C_call int2long ; convert register to long
|
||||
mov SP,BP
|
||||
or ax,ax
|
||||
jnz lt_err ; jump on error
|
||||
mov ax,[BP].COUNT+2 ; get high word of long integer
|
||||
or ax,ax ; if negative
|
||||
js lt_rtn ; return
|
||||
|
||||
mov SI,[BP].REGSAVE ; reg holding list ptr
|
||||
mov BX,[SI].C_page ; BX <= page of list
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; is it a list ?
|
||||
jne lt_err ; no, jump
|
||||
|
||||
mov AX,BX ; AX <= page of list
|
||||
mov BX,[SI].C_disp ; BX <= disp of list
|
||||
|
||||
lt_loop:
|
||||
mov CX,[BP].COUNT+2 ; get lsw of long int
|
||||
or CX,[BP].COUNT
|
||||
jz lt_rtn ; jump if long int = zero
|
||||
cmp AX,NIL_PAGE ; end of list?
|
||||
je lt_rtn ; yes, return
|
||||
LoadPage ES,AX ; ES <= page address of list cell
|
||||
mov AL,ES:[BX].cdr_page ; AX <= page # of cdr
|
||||
mov BX,ES:[BX].cdr ; BX <= disp of cdr
|
||||
sub word ptr [BP].COUNT,1 ; decrement count
|
||||
sbb word ptr [BP].COUNT+2,0
|
||||
jmp lt_loop ; and loop
|
||||
lt_rtn:
|
||||
mov byte ptr [SI].C_page,AL ; save page in reg
|
||||
mov [SI].C_disp,BX ; save disp in reg
|
||||
add SP,BP_SAVE
|
||||
pop BP
|
||||
pop ES
|
||||
jmp next_SP
|
||||
|
||||
lt_err:
|
||||
add SP,BP_SAVE
|
||||
pop BP
|
||||
pop ES ; restore ES register
|
||||
restore <SI> ; and instruction pointer
|
||||
xor AX,AX
|
||||
mov AL,ES:[SI]-1
|
||||
add AX,offset reg0 ; get last operand
|
||||
push AX ; and push for call
|
||||
xor AX,AX
|
||||
mov AL,ES:[SI]-2
|
||||
add AX,offset reg0 ; get first operand
|
||||
push AX ; and push for call
|
||||
|
||||
mov BX,offset m_ltail ; load address of message text
|
||||
pushm <m_two,BX> ; and push
|
||||
C_call set_src_,<SI>,Load_ES
|
||||
restore <SI>
|
||||
jmp sch_err
|
||||
|
||||
|
||||
car_cdr endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/************************************************************************/
|
||||
/* Scheme Special Character Declarations */
|
||||
/* */
|
||||
/* Copyright 1985 by Texas Instruments Incorporated. */
|
||||
/* All Rights Reserved. */
|
||||
/************************************************************************/
|
||||
#define test_num 8 /* the number of "special" characters */
|
||||
|
||||
/* Text Representations for Special Characters */
|
||||
static char *test_string[test_num] = {"NEWLINE", "SPACE", "RUBOUT",
|
||||
"PAGE", "TAB", "BACKSPACE",
|
||||
"RETURN", "ESCAPE"};
|
||||
|
||||
/* Values for Special Characters */
|
||||
static char test_char[test_num] = {'\n', ' ', '\177',
|
||||
'\f', '\t', '\b',
|
||||
'\r', '\033'};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
include schemed.equ
|
||||
include schemed.ref
|
||||
include schemed.mac
|
||||
include smmu.mac
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/* =====> SCHEME.H */
|
||||
#include "memtype.h"
|
||||
#include "schmdefs.h"
|
||||
|
|
@ -0,0 +1,607 @@
|
|||
; =====> SCHEMED.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* (C) Copyright 1984,1985,1986 by *
|
||||
;* Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: April 1984 *
|
||||
;* Last Modification: 10 Feb 1987 *
|
||||
;***************************************
|
||||
include schemed.equ
|
||||
include screen.equ
|
||||
; Modification History:
|
||||
; 26 Feb 86 - Modified the initial value of the global variable "listpage"
|
||||
; (JCJ) so that it points to page zero (0) instead of END_LIST. This
|
||||
; causes it to always point to a valid page, thus eliminating
|
||||
; one check for each CONS operation.
|
||||
; rb 5/22/86 - changed debug flag in R2 used as VM starts up;
|
||||
; if none, R2=0 (nil), else R2=Scheme 0 (i.e. tagged fixnum zero)
|
||||
; tc 2/10/87 - Changed page 5 special symbols to for #T instead of #!TRUE
|
||||
; for the R^3 Report.
|
||||
|
||||
;************************************************************************
|
||||
;* Segment Alignment Macro *
|
||||
;* *
|
||||
;* Purpose: This macro causes "define bytes" to be inserted in the *
|
||||
;* current data section to force the data item which *
|
||||
;* follows it to be aligned on a paragraph boundary. *
|
||||
;* *
|
||||
;* Note: For this macro to work, the current data segment must be *
|
||||
;* aligned on a paragraph boundary. This is accomplished *
|
||||
;* through the "para" option of the "segment" assembler *
|
||||
;* directive, e.g., *
|
||||
;* *
|
||||
;* data segment para public 'DATA' *
|
||||
;* *
|
||||
;************************************************************************
|
||||
align macro
|
||||
AL_TMP = $ - AL_start ; get current location
|
||||
AL_TMP = AL_TMP MOD 16 ; isolate low order 4 bits
|
||||
AL_TMP = 16 - AL_TMP ; determine "correction"
|
||||
AL_TMP = AL_TMP MOD 16 ; adjust if already aligned
|
||||
IF AL_TMP
|
||||
db AL_TMP dup (0)
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
DGROUP group data
|
||||
data segment para public 'DATA'
|
||||
assume DS:DGROUP
|
||||
AL_start equ $ ; Start of data segment for align macro
|
||||
|
||||
;;; Page Table - This area of memory holds the table of base
|
||||
;;; (paragraph) addresses for each of the page
|
||||
;;; frames in Scheme's memory system.
|
||||
|
||||
public pagetabl
|
||||
pagetabl label word
|
||||
dw page0 ; page 0 - 'nil or cdr nil
|
||||
dw 0 ; page 1 - characters (immediates)
|
||||
dw 0 ; page 2 - forwarded pointer
|
||||
dw 0 ; page 3 - 15-bit fixnums (immediates)
|
||||
dw page4 ; page 4 - special 32-bit flonums
|
||||
dw page5 ; page 5 - special symbols
|
||||
dw page6 ; page 6 - standard port page
|
||||
dw page7 ; page 7 - code for test programs
|
||||
dw page8 ; page 8 - initial environments
|
||||
; remainder of page table
|
||||
dw NUMPAGES-PreAlloc dup (0)
|
||||
|
||||
; Page Attribute Table - The bits in the following table are
|
||||
; used to indicate the state of each of the pages
|
||||
; in the Scheme memory system. Only one kind of data
|
||||
; object can be stored in a given page, so a single bit
|
||||
; can be used to classify all references to a page.
|
||||
|
||||
public attrib,w_attrib
|
||||
w_attrib equ $ ; Special redefinition for C to use as int
|
||||
attrib dw ATOM+READONLY ; page 0 - 'nil
|
||||
dw ATOM+CHARS+READONLY+NOMEMORY
|
||||
dw NOMEMORY
|
||||
dw ATOM+FIXNUMS+READONLY+NOMEMORY
|
||||
dw ATOM+FLONUMS+READONLY
|
||||
dw ATOM+SYMBOLS+READONLY
|
||||
dw ATOM+PORTS+READONLY
|
||||
dw ATOM+CODE
|
||||
dw ATOM ; Initial Environments
|
||||
dw NUMPAGES-9 dup (NOMEMORY)
|
||||
|
||||
; Next available location table - The following table contains
|
||||
; the offsets of the next available location which
|
||||
; may be allocated in each page. A negative value
|
||||
; indicates that the page is full and that no further
|
||||
; allocation is possible within a page.
|
||||
public nextcell
|
||||
nextcell dw 8 dup (END_LIST)
|
||||
dw env_nxt-page8 ; Environments page
|
||||
dw NUMPAGES-9 dup (END_LIST)
|
||||
|
||||
; Page link table - Pages which contain data objects of the same
|
||||
; type are linked together via the following table.
|
||||
public pagelink
|
||||
pagelink dw NUMPAGES dup (END_LIST)
|
||||
|
||||
; Page type table - This table holds the "type" of each page for
|
||||
; pointer classification purposes. The values in
|
||||
; this table may be used as indicies into branch
|
||||
; tables.
|
||||
public ptype
|
||||
ptype dw LISTTYPE*2 ; Page 0 contains list cells
|
||||
dw CHARTYPE*2 ; Page 1 is for character immediates
|
||||
dw FREETYPE*2 ; Page 2 is for "forwarded pointers"
|
||||
dw FIXTYPE*2 ; Page 3 is for fixnum immediates
|
||||
dw FLOTYPE*2 ; Page 4 contains pre-defined flonums
|
||||
dw SYMTYPE*2 ; Page 5 contains pre-defined symbols
|
||||
dw PORTTYPE*2 ; Page 6 contains standard I/O ports
|
||||
dw CODETYPE*2 ; Page 7 contains test programs
|
||||
dw ENVTYPE*2 ; Page 8 contains environments
|
||||
dw NUMPAGES-9 dup (FREETYPE*2) ; Rest of pages not pre-allocated
|
||||
|
||||
public psize
|
||||
psize dw page0_end-page0 ; Page 0 contains special list cells
|
||||
dw 0 ; Page 1 is a tag for immediate characters
|
||||
dw 0 ; Page 2 reserved for "forwarded pointers"
|
||||
dw 0 ; Page 3 is a tag used for immediate fixnums
|
||||
dw page4_end-page4 ; Page 4 contains pre-defined flonums
|
||||
dw page5_end-page5 ; Page 5 contains pre-defined symbols
|
||||
dw page6_end-page6 ; Page 6 contains standard I/O ports
|
||||
dw page7_end-page7 ; Page 7 contains test programs
|
||||
dw page8_end-page8 ; Page 8 contains environments
|
||||
dw NUMPAGES-9 dup (MIN_PAGESIZE) ; Initialize default page size
|
||||
|
||||
; Table of pages for allocation by type
|
||||
public pagelist,listpage,fixpage,flopage,bigpage,sympage,strpage
|
||||
public vectpage,contpage,clospage,freepage,codepage,refpage,portpage
|
||||
public envpage
|
||||
pagelist equ $
|
||||
listpage dw 0 ; [0] Page number for list cell allocation
|
||||
fixpage dw END_LIST ; [1] Page number for fixnum allocation
|
||||
flopage dw END_LIST ; [2] Page number for flonum allocation
|
||||
bigpage dw END_LIST ; [3] Page number for bignum allocation
|
||||
sympage dw END_LIST ; [4] Page number for symbol allocation
|
||||
strpage dw END_LIST ; [5] Page number for string allocation
|
||||
vectpage dw END_LIST ; [6] Page number for vector allocation
|
||||
contpage dw END_LIST ; [7] Page number for continuation allocation
|
||||
clospage dw END_LIST ; [8] Page number for closure allocation
|
||||
freepage dw END_LIST ; [9] Free page list header
|
||||
codepage dw END_LIST ; [10] Page number for code block allocation
|
||||
refpage dw END_LIST ; [11] Page number for ref cell allocation
|
||||
portpage dw END_LIST ; [12] Page number for port allocation
|
||||
charpage dw END_LIST ; [13] Page number for characters
|
||||
envpage dw ENV_PAGE ; [14] Page for environments
|
||||
|
||||
; Table of page attributes by data object type
|
||||
public pageattr
|
||||
pageattr dw LISTCELL ; [0] List cell attributes
|
||||
dw ATOM+FIXNUMS ; [1] Fixnum attributes
|
||||
dw ATOM+FLONUMS ; [2] Flonum attributes
|
||||
dw ATOM+BIGNUMS ; [3] Bignum attributes
|
||||
dw ATOM+SYMBOLS ; [4] Symbol attributes
|
||||
dw ATOM+STRINGS ; [5] String attributes
|
||||
dw ATOM+VECTORS ; [6] Vector (array) attributes
|
||||
dw ATOM+CONTINU ; [7] Continuation attributes
|
||||
dw ATOM+CLOSURE ; [8] Closure attributes
|
||||
dw 0 ; [9] Free page has no attributes
|
||||
dw ATOM+CODE ; [10] Code block attributes
|
||||
dw ATOM+REFS ; [11] Ref cell attributes
|
||||
dw ATOM+PORTS ; [12] Port attributes
|
||||
dw ATOM+CHARS ; [13] Character attributes
|
||||
dw ATOM ; [14] Environment attributes
|
||||
|
||||
public nextpage,lastpage,nextpara,PAGESIZE
|
||||
nextpage dw 9 ; Next unused page number
|
||||
lastpage dw 9 ; Will hold last page # for ext memory
|
||||
nextpara dw 0 ; Next available paragraph number
|
||||
PAGESIZE dw MIN_PAGESIZE
|
||||
|
||||
; Table of bit settings to "or" in
|
||||
public bitable
|
||||
bitable dw 08000H,04000H,02000H,01000H,00800H,00400H,00200H,00100H
|
||||
dw 00080H,00040H,00020H,00010H,00008H,00004H,00002H,00001H
|
||||
|
||||
public rtn_name
|
||||
rtn_name db "You didn't use the ENTER macro!",0
|
||||
|
||||
; "Registers" for the Scheme Virtual Machine
|
||||
public nil_reg,regs,reg0,reg0_pag,reg0_dis
|
||||
nil_reg dw NIL_DISP
|
||||
dw NIL_PAGE*2
|
||||
|
||||
regs equ $
|
||||
reg0 equ $ ; Virtual register 0 - always nil
|
||||
reg0_dis dw NIL_DISP
|
||||
reg0_pag dw NIL_PAGE*2
|
||||
|
||||
public reg1,reg1_pag,reg1_dis
|
||||
reg1 equ $ ; Virtual register 1
|
||||
reg1_dis dw UN_DISP
|
||||
reg1_pag dw UN_PAGE*2
|
||||
|
||||
rept NUM_REGS-2 ; define the VM's remaining registers
|
||||
dw UN_DISP,UN_PAGE*2
|
||||
endm
|
||||
|
||||
public FNV_reg,FNV_pag,FNV_dis
|
||||
FNV_reg equ $ ; Fluid Environment Pointer
|
||||
FNV_dis dw NIL_DISP
|
||||
FNV_pag dw NIL_PAGE*2
|
||||
|
||||
public GNV_reg,GNV_pag,GNV_dis
|
||||
GNV_reg equ $ ; Global Environment Pointer
|
||||
GNV_dis dw g_env-page8
|
||||
GNV_pag dw ENV_PAGE*2
|
||||
|
||||
public CB_reg,CB_pag,CB_dis
|
||||
CB_reg equ $ ; Code Base Pointer
|
||||
CB_dis dw 0
|
||||
CB_pag dw 14
|
||||
|
||||
public tmp_reg,tmp_page,tmp_disp ; GC'ed temporary register
|
||||
tmp_reg equ $
|
||||
tmp_disp dw NIL_DISP
|
||||
tmp_page dw NIL_PAGE*2
|
||||
public tm2_reg,tm2_page,tm2_disp ; GC'ed temporary register
|
||||
tm2_reg equ $
|
||||
tm2_disp dw NIL_DISP
|
||||
tm2_page dw NIL_PAGE*2
|
||||
public tmp_adr,tm2_adr ; addresses of temporary registers
|
||||
tmp_adr dw tmp_reg
|
||||
tm2_adr dw tm2_reg
|
||||
|
||||
; Transcript File pointer
|
||||
public TRNS_reg,TRNS_pag,TRNS_dis
|
||||
TRNS_reg equ $
|
||||
TRNS_dis dw NIL_DISP
|
||||
TRNS_pag dw NIL_PAGE*2
|
||||
|
||||
; Storage for interned symbol 'quote
|
||||
public QUOTE_PA,QUOTE_DI
|
||||
QUOTE_DI dw NIL_DISP
|
||||
QUOTE_PA dw NIL_PAGE*2
|
||||
|
||||
public CONSOLE_,CON_PAGE,CON_DISP ; 'console interned symbol
|
||||
CONSOLE_ equ $
|
||||
CON_DISP dw NIL_DISP
|
||||
CON_PAGE dw NIL_PAGE*2
|
||||
|
||||
|
||||
public S_pc
|
||||
S_pc dw entry - page7
|
||||
|
||||
; Storage for oblist hash table
|
||||
public hash_pag,hash_dis
|
||||
hash_pag db HT_SIZE dup (0)
|
||||
hash_dis dw HT_SIZE dup (0)
|
||||
|
||||
; Storage for property list hash table
|
||||
public prop_pag,prop_dis
|
||||
prop_pag db HT_SIZE dup (0)
|
||||
prop_dis dw HT_SIZE dup (0)
|
||||
|
||||
; Storage for object hash table
|
||||
public obj_ht
|
||||
obj_ht db OHT_SIZE*3 dup (0)
|
||||
|
||||
|
||||
; Stack storage (stack buffer)
|
||||
public S_stack
|
||||
S_stack db NIL_PAGE*2 ; caller's code base pointer
|
||||
dw NIL_DISP
|
||||
db SPECFIX*2 ; return address displacement
|
||||
dw 0
|
||||
db SPECFIX*2 ; caller's FP
|
||||
dw 0
|
||||
db ENV_PAGE*2 ; current heap environment
|
||||
dw g_env-page8
|
||||
db SPECFIX*2 ; static link
|
||||
dw 0
|
||||
db NIL_PAGE*2 ; closure pointer ('nil means open call)
|
||||
dw NIL_DISP
|
||||
STK_HEAD equ $-S_stack
|
||||
db STKSIZE-STK_HEAD dup (0)
|
||||
|
||||
public TOS,FP,BASE,PREV_reg,PREV_pag,PREV_dis
|
||||
TOS dw STK_HEAD-PTRSIZE ; current top-of-stack pointer
|
||||
FP dw 0 ; current stack frame pointer
|
||||
BASE dw 0 ; stack buffer base
|
||||
|
||||
PREV_reg equ $ ; pointer to previous stack segment
|
||||
PREV_dis dw NIL_DISP
|
||||
PREV_pag dw NIL_PAGE*2
|
||||
|
||||
; State variables for (reset) and (scheme-reset)
|
||||
public FP_save,FNV_save,STL_save,RST_ent,ERR_ent
|
||||
FP_save dw 0 ; save area for nominal stack
|
||||
FNV_save dw NIL_DISP,NIL_PAGE*2 ; fluid enviornment pointer save area
|
||||
STL_save dw NIL_DISP,NIL_PAGE*2 ; scheme-top-level value save area
|
||||
RST_ent dw reset_x - page7 ; entry point for reset code
|
||||
ERR_ent dw err_rtn - page7 ; entry point for error handler invocation
|
||||
|
||||
; Flags for VM Control
|
||||
public PC_MAKE,VM_debug,s_break
|
||||
PC_MAKE dw 1 ; PC's manufacturer flag
|
||||
VM_debug dw 0 ; flag indicating VM_debug mode
|
||||
s_break dw 0 ; flag indicating shift-break key depressed
|
||||
|
||||
; Current port
|
||||
public iooffs,ioseg
|
||||
iooffs dw 0
|
||||
ioseg dw 0
|
||||
|
||||
; Stack pointer for abort
|
||||
public abadr
|
||||
abadr dw 0
|
||||
|
||||
; Special storage for nil
|
||||
align
|
||||
public page0
|
||||
page0 db NIL_PAGE*2 ; Special constant: (cons nil nil)
|
||||
dw NIL_DISP
|
||||
db NIL_PAGE*2
|
||||
dw NIL_DISP
|
||||
page0_end equ $ ; end of Page 0
|
||||
|
||||
; Special 32-bit floating point constants area
|
||||
align
|
||||
public page4
|
||||
page4 db FLOTYPE,00,00,00,00,00,00,0F0H,0BFH ;-1.0
|
||||
db FLOTYPE,00,00,00,00,00,00,00,00 ; 0.0
|
||||
db FLOTYPE,00,00,00,00,00,00,0F0H,03FH ; 1.0
|
||||
page4_end equ $ ; end of Page 4
|
||||
|
||||
; Define symbol constant
|
||||
symbol MACRO str
|
||||
local x,y
|
||||
x db SYMTYPE ; tag
|
||||
dw y-x ; length field
|
||||
db NIL_PAGE*2 ; link field page number - initially null
|
||||
dw NIL_DISP ; link field displacement - initially null
|
||||
db 0 ; hash key - 0 for "special symbols"
|
||||
db str ; character data
|
||||
y equ $
|
||||
endm
|
||||
|
||||
; Special storage for single character symbols
|
||||
align
|
||||
public page5
|
||||
page5 equ $
|
||||
t_symbol equ $
|
||||
symbol "#T" ; #T for #!true for 't for true
|
||||
symbol "#!UNASSIGNED" ; the proverbial undefined value
|
||||
symbol "#!NOT-A-NUMBER" ; undefined result of arithmetic
|
||||
eof_sym equ $
|
||||
symbol "#!EOF" ; end-of-file indicator
|
||||
non_prt equ $
|
||||
symbol "#!UNPRINTABLE" ; value of *the-non-printing-object*
|
||||
|
||||
page5_end equ $ ; end of Page 5
|
||||
|
||||
align
|
||||
public page6
|
||||
page6 equ $
|
||||
|
||||
BUFFSIZE equ 256 ; buffer size
|
||||
|
||||
; Standard Input Port (for now, a file)
|
||||
stdinp db PORTTYPE ; tag=PORT
|
||||
dw stdinp_-stdinp ; length of object in bytes
|
||||
db 0,0,0 ; null pointer
|
||||
dw 03Eh ; flags (r/w,window,open,transcript,binary)
|
||||
dw 0 ; handle (stdin CON)
|
||||
dw 0 ; cursor line
|
||||
dw 0 ; cursor column
|
||||
dw 0 ; upper left line
|
||||
dw 0 ; upper left column
|
||||
dw DEFAULT_NUM_ROWS ; number of lines
|
||||
dw DEFAULT_NUM_COLS ; number of columns
|
||||
dw -1 ; border attributes (none)
|
||||
dw 000FH ; text attributes (white, enable)
|
||||
dw 1 ; window flags (wrap)
|
||||
dw 0 ; current buffer position
|
||||
dw 0 ; current end of buffer
|
||||
db BUFFSIZE dup (0) ; input buffer
|
||||
db "CON" ; pathname
|
||||
stdinp_ equ $
|
||||
|
||||
; The following point object is now used for the pcs-status-window
|
||||
stdoutp db PORTTYPE ; tag=PORT
|
||||
dw stdoutp_-stdoutp ; length of object in bytes
|
||||
db 0,0,0 ; null pointer
|
||||
dw 02Eh ; flags (r/w,window,open,no transcript,bin)
|
||||
dw 1 ; handle (stdout CON)
|
||||
dw 0 ; cursor line
|
||||
dw 0 ; cursor column
|
||||
dw DEFAULT_NUM_ROWS - 1 ; upper left line
|
||||
dw 0 ; upper left column
|
||||
dw 1 ; number of lines
|
||||
dw DEFAULT_NUM_COLS ; number of columns
|
||||
dw -1 ; border attributes (none)
|
||||
dw 001CH ; text attrs (reverse video, green, enable)
|
||||
dw 1 ; window flags (wrap)
|
||||
dw 0 ; current buffer position
|
||||
dw 0 ; current end of buffer
|
||||
db BUFFSIZE dup (0) ; output buffer
|
||||
db "CON" ; pathname
|
||||
stdoutp_ equ $
|
||||
page6_end equ $ ; end of Page 6
|
||||
|
||||
fxn MACRO val
|
||||
db SPECFIX*2
|
||||
dw val
|
||||
endm
|
||||
|
||||
; Environments
|
||||
align
|
||||
public page8
|
||||
ENV_PAGE equ 8
|
||||
page8 equ $
|
||||
; define USER-GLOBAL-ENVIRONMENT
|
||||
g_env db ENVTYPE
|
||||
dw (HT_SIZE*3)+BLK_OVHD+PTRSIZE
|
||||
db 0,0,0 ; parent pointer (there is no parent)
|
||||
db HT_SIZE*3 dup (0)
|
||||
; define USER-INITIAL-ENVIRONMENT
|
||||
u_env db ENVTYPE
|
||||
dw (HT_SIZE*3)+BLK_OVHD+PTRSIZE
|
||||
db ENV_PAGE*2
|
||||
dw g_env-page8
|
||||
db HT_SIZE*3 dup (0)
|
||||
env_nxt equ $
|
||||
;;; dw MIN_PAGESIZE-(env_nxt-page8)
|
||||
;;; db MIN_PAGESIZE-($-page8) dup (0)
|
||||
page8_siz equ (env_nxt-page8)+(1*ENV_SIZE) ;allow room for 1 environment
|
||||
db FREETYPE
|
||||
dw page8_siz-(env_nxt-page8)
|
||||
db page8_siz-($-page8) dup (0)
|
||||
page8_end equ $
|
||||
|
||||
; Assembly area for test programs
|
||||
include sasm.mac
|
||||
align
|
||||
public page7
|
||||
page7 equ $
|
||||
db CODETYPE ; Block header
|
||||
dw firstend-page7
|
||||
db SPECFIX*2 ; Code starting offset
|
||||
dw entry-page7
|
||||
; Constant (pointers) go here
|
||||
cstart equ *
|
||||
CSTL equ 0
|
||||
db 0,0,0 ; "scheme-top-level" symbol goes here
|
||||
CREAD equ 1
|
||||
db 0,0,0 ; "read" symbol goes here
|
||||
CEOF equ 2
|
||||
db 0,0,0 ; interned "eof" symbol goes here
|
||||
CINP equ 3
|
||||
db 0,0,0 ; interned "input-port" symbol goes here
|
||||
COUTP equ 4
|
||||
db 0,0,0 ; interned "output-port" symbol goes here
|
||||
CCONS equ 5
|
||||
db 0,0,0 ; interned "console" symbol goes here
|
||||
CNO_PRT equ 6
|
||||
db 0,0,0 ; interned "*the-non-printing-object*" sym
|
||||
CUGENV equ 7
|
||||
db 0,0,0 ; interned "user-global-environment" sym
|
||||
CUIENV equ 8
|
||||
db 0,0,0 ; interned "user-initial-environment" sym
|
||||
ERR_NAME equ 9
|
||||
db 0,0,0 ; interned "*error-handler*" symbol
|
||||
CWHO equ 10
|
||||
db 0,0,0 ; interned "pcs-status-window"
|
||||
T_ equ 11
|
||||
db 0,0,0 ; interned "t"
|
||||
NIL_ equ 12
|
||||
db 0,0,0 ; interned "nil"
|
||||
ENGINE_ equ 13
|
||||
db 0,0,0 ; interned "PCS-KILL-ENGINE"
|
||||
CEOFX equ 14
|
||||
db SPECSYM*2 ; special non-interned "eof" symbol
|
||||
dw eof_sym-page5
|
||||
CNO_PRTX equ 15
|
||||
db SPECSYM*2 ; special non-interned "#!unprintable" sym
|
||||
dw non_prt-page5
|
||||
CUGENVX equ 16
|
||||
db ENV_PAGE*2 ; pointer to user-global-environment
|
||||
dw g_env-page8
|
||||
CUIENVX equ 17
|
||||
db ENV_PAGE*2 ; pointer to user-initial-environment
|
||||
dw u_env-page8
|
||||
CWHOX equ 18
|
||||
db SPECPOR*2 ; pointer to "who-line" window object
|
||||
dw stdoutp-page6
|
||||
CT_ equ 19
|
||||
db SPECSYM*2 ; pointer to #!true
|
||||
dw t_symbol-page5
|
||||
; Entry point follows
|
||||
entry equ $
|
||||
; STRINGP_ R2 ; second input argument specified?
|
||||
JNIL_S_ R2,no_debug ; if not, don't begin debug (jump)
|
||||
DEBUG_ ; initiate debug mode
|
||||
no_debug equ $
|
||||
|
||||
; define "eof"
|
||||
LD_CON_ R63,CEOFX
|
||||
DEFINE_ R63,CEOF
|
||||
; define "*the-non-printing-object*" to "#!unprintable"
|
||||
LD_CON_ R63,CNO_PRTX
|
||||
DEFINE_ R63,CNO_PRT
|
||||
; define "user-global-environment" to point to said
|
||||
LD_CON_ R63,CUGENVX
|
||||
DEFINE_ R63,CUGENV
|
||||
; define "user-initial-environment" to point to said
|
||||
LD_CON_ R63,CUIENVX
|
||||
DEFINE_ R63,CUIENV
|
||||
; define "who-line"
|
||||
LD_CON_ R63,CWHOX
|
||||
DEFINE_ R63,CWHO
|
||||
; (define t #!true)
|
||||
LD_CON_ R63,CT_
|
||||
DEFINE_ R63,T_
|
||||
; (define nil '())
|
||||
DEFINE_ R0,NIL_
|
||||
; fluid-bind "input-port", "output-port" to 'console
|
||||
LD_CON_ R63,CCONS
|
||||
BIND_FL_ CINP,R63
|
||||
BIND_FL_ COUTP,R63
|
||||
; fluid-bind "scheme-top-level" to nil
|
||||
BIND_FL_ CSTL,R0
|
||||
; establish the default error handler
|
||||
LD_CON_ R63,ERR_NAME
|
||||
CLOSE_ R63,err_dflt,0
|
||||
DEFINE_ R63,ERR_NAME
|
||||
; establish the default PCS-KILL-ENGINE
|
||||
LD_CON_ R63,ENGINE_
|
||||
CLOSE_ R63,ret_dflt,0
|
||||
DEFINE_ R63,ENGINE_
|
||||
|
||||
; check the input parameter to see if it's a filename
|
||||
FASL_ R1 ; fast load first program unit
|
||||
next_rd equ $
|
||||
COPY_ R8,R0
|
||||
FASL_ R8
|
||||
LD_CON_ R9,CEOFX
|
||||
JEQ_S_ R9,R8,end_rd
|
||||
PUSH_ R8 ; save program just read
|
||||
EXECUTE_ R1 ; execute the previously read program
|
||||
POP_ R1 ; restore pointer to most recently read pgm
|
||||
JMP_S_ next_rd ; see if more procedures follow
|
||||
end_rd equ $
|
||||
EXECUTE_ R1 ; Load program-Create the closure
|
||||
COPY_ R2,R1 ; Copy returned value to R2
|
||||
SYMBOLP_ R2 ; Was a symbol returned?
|
||||
JNIL_S_ R2,not_sym ; If not, don't try to look it up
|
||||
COPY_ R2,R1
|
||||
FLUID_P_ R2
|
||||
JNIL_S_ R2,glob_sym
|
||||
LD_FL_R_ R1,R1
|
||||
JMP_S_ not_sym
|
||||
glob_sym equ $
|
||||
LD_GL_R_ R1,R1 ; Look up symbol in global environment
|
||||
not_sym equ $
|
||||
COPY_ R2,R1
|
||||
CLOSURP_ R2
|
||||
JNIL_S_ R2,not_clos
|
||||
CALL_CL_ R1,0 ; Execute the closure
|
||||
not_clos equ $
|
||||
LD_NIL_ R2
|
||||
PRINT_ R1,R2 ; Print the result (if any)
|
||||
|
||||
HALT_
|
||||
|
||||
; Reset Code
|
||||
S_RESET_ ; debugger entry for forced reset
|
||||
reset_x equ $
|
||||
LD_GLOBAL_ R1,ENGINE_ ; call PCS-KILL-ENGINE
|
||||
CALL_CL_ R1,0
|
||||
CLR_REG_ ; clear all registers
|
||||
LD_FLUID_ R1,CSTL ; load value for 'scheme-top-level
|
||||
CALL_CL_ R1,0 ; call said closure
|
||||
JMP_S_ reset_x ; if control returns, reset again
|
||||
|
||||
; Error Handler Invocation
|
||||
err_rtn equ $
|
||||
reg_ctr = R1
|
||||
rept NUM_REGS-1
|
||||
PUSH_ reg_ctr
|
||||
reg_ctr = reg_ctr+4
|
||||
endm
|
||||
LD_GLOBAL_ R1,err_name
|
||||
CALL_CL_ R1,0
|
||||
reg_ctr = (NUM_REGS-1)*4
|
||||
rept NUM_REGS-1
|
||||
POP_ reg_ctr
|
||||
reg_ctr = reg_ctr-4
|
||||
endm
|
||||
EXIT_
|
||||
err_dflt equ $
|
||||
DEBUG_
|
||||
ret_dflt equ $
|
||||
EXIT_
|
||||
|
||||
firstend equ $ ; end of first code block
|
||||
page7_end equ $
|
||||
data ends
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,539 @@
|
|||
; =====> SCHEMED.EQU
|
||||
page 60,132
|
||||
; TIPC Scheme Runtime Data Structure Equates
|
||||
; Copyright 1984,1985 by Texas Instruments Incorporated.
|
||||
; All Rights Reserved.
|
||||
;
|
||||
; Last Update:
|
||||
;
|
||||
; tc 10 Feb 1987 - Modified Page 5 special symbols to reflect #T
|
||||
; per the R^3 Report.
|
||||
|
||||
include memtype.equ
|
||||
|
||||
; The following equates set the limits on the virtual memory (paging)
|
||||
; system:
|
||||
NUMPAGES equ 128 ; Total number of pages
|
||||
DEDPAGES equ 8 ; Number of dedicated pages
|
||||
PreAlloc equ DEDPAGES+1 ; Pre-allocated pages
|
||||
|
||||
PAGEINCR equ 2
|
||||
PAGEMASK equ 000FEH
|
||||
|
||||
PTRMASK equ MIN_PAGESIZE-1
|
||||
|
||||
WORDSIZE equ 16 ; The computer's word size (16 bits/word)
|
||||
WORDINCR equ 2 ; The number of address units per word
|
||||
HT_SIZE equ 211 ; The oblist's hash table size
|
||||
OHT_SIZE equ 17 ; The object hash table's size
|
||||
STKSIZE equ 900 ; Length of Scheme's internal stack (bytes)
|
||||
NUM_REGS equ 64 ; Number of general regs in the Scheme VM
|
||||
SB_CHECK equ 16 ; Iteration count for shift-break checks
|
||||
|
||||
; Page attribute bits
|
||||
ATOM equ 08000H ; 1 = Atomic data
|
||||
LISTCELL equ 04000H ; 1 = List (cons) cells
|
||||
FIXNUMS equ 02000H ; 1 = 16-bit integer data
|
||||
FLONUMS equ 01000H ; 1 = 32-bit floating point data
|
||||
BIGNUMS equ 00800H ; 1 = big integer values
|
||||
SYMBOLS equ 00400H ; 1 = symbols
|
||||
STRINGS equ 00200H ; 1 = strings
|
||||
VECTORS equ 00100H ; 1 = vector (array) storage
|
||||
NOMEMORY equ 00080H ; 1 = no memory allocated
|
||||
READONLY equ 00040H ; 1 = memory is read only (constant)
|
||||
CONTINU equ 00020H ; 1 = continuation object
|
||||
CLOSURE equ 00010H ; 1 = closure object
|
||||
REFS equ 00008H ; 1 = ref cells
|
||||
PORTS equ 00004H ; 1 = I/O ports
|
||||
CODE equ 00002H ; 1 = code block
|
||||
CHARS equ 00001H ; 1 = characters
|
||||
NUMBERS equ FIXNUMS+FLONUMS+BIGNUMS ; number (fixnums, flonums, bignums)
|
||||
|
||||
; Data type equates (classes of data objects)
|
||||
NUMTYPES equ 15 ; Number of data types
|
||||
LISTTYPE equ 0
|
||||
FIXTYPE equ 1
|
||||
FLOTYPE equ 2
|
||||
BIGTYPE equ 3
|
||||
SYMTYPE equ 4
|
||||
STRTYPE equ 5
|
||||
VECTTYPE equ 6
|
||||
CONTTYPE equ 7
|
||||
CLOSTYPE equ 8
|
||||
FREETYPE equ 9
|
||||
CODETYPE equ 10
|
||||
REFTYPE equ 11
|
||||
PORTTYPE equ 12
|
||||
CHARTYPE equ 13
|
||||
ENVTYPE equ 14
|
||||
|
||||
; Data type lengths for fixed length objects
|
||||
BLK_OVHD equ 3 ; size of a block header
|
||||
PTRSIZE equ 3 ; size of a Scheme pointer (3 bytes)
|
||||
FLOSIZE equ 9
|
||||
|
||||
|
||||
; Special pre-allocated pages
|
||||
SPECCHAR equ 1
|
||||
SPECFIX equ 3
|
||||
SPECFLO equ 4
|
||||
SPECSYM equ 5
|
||||
SPECPOR equ 6
|
||||
SPECCODE equ 7
|
||||
|
||||
; Predefined constants
|
||||
T_PAGE equ SPECSYM ; symbol 't' (representing true)
|
||||
T_DISP equ 0000H
|
||||
UN_PAGE equ SPECSYM ; symbol '#!unassigned' (unbound variable)
|
||||
UN_DISP equ 0009H
|
||||
NTN_PAGE equ SPECSYM ; symbol '#!not-a-number'
|
||||
NTN_DISP equ 001CH
|
||||
DIV0_PAGE equ SPECSYM ; symbol for divide by 0
|
||||
DIV0_DISP equ 001CH
|
||||
EOF_PAGE equ SPECSYM ; symbol for '#!EOF
|
||||
EOF_DISP equ 00031H
|
||||
NPR_PAGE equ SPECSYM ; symbol for '#!unprintable'
|
||||
NPR_DISP equ 003DH
|
||||
|
||||
NIL_PAGE equ 0 ; symbol 'nil' (representing itself)
|
||||
NIL_DISP equ 0
|
||||
IN_PAGE equ SPECPOR ; standard input port
|
||||
IN_DISP equ 0
|
||||
OUT_PAGE equ SPECPOR ; standard output port
|
||||
OUT_DISP equ 0
|
||||
WHO_PAGE equ SPECPOR ; "who-line"
|
||||
WHO_DISP equ 0123H
|
||||
|
||||
; End of linked list indicator
|
||||
END_LIST equ 07FFFH
|
||||
|
||||
; Garbage Collector "marked" bit
|
||||
GC_BIT equ 080H
|
||||
NOT_GC_BI equ 07FH
|
||||
|
||||
; Special Characters
|
||||
CR equ 0DH ; ASCII Carriage Return
|
||||
LF equ 0AH ; ASCII Line Feed
|
||||
|
||||
; Numeric operator sub-opcodes
|
||||
ADD_OP equ 0 ; add
|
||||
SUB_OP equ 1 ; subtract
|
||||
MUL_OP equ 2 ; multiply
|
||||
DIV_OP equ 3 ; divide
|
||||
MOD_OP equ 4 ; modulo
|
||||
AND_OP equ 5 ; bitwise-and
|
||||
OR_OP equ 6 ; bitwise-or
|
||||
MINUS_OP equ 7 ; minus
|
||||
EQ_OP equ 8 ; = (equal comparison)
|
||||
NE_OP equ 9 ; <> (not equal comparison)
|
||||
LT_OP equ 10 ; < (less than comparison)
|
||||
GT_OP equ 11 ; > (greater than comparison)
|
||||
LE_OP equ 12 ; <= (less than or equal comparison)
|
||||
GE_OP equ 13 ; >= (greater than or equal comparison)
|
||||
ABS_OP equ 14 ; absolute value
|
||||
QUOT_OP equ 15 ; quotient (integer division)
|
||||
ZERO_OP equ 21 ; zero?
|
||||
POS_OP equ 22 ; positive?
|
||||
NEG_OP equ 23 ; negative?
|
||||
XOR_OP equ 24 ; bitwise-xor
|
||||
|
||||
; Numeric Error Codes
|
||||
REF_GLOBAL_ERROR equ 1 ; reference of unbound global variable
|
||||
SET_GLOBAL_ERROR equ 2 ; SET! error-- global not defined
|
||||
REF_LEXICAL_ERROR equ 3 ; reference of unbound lexical variable
|
||||
SET_LEXICAL_ERROR equ 4 ; SET! error-- lexical variable not defined
|
||||
REF_FLUID_ERROR equ 5 ; reference of unbound fluid variable
|
||||
SET_FLUID_ERROR equ 6 ; SET-FLUID! error-- fluid not bound
|
||||
VECTOR_OFFSET_ERROR equ 7 ; vector index out of range
|
||||
STRING_OFFSET_ERROR equ 8 ; string index out of range
|
||||
SUBSTRING_RANGE_ERROR equ 9 ; invalid substring range
|
||||
INVALID_OPERAND_ERROR equ 10 ; Invalid operand to VM instruction
|
||||
SHIFT_BREAK_CONDITION equ 11 ; SHFT-BRK key was depressed by user
|
||||
NON_PROCEDURE_ERROR equ 12 ; Attempted to call non-procedural object
|
||||
TIMEOUT_CONDITION equ 13 ; Timer interrupt
|
||||
WINDOW_FAULT_CONDITION equ 14 ; Attempt to do I/O to a de-exposed window
|
||||
FLONUM_OVERFLOW_ERROR equ 15 ; Flonum Over/Under-flow
|
||||
ZERO_DIVIDE_ERROR equ 16 ; Division by zero
|
||||
NUMERIC_OPERAND_ERROR equ 17 ; non-numeric operand
|
||||
APPLY_ARG_LIMIT_ERROR equ 18 ; too many arguments for APPLY to handle
|
||||
VECTOR_SIZE_LIMIT_ERROR equ 19 ; attempt to allocate vector which is too big
|
||||
STRING_SIZE_LIMIT_ERROR equ 20 ; attempt to allocate string which is too big
|
||||
IO_ERRORS_START equ 21 ; Errors between 21 and 84 are DOS I/O errors
|
||||
DOS_FATAL_ERROR equ 21 ; Generic fatal I/O error
|
||||
EXTEND_START_ERROR_CODE equ 1 ; Extended error codes from INT 59h
|
||||
EXTEND_END_ERROR_CODE equ 88
|
||||
DISK_FULL_ERROR equ 200 ; Our own home-grown error codes
|
||||
LAST_ERROR equ 200 ; Future errors should start here
|
||||
|
||||
; List Cell
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-------------+-+-+-----+-----------------------+
|
||||
; | car page no.|0|g|0 0 0| car displacement |
|
||||
; +-------------+-+-+-----+-----------------------+
|
||||
; | cdr page no.|0|0 0 0 0| cdr displacement |
|
||||
; +-------------+-+-------+-----------------------+
|
||||
; where g = used during garbage collection
|
||||
listdef struc
|
||||
car_page db ? ; CAR's page number
|
||||
car dw ? ; CAR's displacement
|
||||
cdr_page db ? ; CDR's page number
|
||||
cdr dw ? ; CDR's displacement
|
||||
listdef ends
|
||||
list_gc equ car+1 ; High order bit used by GC
|
||||
LISTSIZE equ size listdef
|
||||
|
||||
|
||||
; Bignum
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+-------------------------------+
|
||||
; |g| type | length in bytes |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | sign | least significant word |
|
||||
; +---------------+--------------------------------
|
||||
; : :
|
||||
; ----------------+-------------------------------+
|
||||
; | most significant word |
|
||||
; ----------------+-------------------------------+
|
||||
; where g = used during garbage collection
|
||||
bigdef struc
|
||||
big_type db BIGTYPE ; tag = bignum
|
||||
big_len dw ? ; length of entire data structure in bytes
|
||||
big_sign db ? ; sign of the bignum
|
||||
big_data dw ? ; data bits, stored with least significant
|
||||
; bits appearing first
|
||||
big_2nd dw ? ; second word of significant bits
|
||||
bigdef ends
|
||||
big_gc equ big_type
|
||||
|
||||
; Flonum
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+---------------+---------------+
|
||||
; |g| type | 64 bit IEEE floating |
|
||||
; +-+-------------+---------------+---------------+
|
||||
; | |
|
||||
; +---------------+---------------+---------------+
|
||||
; | |
|
||||
; +---------------+---------------+---------------+
|
||||
; where g = used during garbage collection
|
||||
flodef struc
|
||||
flo_type db FLOTYPE ; tag = flonum
|
||||
flo_data db 8 dup (?) ; IEEE floating point number
|
||||
flodef ends
|
||||
flo_gc equ flo_type
|
||||
|
||||
; Vector (Array)
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-+-----------+-------------------------------+
|
||||
; |g|b| type | length in bytes |
|
||||
; +-+-+-----------+-------------------------------+
|
||||
; | first data element, second, ...
|
||||
; +------------------------------------------------
|
||||
; : :
|
||||
; ------------------------------------------------+
|
||||
; ..., last data element |
|
||||
; ------------------------------------------------+
|
||||
; where g = used during garbage collection
|
||||
; b = unboxed array (contains no type info)
|
||||
vecdef struc
|
||||
vec_type db VECTTYPE
|
||||
vec_len dw ?
|
||||
vec_page db ?
|
||||
vec_disp dw ?
|
||||
vecdef ends
|
||||
vec_gc equ vec_type
|
||||
vec_data equ vec_page
|
||||
|
||||
; Symbol
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+-------------------------------+
|
||||
; |g| SYMTYPE | length in bytes |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | link page no. | link displacement |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | hash value | characters ...
|
||||
; +---------------+-------------------------------
|
||||
; : :
|
||||
; ------------------------------------------------+
|
||||
; where g = used during garbage collection
|
||||
symdef struc
|
||||
sym_type db SYMTYPE ; tag = symbol
|
||||
sym_len dw ? ; length of symbol structure in bytes
|
||||
sym_page db ? ; link field page number
|
||||
sym_disp dw ? ; link field displacement
|
||||
sym_hkey db ? ; hash key
|
||||
sym_data db ? ; character(s) in symbol
|
||||
symdef ends
|
||||
sym_gc equ sym_type
|
||||
sym_ovhd equ sym_data-sym_type ; # bytes of overhead in symbol object
|
||||
|
||||
; String
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+-------------------------------+
|
||||
; |g| STRTYPE | length in bytes |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | characters ...
|
||||
; +---------------+---------------+----------------
|
||||
; : :
|
||||
; ----------------+---------------+---------------+
|
||||
; where g = used during garbage collection
|
||||
strdef struc
|
||||
str_type db strTYPE ; tag = string
|
||||
str_len dw ? ; length of string structure in bytes
|
||||
str_data db ? ; character(s) in string
|
||||
strdef ends
|
||||
str_gc equ str_type
|
||||
str_ovhd equ str_data-str_type ; # bytes of overhead in string object
|
||||
|
||||
; Closure
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+-------------------------------+
|
||||
; |g| CLOSTYPE | length in bytes |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | Information Operand Pointer |
|
||||
; +---------------+-------------------------------+
|
||||
; | heap page no. | heap environment displacement |
|
||||
; +---------------+-------------------------------+
|
||||
; | CB page no. | CB displacement |
|
||||
; +---------------+-------------------------------+
|
||||
; | SPECFIX*2 | Entry Point Displacement |
|
||||
; +---------------+-------------------------------+
|
||||
; | SPECFIX*2 | Number of Arguments |
|
||||
; +---------------+-------------------------------+
|
||||
; where g = used during garbage collection
|
||||
closdef struc
|
||||
clo_type db CLOSTYPE ; tag = closure
|
||||
clo_len dw ? ; length of closure object in bytes
|
||||
clo_ipag db ? ; information operand page number
|
||||
clo_idis dw ? ; information operand displacement
|
||||
clo_hpag db ? ; heap environment pointer page number
|
||||
clo_hdis dw ? ; heap environment pointer displacement
|
||||
clo_cb_p db ? ; code base page number
|
||||
clo_cb_d dw ? ; code base displacement pointer
|
||||
clo_etag db SPECFIX*2 ; entry point tag = immediate
|
||||
clo_edis dw ? ; entry point displacement
|
||||
clo_atag db SPECFIX*2 ; number of arguments tag = immediate
|
||||
clo_narg dw ? ; number of arguments
|
||||
clo_dbug db ? ; optional debugging information?
|
||||
closdef ends
|
||||
clo_gc equ clo_type ; garbage collection mark bit field
|
||||
CLO_OVHD equ clo_dbug-clo_type ; number of bytes of overhead in a closure
|
||||
|
||||
; Continuation
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+-------------------------------+
|
||||
; |g| CONTTYPE | length in bytes |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | tag=fixnum | stack base of continuation |
|
||||
; +---------------+-------------------------------+
|
||||
; | return address code base pointer |\
|
||||
; +---------------+-------------------------------+ | return address
|
||||
; | tag=fixnum | return address displacement |/
|
||||
; +---------------+-------------------------------+
|
||||
; | tag=fixnum | caller's dynamic link (FP) |
|
||||
; +---------------+-------------------------------+
|
||||
; | fluid environment pointer (FNV_reg) |
|
||||
; +---------------+-------------------------------+
|
||||
; | previous stack segment (continuation) pointer |
|
||||
; +---------------+-------------------------------+
|
||||
; | global environment pointer (GNV_reg) |
|
||||
; +---------------+-------------------------------+
|
||||
; : :< - BASE
|
||||
; : [contents of stack at call/cc] :
|
||||
; : :< - TOS
|
||||
; +-----------------------------------------------+
|
||||
; where g = used during garbage collection
|
||||
contdef struc
|
||||
con_type db CONTTYPE ; tag = continuation
|
||||
con_len dw ? ; length of continuation structure in bytes
|
||||
con_btag db SPECFIX*2 ; stack base of continuation object
|
||||
con_base dw ?
|
||||
con_cb_p db ? ; return address code base pointer
|
||||
con_cb_d dw ?
|
||||
con_rtag db SPECFIX*2 ; return address displacement
|
||||
con_ret dw ?
|
||||
con_dtag db SPECFIX*2 ; caller's dynamic link
|
||||
con_ddis dw ?
|
||||
con_fl_p db ? ; fluid environment pointer
|
||||
con_fl_d dw ?
|
||||
con_spag db ? ; previous stack segment pointer
|
||||
con_sdis dw ?
|
||||
con_gl_p db ? ; global environment pointer
|
||||
con_gl_d dw ?
|
||||
con_data db ? ; contents of stack at call/cc
|
||||
contdef ends
|
||||
con_gc equ con_type
|
||||
|
||||
; Code Block
|
||||
;
|
||||
; +-----------------------------------------------------+
|
||||
; | 2 2 2 2 1 1 1 1 1 1 1 1 1 1 |
|
||||
; | 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
|
||||
; | +-+-------------+-------------------------------+ |
|
||||
; | |g| CODETYPE | length in bytes | |
|
||||
; | +-+-------------+-------------------------------+ |
|
||||
; | | FIXTYPE*2 | entry offset |--+
|
||||
; | +---------------+-------------------------------+
|
||||
; | | page | displacement |\
|
||||
; | +---------------+-------------------------------+ |
|
||||
; | : : : > constants
|
||||
; | +---------------+-------------------------------+ | area
|
||||
; | | page | displacement |/
|
||||
; | +---------------+---------------+---------------+
|
||||
; +->| code | code | code |\
|
||||
; +---------------+---------------+---------------+ |
|
||||
; : : : : > code
|
||||
; +---------------+---------------+---------------+ |
|
||||
; | code | code | code |/
|
||||
; +---------------+---------------+---------------+
|
||||
; where g = used during garbage collection
|
||||
codedef struc
|
||||
cod_type db CODETYPE ; tag = code block
|
||||
cod_len dw ? ; length of code block in bytes
|
||||
cod_etag db FIXTYPE*2 ; entry offset tag = fixnum
|
||||
cod_entr dw ? ; entry offset in bytes
|
||||
cod_cpag db ? ; code block constants area
|
||||
cod_cdis dw ?
|
||||
codedef ends
|
||||
cod_gc equ cod_type ; garbage collection tag field
|
||||
|
||||
; Environment Data Object
|
||||
;
|
||||
; 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
; 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
; +-+-------------+-------------------------------+
|
||||
; |g| type | length in bytes |
|
||||
; +-+-------------+-------------------------------+
|
||||
; | parent pointer |
|
||||
; +---------------+-------------------------------+
|
||||
; | list of symbols (linked through cdr field) |
|
||||
; +---------------+-------------------------------+
|
||||
; | list of values (linked through car field) |
|
||||
; +---------------+-------------------------------+
|
||||
; where g = used during garbage collection
|
||||
envdef struc
|
||||
env_tag db ENVTYPE ; tag = environment
|
||||
env_len dw ? ; length in bytes
|
||||
env_ppag db ? ; parent pointer page number
|
||||
env_pdis dw ? ; parent pointer displacement
|
||||
env_npag db ? ; list of names page number
|
||||
env_ndis dw ? ; list of names displacement
|
||||
env_vpag db ? ; list of values page number
|
||||
env_vdis dw ? ; list of values displacement
|
||||
envdef ends
|
||||
ENV_SIZE equ size envdef
|
||||
|
||||
; Port
|
||||
; +--------+--------+--------+
|
||||
; 0 |tag=port| length in bytes |
|
||||
; +--------+--------+--------+
|
||||
; 3 | string source pointer |
|
||||
; +--------+--------+--------+--------+
|
||||
; 6 | port flags | handle |
|
||||
; +-----------------+-----------------+
|
||||
; 10 | cursor line | cursor column |
|
||||
; +-----------------+-----------------+
|
||||
; 14 | upper left line |upper left column|
|
||||
; +-----------------+-----------------+
|
||||
; 18 | number of lines |number of columns|
|
||||
; +-----------------+-----------------+
|
||||
; 22 |border attributes| text attributes |
|
||||
; +-----------------+-----------------+
|
||||
; 26 | window flags | buffer position |
|
||||
; +-----------------+-----------------+
|
||||
; 30 | buffer end |
|
||||
; +--------+--------+--------+--------+----... -----+
|
||||
; 32 | input/output buffer |
|
||||
; +--------+--------+-----------------+-------...---+
|
||||
; | window label/file pathname |
|
||||
; +--------+--------+-----------------+---------...-+
|
||||
; where g = used during garbage collection
|
||||
;
|
||||
; 7 6 5 4 3 2 1 0
|
||||
; +-+-+-+-+-+-+---+
|
||||
;port flags: | |s|b|t|o|w|mod|
|
||||
; +-+-+-+-+-+-+---+
|
||||
;
|
||||
; mod - mode: 0=read
|
||||
; 1=write
|
||||
; 2=read and write
|
||||
; w - window/file: 0=file
|
||||
; 1=window
|
||||
; o - open/closed: 0=closed
|
||||
; 1=open
|
||||
; t - transcript: 0=disabled
|
||||
; 1=enabled
|
||||
; b - binary: 0=test file/window
|
||||
; 1=binary file/window
|
||||
; s - string I/O: 0=file/window I/O
|
||||
; 1=string I/O
|
||||
;
|
||||
; 7 6 5 4 3 2 1 0
|
||||
; +-----+-+-+-+-+-+
|
||||
;window flags: | |e|w|
|
||||
; +-----+-+-+-+-+-+
|
||||
;
|
||||
; w - wrap/clip: 0=clip
|
||||
; 1=wrap
|
||||
; e - exposed: 0=exposed
|
||||
; 1=(partially) covered
|
||||
;
|
||||
portdef struc
|
||||
pt_type db PORTTYPE ; tag = port
|
||||
pt_len dw ? ; length of port structure in bytes
|
||||
pt_ptr db ?,?,? ; pointer to string, if any
|
||||
pt_pflgs dw ? ; port flags
|
||||
pt_handl dw ? ; file's handle
|
||||
pt_cline dw ? ; cursor line number
|
||||
pt_ccol dw ? ; cursor column number
|
||||
pt_ullin dw ? ; upper left hand corner's line number
|
||||
pt_ulcol dw ? ; upper left hand corner's column number
|
||||
pt_nline dw ? ; number of lines
|
||||
pt_ncols dw ? ; number of columns/line length
|
||||
pt_bordr dw ? ; window's border attributes
|
||||
pt_text dw ? ; window's text attributes
|
||||
pt_wflgs dw ? ; window flags
|
||||
pt_bfpos dw ? ; buffer position (offset)
|
||||
pt_bfend dw ? ; end of buffer offset
|
||||
pt_buffr dw ? ; input/output buffer
|
||||
portdef ends
|
||||
|
||||
port_gc equ pt_type
|
||||
pt_chunk equ pt_ullin
|
||||
|
||||
W_CLIP equ 00h
|
||||
W_WRAP equ 01h
|
||||
|
||||
READ_ONLY equ 00h
|
||||
WRITE_ONLY equ 01h
|
||||
READWRITE equ 02h
|
||||
WINDOW equ 04h
|
||||
OPEN equ 08h
|
||||
TRANSCRI equ 10h
|
||||
BINARY equ 20h
|
||||
STRIO equ 40h
|
||||
DIRTY equ 80h
|
||||
|
||||
|
||||
; The following is the format of a scheme pointer as far as
|
||||
; Lattice C is concerned:
|
||||
C_ptr struc
|
||||
C_disp dw ?
|
||||
C_page dw ?
|
||||
C_ptr ends
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Assembler Macros *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 19 April 1984 *
|
||||
;* Last Modification: 06 January 1986 *
|
||||
;***************************************
|
||||
; Adjust page number prior to store into pointer
|
||||
adjpage MACRO reg
|
||||
sal reg,1
|
||||
ENDM
|
||||
|
||||
; Convert page number from physical representation to logical page
|
||||
corrpage MACRO reg
|
||||
shr reg,1
|
||||
ENDM
|
||||
|
||||
; Test if an object in Scheme's memory has been "marked" by
|
||||
; the Garbage Collector as referenced. If the GC "marked" bit
|
||||
; is set in the "field" specified, a branch is taken to "label."
|
||||
markedp MACRO field,label
|
||||
cmp byte ptr field,0
|
||||
jl label
|
||||
ENDM
|
||||
|
||||
; Push the page number and displacement components of a Scheme
|
||||
; pointer onto the runtime stack (parameter passing mechanism)
|
||||
pushptr MACRO addr
|
||||
push addr.car ; push the displacement
|
||||
mov AL,addr.car_page ; load the page number,
|
||||
and AX,PAGEMASK ; isolate it, and
|
||||
push AX ; push it on the stack
|
||||
ENDM
|
||||
|
||||
; Pop the page number and displacement components of a Scheme
|
||||
; pointer from the runtime stack and restore a memory location
|
||||
; (parameter return mechanism)
|
||||
popptr MACRO addr
|
||||
pop AX ; Retrieve the page number and
|
||||
mov addr.car_page,AL ; update pointer in Scheme's memory
|
||||
pop addr.car ; Restore displacement in memory
|
||||
ENDM
|
||||
|
||||
; Save the registers in the macro's argument (a list) in the local
|
||||
; stack in the variables "save_xx", where "xx" is the register name.
|
||||
save MACRO regs
|
||||
irp rr,<regs>
|
||||
mov [BP].save_&&rr,rr
|
||||
endm
|
||||
endm
|
||||
|
||||
; Restore the registers in the macro's argument (a list) from the local
|
||||
; stack in the variables "save_xx", where "xx" is the register name.
|
||||
restore MACRO regs
|
||||
irp rr,<regs>
|
||||
mov rr,[BP].save_&&rr
|
||||
endm
|
||||
endm
|
||||
|
||||
; Push multiple
|
||||
pushm MACRO objs
|
||||
irp oo,<objs>
|
||||
push oo
|
||||
endm
|
||||
endm
|
||||
|
||||
; Pop multiple
|
||||
popm MACRO objs
|
||||
irp oo,<objs>
|
||||
pop oo
|
||||
endm
|
||||
endm
|
||||
|
||||
; Call Lattice C routine: C_call rtn,<regs>
|
||||
; A call is made to "rtn". If "rtn" has not been declared, an "extrn"
|
||||
; declaration is generated. "<regs>", if specified is the list of
|
||||
; registers which are to be saved prior to the call (see the "save"
|
||||
; macro above).
|
||||
C_call macro rtn,regs,esp
|
||||
IFNB <regs>
|
||||
irp rr,<regs>
|
||||
mov [BP].save_&&rr,rr
|
||||
endm
|
||||
ENDIF
|
||||
IFNB <esp>
|
||||
mov AX,DS ; make ES point to the current
|
||||
mov ES,AX ; data segment
|
||||
ENDIF
|
||||
IFNDEF rtn
|
||||
extrn rtn:near
|
||||
ENDIF
|
||||
call rtn
|
||||
endm
|
||||
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
/* =====> SCHMDEFS.H */
|
||||
/* TIPC Scheme Data Declarations for Lattice C */
|
||||
/* Last Modification: */
|
||||
/* tc 2/10/87 modified Page 5 special symbols to reflect */
|
||||
/* changes for the R^3 Report. */
|
||||
/* */
|
||||
|
||||
|
||||
extern char *rtn_name;
|
||||
#define ASSERT(arg) if(!(arg))asrt$(rtn_name,"arg")
|
||||
#define ENTER(xyz) static char *rtn_name = "xyz"
|
||||
|
||||
/* Data conversion macros */
|
||||
/* Adjust page number- this macro converts a logical page number to
|
||||
the representation which is stored in the interpreter's registers
|
||||
and pointers. "CORRPAGE" performs the reverse transformation */
|
||||
#define ADJPAGE(x) ((x)<<1)
|
||||
/* Correct page number- this macro converts the interpreter's encoding
|
||||
of a page number into the logical page number. "ADJPAGE" performs
|
||||
the reverse transformation. */
|
||||
#define CORRPAGE(x) ((x)>>1)
|
||||
|
||||
/* Fetch value for Fixnum (immediate) from pointer */
|
||||
#define get_fix(pg,ds) (((ds)<<1)>>1)
|
||||
/* Fetch value for Character (immediate) from pointer */
|
||||
#define get_char(pg,ds) ((ds) & 0x00ff)
|
||||
|
||||
/* define truth */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NULL 0 /* null pointer */
|
||||
|
||||
/* Position of page/displacement values in "registers" */
|
||||
#define C_DISP 0
|
||||
#define C_PAGE 1
|
||||
|
||||
/* Page Management Table Definitions */
|
||||
#define NUMPAGES 128 /* maximum number of pages */
|
||||
#define DEDPAGES 8 /* Number of dedicated pages */
|
||||
|
||||
/* MIN_PAGESIZE is defined in either regmem.h, expmem.h, or extmem.h */
|
||||
#define PTRMASK MIN_PAGESIZE-1 /* mask to isolate a pointer displacement */
|
||||
|
||||
#define PAGEINCR 2 /* increment to get to next page */
|
||||
#define PAGEMASK 0x00FE /* mask to isolate a page number */
|
||||
#define WORDSIZE 16 /* computer's word size (bits/word) */
|
||||
#define WORDINCR 2 /* number of address units/word */
|
||||
#define HT_SIZE 211 /* the oblist's hash table size */
|
||||
#define STKSIZE 900 /* the stack's length (bytes) */
|
||||
#define BLK_OVHD 3 /* number of overhead bytes in a block header */
|
||||
#define NUM_REGS 64 /* number of registers in the Scheme VM */
|
||||
|
||||
/* Data Type Equates */
|
||||
#define NUMTYPES 15 /* the number of data types */
|
||||
#define LISTTYPE 0
|
||||
#define FIXTYPE 1
|
||||
#define FLOTYPE 2
|
||||
#define BIGTYPE 3
|
||||
#define SYMTYPE 4
|
||||
#define STRTYPE 5
|
||||
#define ARYTYPE 6
|
||||
#define VECTTYPE ARYTYPE
|
||||
#define CONTTYPE 7
|
||||
#define CLOSTYPE 8
|
||||
#define FREETYPE 9
|
||||
#define CODETYPE 10
|
||||
#define REFTYPE 11
|
||||
#define PORTTYPE 12
|
||||
#define CHARTYPE 13
|
||||
#define ENVTYPE 14
|
||||
|
||||
#define EOFERR 1 /* Codes for function ERRMSG */
|
||||
#define DOTERR 2
|
||||
#define QUOTERR 3
|
||||
#define RPARERR 4
|
||||
#define OVERERR 5
|
||||
#define DIV0ERR 6
|
||||
#define SHARPERR 7
|
||||
#define FULLERR -1
|
||||
#define PORTERR -2
|
||||
#define HEAPERR -3
|
||||
|
||||
#define BUFSIZE 80
|
||||
#define SYM_OVHD 7
|
||||
|
||||
#define PTRSIZE 3
|
||||
#define LISTSIZE 6
|
||||
#define FIXSIZE 2
|
||||
#define FLOSIZE 9
|
||||
#define SMALL_SIZE 1024 /* a "small" length for a block */
|
||||
|
||||
#define SPECCHAR 1 /* special page of characters */
|
||||
#define SPECFIX 3 /* special page of fixnums */
|
||||
#define SFIXLEN 0 /* length (bytes) of special fixnum page */
|
||||
#define SPECFLO 4 /* special page of flonums */
|
||||
#define SFLOLEN 24 /* length (bytes) of special flonum page */
|
||||
#define SPECSYM 5 /* special page of symbols */
|
||||
#define SSYMLEN 0x51 /* length (bytes) of special symbol page */
|
||||
#define SPECSTK 6
|
||||
#define SPECPOR 6 /* special page of ports */
|
||||
#define SPORLEN 92 /* length (bytes) of special port page */
|
||||
#define SPECCODE 7 /* code page for the bootstrap loader */
|
||||
|
||||
#define END_LIST 0x7FFF /* end of linked list marker */
|
||||
|
||||
#define NIL_PAGE 0 /* Location of "nil" */
|
||||
#define NIL_DISP 0
|
||||
#define T_PAGE SPECSYM /* Location of "t" (for true) */
|
||||
#define T_DISP 0x0000
|
||||
#define UN_PAGE SPECSYM /* Location of "#!unassigned" */
|
||||
#define UN_DISP 0x0009
|
||||
#define NTN_PAGE SPECSYM /* Location of "#!not-a-number" */
|
||||
#define NTN_DISP 0x001C
|
||||
#define OVR_PAGE SPECSYM /* Location of overflow designator */
|
||||
#define OVR_DISP 0x001C /* (same as "not a number" for now) */
|
||||
#define DIV0_PAGE SPECSYM /* Location of divide-by-zero designator */
|
||||
#define DIV0_DISP 0x001C /* (same as "not a number" for now) */
|
||||
#define IN_PAGE SPECPOR /* Location of standard input port */
|
||||
#define IN_DISP 0
|
||||
#define OUT_PAGE SPECPOR /* Location of standard output port */
|
||||
/* #define OUT_DISP 0x011f */
|
||||
#define OUT_DISP 0 /* input=output for standard console device */
|
||||
#define WHO_PAGE SPECPOR /* Location of "who-line" port */
|
||||
#define WHO_DISP 0x0123
|
||||
#define EOF_PAGE SPECSYM /* Location of non-interned "**eof**" symbol */
|
||||
#define EOF_DISP 0x0031
|
||||
#define NPR_PAGE SPECSYM /* Location of "#!unprintable" */
|
||||
#define NPR_DISP 0x003D
|
||||
|
||||
#define ADD_OP 0 /* addition */
|
||||
#define SUB_OP 1 /* subtraction */
|
||||
#define MUL_OP 2 /* multiplication */
|
||||
#define DIV_OP 3 /* divide */
|
||||
#define MOD_OP 4 /* modulo */
|
||||
#define AND_OP 5 /* bitwise and */
|
||||
#define OR_OP 6 /* bitwise or */
|
||||
#define MINUS_OP 7 /* minus */
|
||||
#define EQ_OP 8 /* equal comparison */
|
||||
#define NE_OP 9 /* not equal comparison */
|
||||
#define LT_OP 10 /* less than comparison */
|
||||
#define GT_OP 11 /* greater than comparison */
|
||||
#define LE_OP 12 /* less than or equal comparison */
|
||||
#define GE_OP 13 /* greater than or equal comparison */
|
||||
#define ABS_OP 14 /* absolute value */
|
||||
#define QUOT_OP 15 /* quotient */
|
||||
#define TRUNC_OP 16 /* truncate */
|
||||
#define FLOOR_OP 17 /* floor */
|
||||
#define CEIL_OP 18 /* ceiling */
|
||||
#define ROUND_OP 19 /* round */
|
||||
#define FLOAT_OP 20 /* float */
|
||||
#define ZERO_OP 21 /* zero? */
|
||||
#define POS_OP 22 /* positive? */
|
||||
#define NEG_OP 23 /* negative? */
|
||||
#define XOR_OP 24 /* bitwise xor */
|
||||
|
||||
/* Numeric Error Codes */
|
||||
#define REF_GLOBAL_ERROR 1 /* reference of unbound global variable */
|
||||
#define SET_GLOBAL_ERROR 2 /* SET! error-- global not defined */
|
||||
#define REF_LEXICAL_ERROR 3 /* reference of unbound lexical variable */
|
||||
#define SET_LEXICAL_ERROR 4 /* SET! error-- lexical variable not defined */
|
||||
#define REF_FLUID_ERROR 5 /* reference of unbound fluid variable */
|
||||
#define SET_FLUID_ERROR 6 /* SET-FLUID! error-- fluid not bound */
|
||||
#define VECTOR_OFFSET_ERROR 7 /* vector index out of range */
|
||||
#define STRING_OFFSET_ERROR 8 /* string index out of range */
|
||||
#define SUBSTRING_RANGE_ERROR 9 /* invalid substring range */
|
||||
#define INVALID_OPERAND_ERROR 10 /* invalid operand to VM instruction */
|
||||
#define SHIFT_BREAK_CONDITION 11 /* SHFT-BRK key was depressed by user */
|
||||
#define NON_PROCEDURE_ERROR 12 /* attempted to call non-procedural object */
|
||||
#define TIMEOUT_CONDITION 13 /* timer interrupt */
|
||||
#define WINDOW_FAULT_CONDITION 14 /* attempt to do I/O to a de-exposed window */
|
||||
#define FLONUM_OVERFLOW_ERROR 15 /* flonum overflow/underflow */
|
||||
#define ZERO_DIVIDE_ERROR 16 /* division by zero */
|
||||
#define NUMERIC_OPERAND_ERROR 17 /* non-numeric operand */
|
||||
#define APPLY_ARG_LIMIT_ERROR 18 /* too many arguments for APPLY to handle */
|
||||
#define VECTOR_SIZE_LIMIT_ERROR 19 /* vector too big */
|
||||
#define STRING_SIZE_LIMIT_ERROR 20 /* string too big */
|
||||
#define IO_ERRORS_START 21 /* Errors from 21 and 84 are DOS I/O errors */
|
||||
#define DOS_FATAL_ERROR 21 /* Generic fatal I/O error */
|
||||
#define EXTEND_START_ERROR_CODE 1 /* Extended error codes from INT 59h */
|
||||
#define EXTEND_END_ERROR_CODE 88
|
||||
#define DISK_FULL_ERROR 200 /* Our own home-grown error codes */
|
||||
#define LAST_ERROR 200 /* Future errors should start here */
|
||||
|
||||
|
||||
/* Scheme VM Control Flags */
|
||||
extern int PC_MAKE; /* variable denoting PC's manufacturer & type */
|
||||
extern int VM_debug; /* VM debug mode flag */
|
||||
extern int s_break; /* shift-break indicator */
|
||||
|
||||
extern int QUOTE_PAGE; /* Location of "quote" */
|
||||
extern int QUOTE_DISP;
|
||||
|
||||
extern unsigned PAGESIZE;
|
||||
extern unsigned pagetabl[NUMPAGES]; /* Paragraph Address (bases) */
|
||||
extern struct {
|
||||
unsigned atom:1;
|
||||
unsigned listcell:1;
|
||||
unsigned fixnums:1;
|
||||
unsigned flonums:1;
|
||||
unsigned bignums:1;
|
||||
unsigned symbols:1;
|
||||
unsigned strings:1;
|
||||
unsigned arrays:1;
|
||||
unsigned nomemory:1;
|
||||
unsigned readonly:1;
|
||||
unsigned continu:1;
|
||||
unsigned closure:1;
|
||||
unsigned refs:1;
|
||||
unsigned ports:1;
|
||||
unsigned code:1;
|
||||
unsigned characters:1;
|
||||
} attrib[NUMPAGES]; /* Page Attribute Bits */
|
||||
extern int w_attrib[NUMPAGES]; /* Re-define attribute bits as integer */
|
||||
extern int nextcell[NUMPAGES]; /* Next Available Cell Pointers */
|
||||
extern int pagelink[NUMPAGES]; /* Next Page of Same Type */
|
||||
extern int ptype[NUMPAGES]; /* Page Type Index */
|
||||
extern unsigned psize[NUMPAGES]; /* Page Size Table */
|
||||
|
||||
extern int pageattr[NUMTYPES]; /* Page attribute initialization table */
|
||||
extern int pagelist[NUMTYPES]; /* Page allocation table (by types) */
|
||||
|
||||
extern int listpage; /* Page for List Cell allocation */
|
||||
extern int fixpage; /* Page for Fixnum allocation */
|
||||
extern int flopage; /* Page for Flonum allocation */
|
||||
extern int bigpage; /* Page for Bignum allocation */
|
||||
extern int sympage; /* Page for Symbol allocation */
|
||||
extern int strpage; /* Page for String allocation */
|
||||
extern int arypage; /* Page for Array allocation */
|
||||
extern int contpage; /* Page for Continuation allocation */
|
||||
extern int clospage; /* Page for Closure allocation */
|
||||
extern int freepage; /* Free page allocation list header */
|
||||
extern int codepage; /* Page for Code Block allocation */
|
||||
extern int refpage; /* Ref cell page allocation list header */
|
||||
|
||||
extern int nextpage; /* Next Page # for Allocation in Address Space */
|
||||
extern int lastpage; /* Last Page # for Allocation in Address Space */
|
||||
extern unsigned nextpara; /* Next Paragraph Address for Allocation */
|
||||
|
||||
/* Scheme's Virtual Registers */
|
||||
extern long reg0, regs[NUM_REGS];
|
||||
extern int nil_reg[2];
|
||||
extern int reg0_page, reg0_disp, tmp_reg[2], tmp_page, tmp_disp;
|
||||
extern int tm2_reg[2], tm2_page, tm2_disp;
|
||||
extern int FNV_reg[2], GNV_reg[2], CB_reg[2], PREV_reg[2];
|
||||
extern int FNV_pag, FNV_dis, GNV_pag, GNV_dis, CB_pag, CB_dis;
|
||||
extern int PREV_pag, PREV_dis, FP, BASE;
|
||||
extern int CONSOLE_[2], CON_PAGE, CON_DISP;
|
||||
extern int TRNS_reg[2], TRNS_pag, TRNS_dis; /* transcript file pointer */
|
||||
extern int condcode, S_pc;
|
||||
|
||||
/* Stack */
|
||||
extern int TOS; /* top of stack pointer (displacement in bytes */
|
||||
extern char S_stack[STKSIZE]; /* the stack itself */
|
||||
|
||||
/* Hash Table */
|
||||
extern char hash_page[HT_SIZE];
|
||||
extern int hash_disp[HT_SIZE];
|
||||
|
||||
/* Property List Hash Table */
|
||||
extern char prop_page[HT_SIZE];
|
||||
extern int prop_disp[HT_SIZE];
|
||||
|
||||
/* State Variables for (reset) and (scheme-reset) */
|
||||
extern int FP_save, RST_ent;
|
||||
extern int FNV_save[2];
|
||||
extern int STL_save[2];
|
||||
|
||||
/* Port fields */
|
||||
#define pt_direc 6
|
||||
#define pt_lnlen 20
|
||||
#define pt_csrcol 12
|
||||
#define dtaoffs 32
|
||||
|
||||
/* Error message text strings */
|
||||
extern char m_error[], m_src[], m_dest[], m_first[], m_second[], m_third[];
|
||||
|
||||
/* Macros Normally Found in STDIO.H */
|
||||
#define abs(x) ((x)<0?-(x):(x))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define min(a,b) ((a)<=(b)?(a):(b))
|
||||
|
||||
/* Scheme Function Macros */
|
||||
#define alloc_sym(dest,len) alloc_block(dest,SYMTYPE,len+PTRSIZE+1)
|
||||
|
||||
#ifdef PROMEM
|
||||
#define outchar(ch) printcha(ch)
|
||||
#define outtext(str,len) printtxt(str,len)
|
||||
#else
|
||||
#define outchar(ch) givechar(ch)
|
||||
#define outtext(str,len) printstr(str,len)
|
||||
#endif
|
||||
|
||||
/* International Case Conversion Macros */
|
||||
extern char locases[256];
|
||||
extern char hicases[256];
|
||||
#undef tolower
|
||||
#define tolower(c) locases[(c)]
|
||||
#undef toupper
|
||||
#define toupper(c) hicases[(c)]
|
||||
#undef islower
|
||||
#define islower(c) ((c)!=hicases[(c)])
|
||||
#undef isupper
|
||||
#define isupper(c) ((c)!=locases[(c)])
|
||||
#undef isspace
|
||||
#undef isdigit
|
||||
#define isdigit(c) isdig((c),10)
|
||||
#undef isxdigit
|
||||
#define isxdigit(c) isdig((c),16)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
DEFAULT_NUM_ROWS equ 25
|
||||
DEFAULT_VGA_ROWS equ 30
|
||||
DEFAULT_NUM_COLS equ 80
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
; =====> SCROLL.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* Window Support Routine *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: October 1985 *
|
||||
;* Last Modification: *
|
||||
;***************************************
|
||||
include pcmake.equ
|
||||
|
||||
TI_CRT equ 049h
|
||||
IBM_CRT equ 010h
|
||||
|
||||
DGROUP group DATA
|
||||
DATA segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
extrn PC_MAKE:word
|
||||
DATA ends
|
||||
|
||||
XGROUP group PROGX
|
||||
PROGX segment byte public 'PROGX'
|
||||
assume CS:XGROUP,DS:DGROUP
|
||||
extrn crt_dsr:far
|
||||
|
||||
;************************************************************************
|
||||
;* Scroll Window Down one line *
|
||||
;************************************************************************
|
||||
s_args struc
|
||||
dw ? ; caller's BP
|
||||
dd ? ; return address
|
||||
dw ?
|
||||
s_line dw ? ; upper left hand corner line number
|
||||
s_col dw ? ; upper left hand corner column number
|
||||
s_nline dw ? ; number of lines
|
||||
s_ncols dw ? ; number of columns
|
||||
s_attr dw ? ; text attributes (used for blanking)
|
||||
s_args ends
|
||||
|
||||
scroll%d proc far
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
; scroll window's text down one line
|
||||
mov CL,byte ptr [BP].s_nline ; load number of lines
|
||||
dec CL ; decrease number of lines by one
|
||||
jz blank ; Jump if scrolling 1-line and just blank it
|
||||
mov CH,byte ptr [BP].s_ncols ; load number of columns
|
||||
mov DL,byte ptr [BP].s_line ; load upper left line number
|
||||
mov DH,byte ptr [BP].s_col ; load upper left column number
|
||||
mov AX,0701h ; load "scroll text" code with no blanking
|
||||
cmp DGROUP:PC_MAKE,TIPC
|
||||
je ti_down
|
||||
|
||||
push AX ; else
|
||||
mov AH,0Fh
|
||||
int IBM_CRT ; Are we in graphics mode?
|
||||
cmp AL,4 ; If we are then fix blank fill attributes
|
||||
jl text_m ; so that the bar characters don't show up
|
||||
cmp AL,7
|
||||
je text_m
|
||||
xor BH,BH ; zero attribute for fill blanks
|
||||
jmp short wrte_atr
|
||||
text_m: mov BH,byte ptr [BP].s_attr ; Blanked lines' attribute txt mode
|
||||
|
||||
wrte_atr: pop AX
|
||||
xchg CX,DX ; CX=Upper left corner
|
||||
xchg CH,CL ; Row,column instead of TI's column,row
|
||||
xchg DH,DL ; ditto
|
||||
add DX,CX ; DX=Lower right corner
|
||||
dec DL ; adjust column count (0 is first column)
|
||||
int IBM_CRT
|
||||
jmp short quit ; IFF IBM is in graphics mode weird char's
|
||||
; are used for blanks when scrolling. Do
|
||||
; as TIPC does and "manual" blank 'em.
|
||||
;
|
||||
ti_down: mov BX,DX ; copy destination coordinates
|
||||
inc BL ; compute dest by incrementing line number
|
||||
int TI_CRT ; perform the block move
|
||||
; paint the first line of the window with blank of proper attributes
|
||||
blank: mov DH,byte ptr [BP].s_col ; load starting column number
|
||||
mov DL,byte ptr [BP].s_line ; load upper line number
|
||||
mov AH,02h ; load the "put cursor" code
|
||||
xor BH,BH ; IBMism
|
||||
call crt_dsr ; position cursor for write
|
||||
mov AX,0920h ; load "write char/attr" code, write a blank
|
||||
mov BL,byte ptr [BP].s_attr ; load attribute bit setting
|
||||
xor BH,BH ; IBMism
|
||||
mov CX,[BP].s_ncols ; load line length
|
||||
call crt_dsr ; write a line of blanks
|
||||
; return to caller
|
||||
quit: pop BP ; restore caller's BP
|
||||
ret
|
||||
scroll%d endp
|
||||
PROGX ends
|
||||
|
||||
;****************************************************************************
|
||||
;* Link routine *
|
||||
;****************************************************************************
|
||||
|
||||
PGROUP GROUP PROG
|
||||
PROG SEGMENT BYTE PUBLIC 'PROG'
|
||||
assume CS:PGROUP
|
||||
public scroll_d
|
||||
|
||||
scroll_d proc near
|
||||
call scroll%d ; link to window scroll down routine
|
||||
ret
|
||||
scroll_d endp
|
||||
PROG ends
|
||||
end
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Operation Support *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985,1986 by *
|
||||
;* Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 19 April 1984 *
|
||||
;* Last Modification: 26 February 1986*
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
new_disp dw 0
|
||||
new_page dw 0
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
; CONS Support -- combine two pointers in a new list cell
|
||||
con_arg struc
|
||||
dw ? ; return address
|
||||
con_res dw ? ; address of result register
|
||||
con_car dw ? ; address of reg. containing car
|
||||
con_cdr dw ? ; address of reg. containing cdr
|
||||
con_arg ends
|
||||
|
||||
extrn alloc_li:near ; C routine to allocate a list cell
|
||||
|
||||
public cons
|
||||
cons proc near
|
||||
; Attempt a "short circuit" allocation of a list cell
|
||||
mov BX,listpage ; load current list cell allocation page no.
|
||||
;;; cmp BX,END_LIST ; is allocation page specified?
|
||||
;;; je cons_no
|
||||
shl BX,1
|
||||
mov SI,nextcell+[BX] ; load next available cell offset
|
||||
cmp SI,END_LIST
|
||||
je cons_no
|
||||
; at this point, the allocation has succeeded
|
||||
mov DX,ES ; save the caller's ES register
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load list cell page's segment address
|
||||
mov AX,ES:[SI].car ; load pointer to next available cell
|
||||
mov nextcell+[BX],AX ; and update free cell chain header
|
||||
|
||||
; store CDR value into list cell
|
||||
cons_ok: mov CX,BP ; save the caller's base pointer
|
||||
mov BP,SP ; and establish addressability for args
|
||||
mov DI,[BP].con_cdr ; fetch address of register containing CDR
|
||||
mov AL,byte ptr [DI].C_page ; copy contents of register into
|
||||
mov ES:[SI].cdr_page,AL ; the new list cell's CDR field
|
||||
mov AX,[DI].C_disp
|
||||
mov ES:[SI].cdr,AX
|
||||
|
||||
; store CAR value into list cell
|
||||
mov DI,[BP].con_car ; fetch address of register containing CAR
|
||||
mov AL,byte ptr [DI].C_page ; copy contents of register into
|
||||
mov ES:[SI].car_page,AL ; the new list cell's CAR field
|
||||
mov AX,[DI].C_disp
|
||||
mov ES:[SI].car,AX
|
||||
|
||||
; store pointer to new list cell in destination register
|
||||
mov DI,[BP].con_res ; fetch address of destination register
|
||||
mov byte ptr [DI].C_page,BL
|
||||
mov [DI].C_disp,SI
|
||||
|
||||
mov ES,DX ; restore caller's ES register
|
||||
mov BP,CX ; restore caller's BP register
|
||||
ret ; return to caller
|
||||
|
||||
; OOPS-- no list cell immediately available-- go through channels
|
||||
cons_no: mov AX,offset new_disp ; push address of a dummy result
|
||||
push AX ; register onto the TIPC's stack
|
||||
call alloc_li ; allocate a list cell
|
||||
add SP,WORDINCR ; drop argument from stack
|
||||
mov BX,new_page ; fetch list cell's page number
|
||||
mov SI,new_disp ; and displacement
|
||||
mov DX,ES ; save the caller's ES register
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; make ES point to the new list cell
|
||||
jmp cons_ok
|
||||
cons endp
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Garbage Collection - Mark Phase *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: April 1984 *
|
||||
;* Last Modification: 06 January 1986 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
arguments struc
|
||||
dw ? ; Caller's BP
|
||||
dw ? ; Return address
|
||||
page_idx dw ? ; Page number of pointer
|
||||
pointer dw ? ; Displacement of pointer
|
||||
arguments ends
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
extrn _base:word ; base address of the TIPC runtime stack
|
||||
sum_bt dw sum_list ; [0] List cells
|
||||
dw sum_fix ; [1] Fixnums
|
||||
dw sum_flo ; [2] Flonums
|
||||
dw sum_big ; [3] Bignums
|
||||
dw sum_sym ; [4] Symbols
|
||||
dw sum_str ; [5] Strings
|
||||
dw sum_ary ; [6] Arrays
|
||||
dw sum_cont ; [7] Continuations
|
||||
dw sum_clos ; [8] Closures
|
||||
dw sum_free ; [9] Free page
|
||||
dw sum_code ; [10] Code page
|
||||
dw sum_free ; [11] (Formerly, Reference cells)
|
||||
dw sum_port ; [12] Port data objects
|
||||
dw sum_char ; [13] Characters
|
||||
dw sum_env ; [14] Environments
|
||||
; Branch table for pointer classification
|
||||
branchtab dw gcmlist ; [0] List cells
|
||||
dw gcmfix ; [1] Fixnums
|
||||
dw gcmflo ; [2] Flonums
|
||||
dw gcmbig ; [3] Bignums
|
||||
dw gcmsym ; [4] Symbols
|
||||
dw gcmstr ; [5] Strings
|
||||
dw gcmary ; [6] Arrays
|
||||
dw gcmcont ; [7] Continuations
|
||||
dw gcmclos ; [8] Closures
|
||||
dw gcmfree ; [9] Free page
|
||||
dw gcmcode ; [10] Code page
|
||||
dw gcmfree ; [11] (Formerly, Reference cells)
|
||||
dw gcmport ; [12] Port data objects
|
||||
dw gcmchar ; [13] Characters
|
||||
dw gcmenv ; [14] Environments
|
||||
|
||||
m_oops db "[VM INTERNAL ERROR] sum_spac: infinite loop page %d",LF,0
|
||||
m_format db "[VM INTERNAL ERROR] sgcmark: invalid pointer: %x:%04x "
|
||||
db "(unadjusted)",LF,0
|
||||
m_overfl db "[VM FATAL ERROR] Stack overflow during GC",LF,0
|
||||
DS_addr dw DGROUP
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
|
||||
assume CS:PGROUP
|
||||
|
||||
public garbage
|
||||
garbage proc near
|
||||
push ES
|
||||
mov ES,DS_addr
|
||||
C_call garbage1
|
||||
pop ES
|
||||
ret
|
||||
garbage endp
|
||||
|
||||
mark proc near
|
||||
; ***error-- bad pointer found-- report error***
|
||||
gcmfix: ; Fixnums are immediates
|
||||
gcmchar: ; Characters are immediates
|
||||
gcmfree: ; Why are we collecting in a free page?
|
||||
bad_ptr:
|
||||
push AX
|
||||
mov AX,offset m_format ; load address of format text
|
||||
push DX ; save the return address
|
||||
pushm <SI,BX,AX> ; push arguments to printf
|
||||
C_call printf,,Load_ES ; print error message
|
||||
add SP,WORDINCR*3 ; drop arguments from stack
|
||||
C_call force_de ; go into debug mode
|
||||
pop DX ; restore the return address
|
||||
pop AX
|
||||
jmp gcmret ; go on as if nothing happened
|
||||
|
||||
public gcmark
|
||||
gcmark: pop DX ; unload return address
|
||||
pop BX ; fetch page number (x 2)
|
||||
mov AX,BX ; save in AX
|
||||
pop SI ; fetch displacement
|
||||
push DX ; save return address
|
||||
push ES ; save ES
|
||||
mov DX,offset pgroup:gcmarkret
|
||||
jmp gcm_tr
|
||||
gcmarkret:
|
||||
pop ES
|
||||
pop DX
|
||||
jmp DX ; return
|
||||
|
||||
|
||||
; see if pointer is to one of the "special" non-collected pages
|
||||
gcm_tr: cmp BX,DEDPAGES*PAGEINCR ; check for non-gc'ed pages
|
||||
jge gcm_go ; if not one of the special pages, jump
|
||||
jmp DX ; return
|
||||
;
|
||||
gcm_go: push AX ; Preserve the page number
|
||||
; load pointer offset into ES:; displacement into SI
|
||||
test BX,0FF01h ; valid pointer?
|
||||
jnz bad_ptr ; if so, error (jump)
|
||||
LoadPage ES,BX
|
||||
mov AX,BX ; Use AX to store page number
|
||||
; classify pointer according to data type
|
||||
mov DI,ptype+[BX] ; load data type*2
|
||||
cmp DI,NUMTYPES*2 ; valid page type?
|
||||
jae bad_ptr ; if not, error (jump)
|
||||
jmp branchtab+[DI]
|
||||
|
||||
; Process symbol or port
|
||||
gcmport:
|
||||
gcmsym: markedp ES:[SI].sym_gc,gcmret ; already marked? if so, return (jump)
|
||||
or byte ptr ES:[SI].sym_gc,GC_BIT ; mark symbol/port as seen
|
||||
mov BL,ES:[SI].sym_page ; fetch pointer from symbol/port object
|
||||
mov SI,ES:[SI].sym_disp
|
||||
pop AX ; restore saved page number
|
||||
LoadPage ES,AX ; Get Page address
|
||||
jmp gcm_tr ; make a tail recursive call to gcmark
|
||||
|
||||
; Process List Cell-- If marked, skip rest of processing
|
||||
gcmlist: markedp ES:[SI].list_gc,gcmret ; if marked, jump to return
|
||||
; Call gcmark with CAR of list cell
|
||||
or byte ptr ES:[SI].list_gc,GC_BIT ; "mark" as referenced
|
||||
mov BL,ES:[SI].car_page ; load page number of car field
|
||||
cmp BX,DEDPAGES*PAGEINCR ; check for non-gc'ed pages
|
||||
jl gcmls_ok ; if one of the special pages, jump
|
||||
; Test for TIPC stack overflow
|
||||
push AX
|
||||
mov AX,SP ; copy the current stack top pointer
|
||||
sub AX,_base ; and compute number of bytes remaining
|
||||
cmp AX,64 ; enough space to continue?
|
||||
pop AX
|
||||
jb stk_ovfl ; if not enough room, abort (jump)
|
||||
; Mark expression pointed to by the car field
|
||||
push SI ; save offset of list cell
|
||||
push DX ; save the previous return address
|
||||
mov DX,offset PGROUP:gcmls_rt ; Load the return address
|
||||
mov SI,ES:[SI].car ; Load car field pointer
|
||||
and SI,07FFFh ; Clear out the GC bit
|
||||
jmp gcm_go ; Call gcmark recursively
|
||||
gcmls_rt:
|
||||
pop DX ; Restore previous return address
|
||||
pop SI ; Restore offset of list cell
|
||||
; Call gcmark tail recursively with CDR of list cell
|
||||
gcmls_ok: mov BL,ES:[SI].cdr_page ; load the pointer contained in the
|
||||
mov SI,ES:[SI].cdr ; cdr field
|
||||
pop AX ; restore saved page
|
||||
LoadPage ES,AX ; Get Page address
|
||||
jmp gcm_tr ; call gcmark tail recursively
|
||||
|
||||
; TIPC stack overflow-- Abort
|
||||
stk_ovfl: mov AX,offset m_overfl ; load address of error message text
|
||||
push AX ; and push it as an argument to printf
|
||||
C_call printf,,Load_ES ; print the error message
|
||||
C_call getch ; wait for any key to be pressed
|
||||
C_call exit ; return to MS-DOS
|
||||
|
||||
; Return to caller
|
||||
gcmret: pop AX ; restore saved page
|
||||
LoadPage ES,AX ; Get Page address
|
||||
jmp DX ; return to caller
|
||||
|
||||
|
||||
; Process reference to variable length data object or flonum
|
||||
gcmflo:
|
||||
gcmbig:
|
||||
gcmstr:
|
||||
or byte ptr ES:[SI].vec_gc,GC_BIT
|
||||
pop AX ; restore saved page
|
||||
LoadPage ES,AX ; Get Page address
|
||||
jmp DX ; return
|
||||
|
||||
; Process Code Block
|
||||
gcmcode: markedp ES:[SI].cod_gc,gcmret ; If already processed, return
|
||||
or byte ptr ES:[SI].cod_gc,GC_BIT
|
||||
mov CX,ES:[SI].cod_entr ; load entry point offset as counter
|
||||
jmp gcmlop1
|
||||
|
||||
; Process Variable Length Object Containing Pointers
|
||||
gcmary:
|
||||
gcmclos:
|
||||
gcmcont:
|
||||
gcmenv:
|
||||
markedp ES:[SI].vec_gc,gcmret ; If already processed, jump to return
|
||||
or byte ptr ES:[SI].vec_gc,GC_BIT ; mark as referenced
|
||||
mov CX,ES:[SI].vec_len
|
||||
cmp CX,PTRSIZE ; test for zero length vector
|
||||
jle gcmret ; if no elements, jump
|
||||
; Test the size of the TIPC stack to insure room to continue
|
||||
gcmlop1: push AX
|
||||
mov AX,SP ; load the current stack top pointer
|
||||
sub AX,_base ; and compute the number of bytes remaining
|
||||
cmp AX,64 ; are there at least 64 bytes left?
|
||||
pop AX
|
||||
jb stk_ovfl ; if not enough room, abort (jump)
|
||||
; Call gcmark with pointer in this object
|
||||
push DX ; Save previous return address
|
||||
mov DX,offset PGROUP:gcml_ret ; Load return address into DX
|
||||
gcmloop: add SI,PTRSIZE ; Increment address for next pointer
|
||||
push CX ; Save counter across calls
|
||||
push SI ; Save curr offset into vector (or whatever)
|
||||
mov BL,ES:[SI].car_page ; load next element pointer from array,
|
||||
mov SI,ES:[SI].car ; closure, etc.
|
||||
jmp gcm_tr ; call gcmark recursively
|
||||
gcml_ret: pop SI ; Restore current offset
|
||||
pop CX ; Restore iteration count
|
||||
sub CX,PTRSIZE ; Decrement counter
|
||||
cmp CX,PTRSIZE ; and test for completion
|
||||
jg gcmloop ; Loop through all pointers in object
|
||||
pop DX ; Restore previous return address
|
||||
pop AX ; Restore saved page
|
||||
LoadPage ES,AX ; Get Page address
|
||||
jmp DX ; Return
|
||||
|
||||
mark endp
|
||||
|
||||
sum_args struc
|
||||
dw ? ; caller's ES
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
sum_vctr dw ? ; pointer to summation vector (for results)
|
||||
sum_args ends
|
||||
|
||||
public sum_spac
|
||||
sum_spac proc near
|
||||
push BP ; save the caller's BP on entry
|
||||
push ES ; save the caller's ES
|
||||
mov BP,SP ; update BP
|
||||
|
||||
; initialize
|
||||
mov DI,[BP].sum_vctr ; load address of result vector
|
||||
xor BX,BX ; start with zero-th page
|
||||
|
||||
; top of loop-- look at next page
|
||||
sum_loop: xor AX,AX ; clear the free space counter
|
||||
cmp BX,DEDPAGES*PAGEINCR
|
||||
jl sum_end
|
||||
test attrib+[BX],NOMEMORY ; is page allocated?
|
||||
jnz sum_end ; if not, skip it (branch)
|
||||
cmp ptype+[BX],FREETYPE*2
|
||||
je sum_free ; Ignore free pages [TC]
|
||||
LoadPage ES,BX ; load current paragraph's base address
|
||||
mov SI,ptype+[BX] ; load type of current page
|
||||
jmp sum_bt+[SI] ; branch on page type
|
||||
|
||||
; add up unused list cells
|
||||
sum_list: mov CX,LISTSIZE ; load size of list cell data object
|
||||
sum_l1st: mov SI,nextcell+[BX] ; load list cell free storage chain header
|
||||
sum_lnxt: cmp SI,END_LIST ; end of list?
|
||||
je sum_end ; if so, we're through here
|
||||
add AX,CX ; increment the free list cell counter
|
||||
jo sum_oops ; if overflow, we're stuck in a loop
|
||||
mov SI,ES:[SI].car ; follow free cell chain
|
||||
jmp sum_lnxt ; keep following linked list
|
||||
|
||||
; add up unused variable length things
|
||||
sum_big:
|
||||
sum_sym:
|
||||
sum_str:
|
||||
sum_clos:
|
||||
sum_cont:
|
||||
sum_ary:
|
||||
sum_code:
|
||||
sum_port:
|
||||
sum_env:
|
||||
mov SI,0 ; initialize pointer into page
|
||||
mov CX,psize+[BX] ; load size of current page
|
||||
sub CX,PTRSIZE ; adjust size for page boundary check
|
||||
sum_vnxt: cmp SI,CX ; through with this page?
|
||||
ja sum_end ; if so, branch
|
||||
mov DX,ES:[SI].vec_len ; load block length
|
||||
cmp DX,0 ;;; check for small string
|
||||
jge sum_010
|
||||
mov DX,BLK_OVHD+PTRSIZE ;;; get the exact length
|
||||
sum_010: cmp ES:[SI].vec_type,FREETYPE ; free block?
|
||||
jne sum_used ; if so, branch around add
|
||||
add AX,DX ; add in number of free bytes
|
||||
sum_used: add SI,DX ; update pointer to next block in page
|
||||
jmp sum_vnxt ; look at next block
|
||||
|
||||
sum_free: mov AX,psize+[BX] ; load size of free page
|
||||
|
||||
sum_fix:
|
||||
sum_char:
|
||||
sum_end: mov [DI],AX ; store number of free bytes (AX)
|
||||
add DI,2 ; increment array index
|
||||
add BX,2 ; increment page index
|
||||
cmp BX,NUMPAGES*2 ; test for completion
|
||||
jl sum_loop ; if more pages, jump
|
||||
|
||||
sum_ret: pop ES ; restore caller's ES
|
||||
pop BP ; restore caller's BP
|
||||
ret ; return to caller
|
||||
|
||||
; add up unused flonums
|
||||
sum_flo: mov CX,FLOSIZE ; load size of flonum
|
||||
jmp sum_l1st ; process assuming linked list allocation
|
||||
|
||||
sum_oops: shr BX,1
|
||||
lea SI,m_oops
|
||||
pushm <BX,SI>
|
||||
mov AX,DS
|
||||
mov ES,AX
|
||||
C_call printf
|
||||
C_call exit
|
||||
|
||||
sum_spac endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,335 @@
|
|||
; =====> SGCSWEEP.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Garbage Collector - Sweep Phase *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: April 1984 *
|
||||
;* Last Modification: 06 January 1986 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
m_fix_er db "[VM INTERNAL ERROR] swpage: logical page not found",LF,0
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
public gcsweep
|
||||
gcsweep proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
; Initialize similar page type chain headers
|
||||
push ES ; save the caller's ES register
|
||||
mov AX,DS ; set ES to point to the current
|
||||
mov ES,AX ; data segment
|
||||
mov AX,END_LIST ; load the end of list indicator
|
||||
mov CX,NUMTYPES ; load table length
|
||||
mov DI,offset pagelist ; load table address
|
||||
cld ; move direction = forward
|
||||
rep stosw ; initialize the pagelist table
|
||||
pop ES ; restore the caller's ES
|
||||
; Process all except the "special" non-garbage collected pages
|
||||
; mov DX,DEDPAGES-1 ;;;; mov dx,NUMPAGES
|
||||
; Increment loop index, test for completion
|
||||
;gcsloop: inc DX ;;;; dec dx
|
||||
; cmp DX,NUMPAGES ;;;; cmp dx,DEDPAGES-1
|
||||
; jl gcsl010 ;;;; ja gcsl010
|
||||
|
||||
mov DX,NUMPAGES
|
||||
gcsloop: dec DX
|
||||
cmp DX,DEDPAGES-1
|
||||
ja gcsl010
|
||||
|
||||
pop BP
|
||||
ret
|
||||
gcsl010: push DX
|
||||
call swpage ; "sweep" the page (GC it)
|
||||
pop DX
|
||||
mov BX,DX ; copy current page number
|
||||
sal BX,1 ; double for use as index
|
||||
test attrib+[BX],NOMEMORY ; is page frame allocated?
|
||||
jnz gcsloop ; if not, skip list update
|
||||
mov AX,DX ; copy current page number
|
||||
mov SI,ptype+[BX] ; move current page's type to SI
|
||||
xchg pagelist+[SI],AX ; pagelist[type] <- page
|
||||
mov pagelink+[BX],AX ; pagelink[page] <- old pagelist[type]
|
||||
jmp short gcsloop
|
||||
gcsweep endp
|
||||
|
||||
arguments struc
|
||||
page_len dw ? ; page boundary (length - fudge factor)
|
||||
args_BP dw ? ; Caller's BP
|
||||
dw ? ; Return address
|
||||
page_no dw ?
|
||||
arguments ends
|
||||
|
||||
; Test the current page to see if it's been allocated
|
||||
public swpage
|
||||
swpage proc near
|
||||
push BP
|
||||
sub SP,offset args_BP ; reserve local storage
|
||||
mov BP,SP
|
||||
push ES ; save caller's ES
|
||||
mov BX,[BP].page_no
|
||||
sal BX,1 ; double page number for index
|
||||
test DGROUP:attrib+[BX],NOMEMORY ; allocated?
|
||||
jz swp020 ; if not allocated, loop
|
||||
swpfix: ; Fixnums are handled as immediates
|
||||
swpchar: ; Characters are handled as immediates
|
||||
swpfree: ; Why are we processing a free page?
|
||||
swpref: ; Ref cells no longer exist?
|
||||
swpret: pop ES
|
||||
add SP,offset args_BP ; drop local storage from stack
|
||||
pop BP
|
||||
ret
|
||||
swp020:
|
||||
; Dispatch on the type of data stored in this page
|
||||
mov DI,DGROUP:ptype+[BX] ; load data type for this page
|
||||
cmp DI,FREETYPE*2 ; Ignore free pages [HS]
|
||||
jz swpfree ; to relieve the swapper... [HS]
|
||||
LoadPage ES,BX ; define base paragraph for this page[HS]
|
||||
mov DI,CS:btable+[DI]
|
||||
jmp DI
|
||||
|
||||
; Process List Cells (and other fixed length pointer objects)
|
||||
swplist: mov AX,LISTSIZE
|
||||
swpl010: xor SI,SI ; SI <- 0
|
||||
xor DI,DI ; zero referenced cell counter
|
||||
mov CX,END_LIST ; load end of list marker
|
||||
mov DX,-1 ; marker for unused cell header
|
||||
push BX ; save page number index
|
||||
mov BX,psize+[BX] ; load page length and
|
||||
sub BX,AX ; adjust for boundary check
|
||||
swpl020: markedp ES:[SI].list_gc,swpl030 ; branch, if marked
|
||||
; add cell to free list
|
||||
mov ES:[SI].car,CX
|
||||
mov ES:[SI].car_page,DL ; make page=FF for unused cell
|
||||
mov CX,SI
|
||||
jmp short swpl040
|
||||
; clear GC bit
|
||||
swpl030: and byte ptr ES:[SI].list_gc,NOT_GC_BI ; clear GC "marked" bit
|
||||
inc DI ; increment referenced cell counter
|
||||
; increment cell pointer and test for end of page
|
||||
swpl040: add SI,AX
|
||||
cmp SI,BX ; test for end of page
|
||||
jbe swpl020
|
||||
; end of page-- update free list header and process next page
|
||||
pop BX ; restore page table index
|
||||
mov DGROUP:nextcell+[BX],CX
|
||||
cmp DI,0 ; any referenced cells in this page?
|
||||
jne swpret ; if ref'd cells in page, branch
|
||||
mov ptype+[BX],FREETYPE*2 ; mark empty page as free
|
||||
mov attrib+[BX],0
|
||||
jmp short swpret
|
||||
|
||||
; Process Page of Flonums
|
||||
swpflo: mov AX,FLOSIZE ; load size of a single flonum
|
||||
xor SI,SI ; SI <- 0
|
||||
xor DI,DI ; zero referenced cell counter
|
||||
mov CX,END_LIST ; load end of list marker
|
||||
mov DX,-1 ; marker for unused cell header
|
||||
push BX ; save page number index
|
||||
mov BX,psize+[BX] ; load page length and
|
||||
sub BX,AX ; adjust for boundary check
|
||||
swpf020: cmp ES:[SI].flo_type,DL ; tag = free?
|
||||
je swpf025 ; if a non-allocated cell, jump
|
||||
markedp ES:[SI].flo_gc,swpf030 ; branch, if marked
|
||||
; add flonum to free list
|
||||
mov ES:[SI].car_page,DL ; make page=FF for unused cell
|
||||
swpf025: mov ES:[SI].car,CX
|
||||
mov CX,SI
|
||||
jmp short swpf040
|
||||
; clear GC bit
|
||||
swpf030: and byte ptr ES:[SI].flo_gc,NOT_GC_BI ; clear GC "marked" bit
|
||||
inc DI ; increment referenced cell counter
|
||||
; increment cell pointer and test for end of page
|
||||
swpf040: add SI,AX
|
||||
cmp SI,BX ; test for end of page
|
||||
jbe swpf020
|
||||
; end of page-- update free list header and process next page
|
||||
pop BX ; restore page table index
|
||||
mov DGROUP:nextcell+[BX],CX
|
||||
cmp DI,0 ; any referenced cells in this page?
|
||||
jne swpf050 ; if ref'd cells in page, branch
|
||||
mov ptype+[BX],FREETYPE*2 ; mark empty page as free
|
||||
mov attrib+[BX],0
|
||||
swpf050: jmp swpret
|
||||
|
||||
; Process variable length data object
|
||||
swpbig:
|
||||
swpsym:
|
||||
swpstr:
|
||||
swpary:
|
||||
swpclos:
|
||||
swpcont:
|
||||
swpcode:
|
||||
swpenv:
|
||||
xor SI,SI
|
||||
mov DI,-1
|
||||
push BX ; save page table index
|
||||
mov BX,psize+[BX] ; load size of current page and
|
||||
sub BX,PTRSIZE ; adjust for boundary check
|
||||
swpvloop: mov DX,ES:[SI].vec_len ; load length of current object
|
||||
cmp DX,0
|
||||
jge swp001
|
||||
mov DX,BLK_OVHD+PTRSIZE
|
||||
swp001: markedp ES:[SI].vec_gc,swpv020 ; branch if object referenced
|
||||
; Object not referenced-- can we combine with previous free area?
|
||||
cmp DI,0
|
||||
jge swpv010 ; If prev obj free, branch
|
||||
; Object not referenced, but previous area was
|
||||
mov ES:[SI].vec_type,FREETYPE ; Mark this object as free
|
||||
cmp ES:[SI].vec_len,0
|
||||
jge swp002
|
||||
mov ES:[SI].vec_len,BLK_OVHD+PTRSIZE
|
||||
swp002: mov DI,SI ; Record this fact for next iteration
|
||||
jmp short swpvnxt
|
||||
; Object was not referenced and can be combined with prev free area
|
||||
swpv010: add ES:[DI].vec_len,DX ; add length into previous free obj
|
||||
jmp short swpvnxt
|
||||
; Object was referenced
|
||||
swpv020: and ES:[SI].vec_gc,NOT_GC_BI ; clear gc bit
|
||||
mov DI,-1 ; Remember last object was referenced
|
||||
; Processing of current object finished-- add length and iterate
|
||||
swpvnxt: add SI,DX ; Increment area pointer by block length
|
||||
cmp SI,BX ; Last object in block?
|
||||
jb swpvloop ; Branch, if more space
|
||||
; Processing of this page finished-- update next free area pointer
|
||||
swppfin: pop BX ; Restore page table index
|
||||
cmp DI,-1
|
||||
je swpv030 ; If last block not free, skip it
|
||||
sub SI,psize+[BX] ; Adjust in case last byte of page
|
||||
neg SI ; not accounted for
|
||||
add ES:[DI].vec_len,SI
|
||||
mov nextcell+[BX],DI ; Update free pool header
|
||||
cmp DI,0 ; is page empty?
|
||||
jne swpv040 ; if not, jump
|
||||
mov ptype+[BX],FREETYPE*2 ; mark page as being free
|
||||
mov attrib+[BX],0
|
||||
mov AX,psize+[BX]
|
||||
cmp AX,PAGESIZE ; is page larger than default page size?
|
||||
ja fix_big ; if a "large" page, must fix memory tables
|
||||
jmp swpret
|
||||
swpv030: mov nextcell+[BX],END_LIST ; Indicate no free pool
|
||||
swpv040: jmp swpret
|
||||
|
||||
; Process page of ports-- close any open files before salvaging memory
|
||||
swpport:
|
||||
xor SI,SI
|
||||
mov DI,-1
|
||||
push BX ; save page table index
|
||||
mov BX,psize+[BX] ; load size of current page and
|
||||
sub BX,PTRSIZE ; adjust for boundary check
|
||||
swpploop: mov DX,ES:[SI].pt_len ; load length of current object
|
||||
markedp ES:[SI].port_gc,swpp020 ; branch if object referenced
|
||||
cmp ES:[SI].pt_type,FREETYPE
|
||||
je not_file
|
||||
; Object not referenced-- is it an open file?
|
||||
test ES:[SI].pt_pflgs,WINDOW+STRIO
|
||||
; is this a file or a window?
|
||||
jnz not_file ; if a window, don't bother with close (jump)
|
||||
test ES:[SI].pt_pflgs,OPEN ; is file opened?
|
||||
jz not_open ; if not open, skip close (jump)
|
||||
; Close the file
|
||||
push BX ; save BX across call
|
||||
mov BX,ES:[SI].pt_handl ; load handle
|
||||
push BX ; and push as argument
|
||||
extrn zclose:near
|
||||
call zclose
|
||||
pop BX ; drop argument off stack
|
||||
pop BX ; restore register BX
|
||||
not_file:
|
||||
not_open:
|
||||
; Object not referenced-- can we combine with previous free area?
|
||||
cmp DI,0
|
||||
jge swpp010 ; If prev obj free, branch
|
||||
; Object not referenced, but previous area was
|
||||
mov ES:[SI].pt_type,FREETYPE ; Mark this object as free
|
||||
mov DI,SI ; Record this fact for next iteration
|
||||
jmp short swppnxt
|
||||
; Object was not referenced and can be combined with prev free area
|
||||
swpp010: add ES:[DI].pt_len,DX ; add length into previous free obj
|
||||
jmp short swppnxt
|
||||
; Object was referenced
|
||||
swpp020: and ES:[SI].port_gc,NOT_GC_BI ; clear gc bit
|
||||
mov DI,-1 ; Remember last object was referenced
|
||||
; Processing of current object finished-- add length and iterate
|
||||
swppnxt: add SI,DX ; Increment area pointer by block length
|
||||
cmp SI,BX ; Last object in block?
|
||||
jb swpploop ; Branch, if more space
|
||||
jmp swppfin ; complete processing
|
||||
|
||||
public fix_big
|
||||
; Restore memory management tables due to release of large page
|
||||
fix_big label near
|
||||
mov AX,PAGESIZE ; update page size of large page to
|
||||
xchg AX,psize+[BX] ; the default page size
|
||||
LoadPage DX,BX ; load para address of large page
|
||||
IFDEF EXTMEM
|
||||
and pagetabl+[BX],0FF00h
|
||||
ENDIF
|
||||
IFDEF PROMEM
|
||||
mov CX,8 ; amount to get to next selector
|
||||
ELSE
|
||||
mov CX,PAGESIZE ; CX <- PAGESIZE/16
|
||||
shr CX,1
|
||||
shr CX,1
|
||||
shr CX,1
|
||||
shr CX,1
|
||||
ENDIF
|
||||
mov BX,PAGESIZE
|
||||
fix_lop: sub AX,PAGESIZE ; decrease extended page size by one page
|
||||
jbe fix_ret ; if all pages fixed, return
|
||||
add DX,CX ; compute pointer to next physical page
|
||||
mov SI,DEDPAGES*2 ; initialize page table index
|
||||
fix_more: push BX
|
||||
LoadPage BX,SI ; is this the page we're looking for?
|
||||
cmp DX,BX
|
||||
pop BX
|
||||
je fix_fnd ; if so, jump
|
||||
inc SI ; increment the page table index
|
||||
inc SI ; twice
|
||||
cmp SI,NUMPAGES*2 ; more pages?
|
||||
jl fix_more ; if so, jump
|
||||
lea BX,m_fix_er ; error-- loop should not exit
|
||||
push BX
|
||||
mov AX,DS ; set TIPC register ES for call to
|
||||
mov ES,AX ; Lattice C routines
|
||||
C_call print_an ; print error message and exit
|
||||
fix_fnd: mov psize+[SI],BX ; reset page size to default
|
||||
mov attrib+[SI],0 ; reset "no memory" bit in attribute table
|
||||
IFDEF EXTMEM
|
||||
and pagetabl+[SI],0FF00h ; strip attributes
|
||||
ENDIF
|
||||
mov ptype+[SI],FREETYPE*2 ; mark page as free
|
||||
jmp short fix_lop ; continue to free extended pages
|
||||
fix_ret: jmp swpret ; all pages released-- return
|
||||
; Branch table for processing each data type
|
||||
btable dw swplist ; [0] List cells
|
||||
dw swpfix ; [1] Fixnums
|
||||
dw swpflo ; [2] Flonums
|
||||
dw swpbig ; [3] Bignums
|
||||
dw swpsym ; [4] Symbols
|
||||
dw swpstr ; [5] Strings
|
||||
dw swpary ; [6] Arrays
|
||||
dw swpcont ; [7] Continuations
|
||||
dw swpclos ; [8] Closures
|
||||
dw swpfree ; [9] Free space (unallocated)
|
||||
dw swpcode ; [10] Code
|
||||
dw swpref ; [11] Reference cells
|
||||
dw swpport ; [12] Port data objects
|
||||
dw swpchar ; [13] Characters
|
||||
dw swpenv ; [14] Environments
|
||||
|
||||
swpage endp
|
||||
prog ends
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Interpreter Local Data *
|
||||
;* *
|
||||
;* (C) Copyright 1984 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 2 May 1984 *
|
||||
;* Last Modification: 7 June 1984 *
|
||||
;***************************************
|
||||
; Arguments and local storage for "sinterp"
|
||||
sint_arg struc
|
||||
save_SI dw ? ; place to save the PC ([SI])
|
||||
save_ES dw ? ; place to save ES:
|
||||
save_DI dw ? ; place to save DI
|
||||
save_AX dw ? ; place to save AX
|
||||
save_BX dw ? ; place to save BX
|
||||
save_CX dw ? ; place to save CX
|
||||
save_DX dw ? ; place to save DX
|
||||
C_ES dw ? ; ES: needed by C routines
|
||||
temp_reg dw 2 dup (?) ; temp register
|
||||
sint_BP dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
cod_ent dw ? ; &entry offset
|
||||
no_insts dw ? ; number of instructions to interpret
|
||||
sint_arg ends
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,20 @@
|
|||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Interpreter Macros *
|
||||
;* *
|
||||
;* (C) Copyright 1984 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 2 May 1984 *
|
||||
;* Last Modification: 14 Sept. 1984 *
|
||||
;***************************************
|
||||
; Call "printf" to produce error message
|
||||
error macro args
|
||||
irp txt,<args>
|
||||
lea BX,txt
|
||||
push BX
|
||||
endm
|
||||
jmp printf_c
|
||||
endm
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
; =====> SIO.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* I/O Utilities *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: June 1984 *
|
||||
;* Last Modification: 09 July 1985 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;For space and performance reasons, some procedures have been written in the
|
||||
; following style: the arguments are popped off the stack, and the
|
||||
; procedure ends in an indirect JMP instead of a RET. In this source file,
|
||||
; the following are such procedures:
|
||||
; isspace, copybig
|
||||
|
||||
; Find approximate space left on stack
|
||||
; Caling sequence: stkspc()
|
||||
extrn _base:word
|
||||
public stkspc
|
||||
stkspc proc near
|
||||
mov AX,SP
|
||||
sub AX,DGROUP:_base
|
||||
ret
|
||||
stkspc endp
|
||||
|
||||
; Parse input integer
|
||||
; Calling sequence: buildint(work,buf,base)
|
||||
; Where ---- work: pointer to some workspace
|
||||
; buf: pointer to integer characters
|
||||
; base: numeric base
|
||||
int_args struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
bigptr dw ? ;Pointer to workspace
|
||||
atptr dw ? ;Pointer to integer characters
|
||||
bas dw ? ;Numeric base
|
||||
int_args ends
|
||||
public buildint
|
||||
buildint proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
cld ;Direction forward
|
||||
mov SI,[BP].atptr ;Point DS:SI to characters
|
||||
lodsb ;Fetch first character
|
||||
cmp AL,'-' ;Negative?
|
||||
pushf ;Save ZF
|
||||
je negint ;Jump if negative
|
||||
cmp AL,'+' ; or if signed positive
|
||||
je negint
|
||||
dec SI ;Point SI back to first char
|
||||
negint: mov CX,1 ;At first, bignum is one word
|
||||
add word ptr[BP].bigptr,3 ;Point BIGPTR to bignum proper
|
||||
skiplp: lodsb ;Get first number char
|
||||
cmp AL,'#' ;We know the base - skip all #x's
|
||||
jne skipped ;All #x's skipped - parse number
|
||||
inc SI ;Otherwise check again
|
||||
jmp skiplp
|
||||
biglp: lodsb ;Get next int character
|
||||
skipped: mov DI,[BP].bigptr ;Point ES:DI to workspace
|
||||
sub AL,'0' ;Character -> number
|
||||
js bigend ;Jump if number ended
|
||||
cmp AL,9 ;Jump if ordinary digit
|
||||
jbe orddig
|
||||
and AL,7 ;Otherwise, parse extra hex digit
|
||||
add AL,9
|
||||
orddig: xor AH,AH ;Clear AH
|
||||
call bigx10 ;Multiply bignum by 10, adding digit
|
||||
jmp biglp
|
||||
bigend: sub DI,3 ;Point DI back to start of buffer
|
||||
mov AX,CX ;Save integer size
|
||||
stosw
|
||||
xor AL,AL ;Clear AX
|
||||
popf ;Get number's sign
|
||||
jne stosgn ;Store it
|
||||
inc AL
|
||||
stosgn: mov [DI],AL
|
||||
pop BP ;Restore BP
|
||||
ret
|
||||
;BIGX10: Multiply bignum at ES:[DI], size=CX words, by BASE and add AX
|
||||
bigx10: push CX
|
||||
mov DX,AX ;Transfer digit to add
|
||||
cld
|
||||
x10lp: mov AX,[DI] ;Get word to multiply
|
||||
call wordx10 ;Multiply word by 10
|
||||
stosw ;Replace result
|
||||
loop x10lp ;Loop 'til done
|
||||
pop CX ;Restore CX
|
||||
or DX,DX ;Does a carry remain?
|
||||
jz samlen ;Jump if not
|
||||
mov ES:[DI],DX ;Otherwise, enlarge bignum
|
||||
inc CX
|
||||
samlen: ret
|
||||
;WORDX10: Multiply AX by BASE and add DX; product in AX, carry in DX
|
||||
wordx10: push CX ;Save value of CX
|
||||
push DX ;Save carry in
|
||||
mul word ptr[BP].bas ;Multiply by BASE
|
||||
pop CX ;Restore carry to CX
|
||||
add AX,CX ;Add carry
|
||||
adc DX,0
|
||||
pop CX ;Restore CX
|
||||
ret
|
||||
buildint endp
|
||||
|
||||
; Copy bignum data to a math buffer
|
||||
; Calling sequence: copybig(pg,ds,buf)
|
||||
; Where: pg,ds ---- page & displacement of bignum
|
||||
; buf ------ pointer to math buffer
|
||||
cb_args struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
cbpg dw ? ;Page
|
||||
cbds dw ? ;Displacement
|
||||
cbbuf dw ? ;Buffer pointer
|
||||
cb_args ends
|
||||
public copybig
|
||||
copybig proc near
|
||||
pop BX ;Pop return address to BX
|
||||
mov DX,DS ;Save DS in DX
|
||||
pop SI ;Fetch logical page number
|
||||
sal SI,1 ;Convert
|
||||
LoadPage DS,SI ;Get page segment
|
||||
;;; mov DS,DGROUP:pagetabl+[SI] ;Get page segment
|
||||
pop SI ;Get displacement
|
||||
mov AX,[SI]+1 ;Get size of bignum proper (words)
|
||||
sub AX,4
|
||||
shr AX,1
|
||||
add SI,3 ;Point DS:SI to sign byte
|
||||
pop DI ;Point ES:DI to math buffer
|
||||
cld ;Direction forward
|
||||
stosw ;Store bignum size in math buffer
|
||||
movsb ;Copy sign byte
|
||||
mov CX,AX ;Copy bignum proper
|
||||
rep movsw
|
||||
mov DS,DX ;Restore DS
|
||||
jmp BX ;Return
|
||||
copybig endp
|
||||
|
||||
; Convert buffered bignum to ASCII
|
||||
; Calling sequence: big2asc(mathbuf,charbuf)
|
||||
; Where: mathbuf --- pointer to buffered bignum
|
||||
; charbuf --- pointer to ASCII charcater array
|
||||
b2a struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
mbuf dw ? ;Math buffer
|
||||
cbuf dw ? ;Character buffer
|
||||
b2a ends
|
||||
public big2asc
|
||||
big2asc proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov SI,[BP].mbuf ;Fetch math buffer pointer
|
||||
mov DI,[BP].cbuf ;Fetch character buffer pointer
|
||||
cld ;Direction forward
|
||||
lodsw ;Fetch bignum size
|
||||
mov CX,AX
|
||||
lodsb ;Fetch sign
|
||||
test AL,1 ;Skip on positive bignum
|
||||
jz posbig
|
||||
mov AL,'-' ;First character: minus
|
||||
stosb
|
||||
posbig: mov BX,10 ;Set divisor to 10
|
||||
and AX,1 ;Push 0 or 1 (1 if start with -)
|
||||
prtbglp: push AX
|
||||
call divbig ;Divide bignum by 10
|
||||
mov AL,DL ;Store digit
|
||||
add AL,'0'
|
||||
stosb
|
||||
pop AX ;Increment character counter
|
||||
inc AX
|
||||
or CX,CX ;Loop until bignum is zeroed
|
||||
jnz prtbglp
|
||||
mov CX,AX ;Transfer & save character count
|
||||
push AX
|
||||
sub DI,CX ;Point DI to beginning of string
|
||||
call reverse ;Reverse digits in ASCII bignum
|
||||
pop AX ;Restore character count
|
||||
pop BP
|
||||
ret
|
||||
;Divide bignum at DS:SI, length CX words, by BX (ES=DS)
|
||||
divbig: push CX ;Save count
|
||||
push DI ;Save DI
|
||||
add SI,CX ;Point SI to last word (most signif.)
|
||||
add SI,CX
|
||||
sub SI,2
|
||||
cmp [SI],BX ;Will working length be reduced?
|
||||
pushf
|
||||
mov DI,SI ;ES:DI = DS:SI
|
||||
std ;Direction backward
|
||||
xor DX,DX ;Clear carry in
|
||||
divlp: lodsw ;Fetch piece of dividend
|
||||
div BX
|
||||
stosw ;Store quotient (retain remainder)
|
||||
loop divlp
|
||||
add SI,2 ;Point SI again to first word
|
||||
popf
|
||||
pop DI
|
||||
pop CX
|
||||
jae divdone ;Jump if bignum length not reduced
|
||||
dec CX
|
||||
divdone: ret ;Remainder left in DX
|
||||
;Reverse the string containing CX characters at ES:DI (ES=DS)
|
||||
reverse: cmp byte ptr[DI],'-' ;Start with minus?
|
||||
jne revpos ;No, reverse whole string
|
||||
inc DI ;Otherwise, don't include minus in reverse
|
||||
dec CX
|
||||
revpos: mov SI,DI ;Point SI to last string char
|
||||
add SI,CX
|
||||
dec SI
|
||||
shr CX,1 ;Number of switches
|
||||
or CX,CX ;Jump if no switches to make
|
||||
jz revend
|
||||
revlp: mov AL,[DI] ;Exchange outside bytes
|
||||
xchg AL,[SI]
|
||||
stosb
|
||||
dec SI ;Move pointers inward
|
||||
loop revlp
|
||||
revend: ret
|
||||
big2asc endp
|
||||
|
||||
; Is character a whitespace?
|
||||
; Calling sequence: isspace(ch)
|
||||
; Where ch = character to check
|
||||
; Returns zero iff not a whitespace
|
||||
; NOTE: Before use, the C macro ISSPACE must not be defined
|
||||
isspargs struc
|
||||
dw ? ;Return address
|
||||
issparg dw ? ;Argument
|
||||
isspargs ends
|
||||
public isspace
|
||||
isspace proc near
|
||||
pop DI ;Get return address
|
||||
pop AX ;Get argument
|
||||
cmp AL,' '
|
||||
je issp
|
||||
cmp AL,9
|
||||
jb isntsp
|
||||
cmp AL,13
|
||||
jbe issp
|
||||
isntsp: xor AX,AX ;Set to zero
|
||||
issp: jmp DI ;Return
|
||||
isspace endp
|
||||
|
||||
; Save stack pointer in case of abort
|
||||
; Calling sequence: setabort()
|
||||
; NOTE: Due to the program-sensitive nature of this routine, a call to
|
||||
; SETABORT MUST be the very first in a C routine, and there must be
|
||||
; NO preassigned local variables.
|
||||
public setabort
|
||||
setabort proc near
|
||||
mov BX,SP ;Fetch stack pointer
|
||||
mov SI,SS:[BX] ;Fetch return address
|
||||
mov CL,CS:[SI-6] ;Fetch byte just before MOV BP,SP
|
||||
cmp CL,55h ;Compare with PUSH BP opcode
|
||||
je nolocal ;Jump if no extra stack space allocated
|
||||
xor CH,CH ;Clear CH
|
||||
add BX,CX ;Discount extra stack space
|
||||
nolocal: add BX,2 ;Discount SETABORT's return address
|
||||
mov DGROUP:abadr,BX ;Save pointer
|
||||
ret
|
||||
setabort endp
|
||||
|
||||
; Abort & set stack to saved pointer
|
||||
; Calling sequence: abort(code)
|
||||
; where: code ---- type of error message to print
|
||||
public abort
|
||||
abort proc
|
||||
pop AX ;Discard return address (leaving CODE)
|
||||
C_call errmsg ;Print error message
|
||||
pop AX ;Get "value"
|
||||
mov SP,DGROUP:abadr ;Restore stack for abort
|
||||
pop BP ;Restore BP
|
||||
ret ;Return (from aborted operation)
|
||||
abort endp
|
||||
prog ends
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* =====> SLINK.H */
|
||||
/* PC Scheme Lattice C Macros to Support Scheme to C Interface
|
||||
Copyright 1985 by Texas Instruments Incorporated.
|
||||
All Rights Reserved.
|
||||
|
||||
Author: John C. Jensen
|
||||
Installation: Texas Instruments Incorporated, Dallas, Texas
|
||||
Division: Central Research Laboratories
|
||||
Cost Center: Computer Science Laboratory
|
||||
Project: Computer Architecture Branch
|
||||
Date Written: 22 June 1985
|
||||
Last Modification: 23 June 1985
|
||||
|
||||
Purpose: The macros within this module provide the capability to
|
||||
fetch values passed from the Scheme Runtime and return
|
||||
values to the Scheme Runtime.
|
||||
|
||||
Description: For a description of parameter passing conventions, see the
|
||||
module header in the file SLINK.C.
|
||||
*/
|
||||
|
||||
#define INTEGER(x) *((int *)x)
|
||||
#define LONG_INTEGER(x) *x
|
||||
#define FLOAT(x) *((float *)x)
|
||||
#define DOUBLE(x) *((double *)x)
|
||||
#define CHARACTER(x) *((char *)x)
|
||||
#define STRING(x) ((char*)x)
|
||||
|
||||
#define RETURN_NOVALUE() return(0)
|
||||
#define RETURN_T_OR_NIL(x) **result = (x); return(1)
|
||||
#define RETURN_INTEGER(x) **result = (x); return(2)
|
||||
#define RETURN_FLONUM(x) *((double *) *result) = (x); return(3)
|
||||
#define RETURN_CHARACTER(x) *((char *) *result) = (x); return(4)
|
||||
#define RETURN_STRING(x) t_=(x);if(t_){*result=(long *)t_;return(5);}else{**result=0;return(1);}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/************************************************************************/
|
||||
/* C Equivalents for Scheme List Operations */
|
||||
/* */
|
||||
/* Copyright 1985 by Texas Instruments Incorporated. */
|
||||
/* All Rights Reserved. */
|
||||
/* */
|
||||
/* Date Written: 29 March 1985 */
|
||||
/* Last Modification: 1 April 1985 */
|
||||
/************************************************************************/
|
||||
|
||||
/* copy contents of one "register" to another */
|
||||
#define mov_reg(dest,src) dest[C_PAGE]=src[C_PAGE]; dest[C_DISP]=src[C_DISP]
|
||||
|
||||
/* test equality (eq? -ness) of two registers */
|
||||
#define eq(r1,r2) (r1[C_DISP] == r2[C_DISP] && r1[C_PAGE] == r2[C_PAGE])
|
||||
|
||||
/* take caar of a "register" */
|
||||
#define take_caar(reg) take_car(reg); take_car(reg)
|
||||
|
||||
/* take cadr of a "register" */
|
||||
#define take_cadr(reg) take_cdr(reg); take_car(reg)
|
||||
|
||||
/* take cddr of a "register" */
|
||||
#define take_cddr(reg) take_cdr(reg); take_cdr(reg)
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
name SMMU
|
||||
title Scheme Memory Management Utilities
|
||||
page 62,132
|
||||
; =====> SMMU.ASM
|
||||
;****************************************************************
|
||||
;* TIPC Scheme '84 Memory Management Utilities *
|
||||
;* *
|
||||
;* (C) Copyright 1985, 1987 by Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Author: Terry Caudill *
|
||||
;* Date written: 18 March 1986 *
|
||||
;* History: *
|
||||
;* rb 4/ 5/87 "getbase" returns a page's swap state in carry *
|
||||
;* (for compatibility with PCSEXT and PCSEXP) *
|
||||
;****************************************************************
|
||||
include schemed.equ
|
||||
include schemed.ref
|
||||
|
||||
DOS equ 021h
|
||||
|
||||
DGROUP group data
|
||||
PGROUP group prog
|
||||
|
||||
data segment word public 'DATA'
|
||||
assume ds:DGROUP
|
||||
extrn page0:byte, page4:byte, page5:byte, page6:byte
|
||||
extrn page7:byte, page8:byte
|
||||
|
||||
extrn _top:word, _paras:word,first_pa:word,first_dos:word
|
||||
|
||||
public GC_ING
|
||||
GC_ING dw 0
|
||||
|
||||
data ends
|
||||
|
||||
|
||||
prog segment byte public 'PROG'
|
||||
assume cs:PGROUP
|
||||
|
||||
;;======================================================================
|
||||
;;
|
||||
;; Get page base address of page
|
||||
;;
|
||||
;; On exit, carry is clear to indicate page is always in memory
|
||||
;; (for compatibility with extended and expanded versions of this routine)
|
||||
;;
|
||||
;;======================================================================
|
||||
|
||||
public getbase
|
||||
getbase proc near
|
||||
push BP
|
||||
mov BP,SP
|
||||
mov BX,word ptr [BP+4]
|
||||
mov AX,word ptr [BX+pagetabl] ;; Get table indicator
|
||||
clc ;; page always avail in conv. memory
|
||||
pop BP
|
||||
ret
|
||||
|
||||
getbase endp
|
||||
|
||||
;;======================================================================
|
||||
;;
|
||||
;; InitMem()
|
||||
;; Compute the best page size, but not smaller than MIN_PAGESIZE
|
||||
;;
|
||||
;;======================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
public InitMem
|
||||
InitMem proc near
|
||||
push BP
|
||||
sub SP,2 ;; Local storage
|
||||
mov BP,SP
|
||||
|
||||
mov BX,DS
|
||||
mov ES,BX ;; Ensure ES = DS
|
||||
|
||||
;; Convert offset within pagetabl[0] into paragraph address
|
||||
|
||||
mov DI,offset pagetabl
|
||||
mov AX,word ptr [DI]
|
||||
mov CX,4
|
||||
shr AX,CL
|
||||
add AX,BX
|
||||
mov word ptr [DI],AX
|
||||
|
||||
;; Same for pagetabl[4] through pagetabl[8]
|
||||
|
||||
mov DX,5
|
||||
mov DI,offset pagetabl[8]
|
||||
EmmP$0:
|
||||
mov AX,word ptr [DI]
|
||||
shr AX,CL
|
||||
add AX,BX
|
||||
mov word ptr [DI],AX
|
||||
add DI,2
|
||||
dec DX
|
||||
jnz EmmP$0
|
||||
|
||||
;; Allocate all the memory that DOS will give us.
|
||||
|
||||
mov BX,0FFFFh ;; first ask for too much
|
||||
mov AH,048h
|
||||
int DOS ;; DOS gets an error, but tells us
|
||||
;; in BX how much we CAN get
|
||||
mov AH,048h
|
||||
int DOS ;; reissue allocation request
|
||||
mov first_dos,AX ;; save address for returning it to DOS
|
||||
mov first_pa,AX ;; save address for Scheme heap
|
||||
|
||||
;; Compute the best page size, but not smaller than MIN_PAGESIZE
|
||||
|
||||
mov AX,_paras ;; max number of paragraphs
|
||||
sub AX,first_pa ;; subtract first paragragh
|
||||
xor DX,DX ;; get ready for divide
|
||||
mov CX,NUMPAGES-PreAlloc ;; CX <= number heap allocated pages
|
||||
idiv CX ;; AX <= paras-per-page
|
||||
|
||||
mov DX,(MIN_PAGESIZE shr 4)
|
||||
cmp AX,DX ;; If paras-per-page < MIN_PAGESIZE/16
|
||||
jge EmmP$05 ;; then
|
||||
mov AX,DX ;; paras-per-page = MIN_PAGESIZE/16
|
||||
EmmP$05:
|
||||
mov [BP],AX ;; Save paras-per-page
|
||||
|
||||
;; Pagesize = (paras-per-page * 16)
|
||||
|
||||
mov CX,4
|
||||
shl AX,CL
|
||||
mov pagesize,AX
|
||||
mov SI,AX
|
||||
|
||||
;; Initialize page management table
|
||||
|
||||
xor CX,CX ;; Keep number of pages in CX
|
||||
mov DX,nextpage
|
||||
mov freepage,DX ;; freepage = nextpage
|
||||
mov AX,first_pa ;; AX <= next paragraph
|
||||
mov DI,_paras ;; DI <= (_paras - paras per page)
|
||||
sub DI,[BP]
|
||||
EmmP$1:
|
||||
cmp DI,AX ;; Did we reach it
|
||||
jb EmmP$2 ;; Yes...no more
|
||||
cmp DX,NUMPAGES ;; See if we have filled the table
|
||||
jae EmmP$2
|
||||
mov BX,DX
|
||||
shl BX,1
|
||||
mov word ptr [BX+pagetabl],AX
|
||||
mov word ptr [BX+psize],SI
|
||||
and word ptr [BX+attrib],not NOMEMORY
|
||||
inc DX
|
||||
mov word ptr [BX+pagelink],DX
|
||||
mov word ptr [BX+nextcell],0
|
||||
inc CX ;; page_count++
|
||||
add AX,[BP] ;; nextpara = nextpara + para per page
|
||||
jmp EmmP$1
|
||||
EmmP$2:
|
||||
mov nextpage,DX ;; nextpage = lastpage
|
||||
mov lastpage,DX
|
||||
mov AX,CX
|
||||
pop BP
|
||||
pop BP
|
||||
ret
|
||||
|
||||
InitMem endp
|
||||
|
||||
prog ends
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
;*******************************************************************************
|
||||
;* TIPC Scheme '84 Runtime Support - Assembler Macros *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Memory and Machine specific macros to aid in the building specific *
|
||||
;* of PC Scheme. There are four versions of the PC Scheme system: *
|
||||
;* 1. Conventional Memory Scheme *
|
||||
;* 2. Expanded Memory Scheme *
|
||||
;* 3. Extended Memory Scheme *
|
||||
;* 4. Protected Mode Scheme *
|
||||
;* These macros create version specific code for each of the above schemes. *
|
||||
;* The Macro assembler symbols REGMEM, EXPMEM, EXTMEM, and PROMEM are used *
|
||||
;* to conditionally define the correct macros. It can be (and must be) *
|
||||
;* specified on the MASM command line during the assembly phase as follows: *
|
||||
;* MASM /DREGMEM srcfile,objfile,... *
|
||||
;* *
|
||||
;* Date Written: 29 July 1987 *
|
||||
;* *
|
||||
;* *
|
||||
;*******************************************************************************
|
||||
|
||||
|
||||
;;;
|
||||
;;; Macros for conventional memory version - default
|
||||
;;;
|
||||
|
||||
; The LoadPage macros should be used to obtain the address of a given page
|
||||
; from the pagetable. This must be done in order to access any given heap
|
||||
; allocated object. For conventional memory, this just means indexing into
|
||||
; the pagetable and accessing the paragraph address, however for extended
|
||||
; and expanded memories, it is quite different. See the macro definitions
|
||||
; for EXPMEM and EXTMEM for definitions for expanded and extended memorys.
|
||||
|
||||
LoadPage MACRO dst,src ; Get Page address from page table
|
||||
IFIDN <src>,<BX>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
IFIDN <src>,<bx>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
IFIDN <src>,<DI>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
IFIDN <src>,<di>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
IFIDN <src>,<DI>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
IFIDN <src>,<si>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
IFIDN <src>,<SI>
|
||||
mov dst,[SS:pagetabl+src]
|
||||
ELSE
|
||||
push BX
|
||||
mov BX,src
|
||||
mov dst,[SS:pagetabl+BX]
|
||||
pop BX
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDM
|
||||
|
||||
%LoadPage MACRO dst,src
|
||||
LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
%LoadPage0 MACRO dst,src
|
||||
LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
%LoadPage1 MACRO dst,src
|
||||
LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
LoadCode MACRO dst,src
|
||||
LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
; The following macros should be used whenever saving some value in a
|
||||
; location within the code segment. For real mode, you may store anything
|
||||
; within the code segment, however in protected mode, this causes a
|
||||
; protection violation. See the macro expansions for PROMEM to see how
|
||||
; this may be accomplished in protected mode.
|
||||
|
||||
STORE_WORD_IN_CS MACRO SEG,OFFSET,VALUE
|
||||
mov word ptr CS:OFFSET,VALUE
|
||||
ENDM
|
||||
|
||||
STORE_BYTE_IN_CS MACRO SEG,OFFSET,VALUE
|
||||
mov byte ptr CS:OFFSET,VALUE
|
||||
ENDM
|
||||
|
||||
XCHG_WORD_IN_CS MACRO SEG,OFFSET,VALUE
|
||||
xchg word ptr CS:OFFSET,VALUE
|
||||
ENDM
|
||||
|
||||
|
||||
IFDEF REGMEM
|
||||
; Access to pagetabl for LoadPage macros
|
||||
extrn pagetabl:word
|
||||
ENDIF
|
||||
|
||||
|
||||
;;;
|
||||
;;; Macros for expanded memory version
|
||||
;;;
|
||||
|
||||
IFDEF EXPMEM
|
||||
; get rid of default conventional memory definitions
|
||||
purge LoadPage,%LoadPage,%LoadPage0,%LoadPage1,LoadCode
|
||||
|
||||
; Load page address
|
||||
extrn _MMU:near
|
||||
LoadPage MACRO dst,src
|
||||
push src
|
||||
call _MMU
|
||||
pop dst
|
||||
ENDM
|
||||
|
||||
; Load code block
|
||||
extrn _MMUCB:near
|
||||
LoadCode MACRO dst,src
|
||||
push src
|
||||
call _MMUCB
|
||||
pop dst
|
||||
ENDM
|
||||
|
||||
; SAME AS LoadPage EXCEPT CALLABLE FROM PROGX SEGMENT
|
||||
extrn _%MMU:far
|
||||
%LoadPage MACRO dst,src
|
||||
IF1
|
||||
IFIDN <dst>,<AX>
|
||||
%OUT *AX as destination of %LoadPage not recommended*
|
||||
ELSE
|
||||
IFIDN <dst>,<ax>
|
||||
%OUT *AX as destination of %LoadPage not recommended*
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
push AX
|
||||
mov AX,src
|
||||
call _%MMU
|
||||
mov dst,AX
|
||||
pop AX
|
||||
ENDM
|
||||
|
||||
; Loads only Emm page 0
|
||||
extrn _%MMU0:far
|
||||
%LoadPage0 MACRO dst,src
|
||||
IF1
|
||||
IFIDN <dst>,<AX>
|
||||
%OUT *AX as destination of %LoadPage0 not recommended*
|
||||
ELSE
|
||||
IFIDN <dst>,<ax>
|
||||
%OUT *AX as destination of %LoadPage0 not recommended*
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
push AX
|
||||
mov AX,src
|
||||
call _%MMU0
|
||||
mov dst,AX
|
||||
pop AX
|
||||
ENDM
|
||||
|
||||
; Loads only Emm page 1
|
||||
extrn _%MMU1:far
|
||||
%LoadPage1 MACRO dst,src
|
||||
IF1
|
||||
IFIDN <dst>,<AX>
|
||||
%OUT *AX as destination of %LoadPage1 not recommended*
|
||||
ELSE
|
||||
IFIDN <dst>,<ax>
|
||||
%OUT *AX as destination of %LoadPage1 not recommended*
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
push AX
|
||||
mov AX,src
|
||||
call _%MMU1
|
||||
mov dst,AX
|
||||
pop AX
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
|
||||
;;;
|
||||
;;; Macros for extended memory version
|
||||
;;;
|
||||
|
||||
|
||||
IFDEF EXTMEM
|
||||
; get rid of default conventional memory definitions
|
||||
purge LoadPage,%LoadPage,%LoadPage0,%LoadPage1,LoadCode
|
||||
|
||||
; Load page address
|
||||
extrn _MMU:near
|
||||
LoadPage MACRO dst,src
|
||||
push src
|
||||
call _MMU
|
||||
pop dst
|
||||
ENDM
|
||||
|
||||
; SAME AS LoadPage EXCEPT CALLABLE FROM PROGX SEGMENT
|
||||
extrn _%MMU:far
|
||||
%LoadPage MACRO dst,src
|
||||
IF1
|
||||
IFIDN <dst>,<AX>
|
||||
%OUT *AX as destination of %LoadPage not recommended*
|
||||
ELSE
|
||||
IFIDN <dst>,<ax>
|
||||
%OUT *AX as destination of %LoadPage not recommended*
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
push AX
|
||||
mov AX,src
|
||||
call _%MMU
|
||||
mov dst,AX
|
||||
pop AX
|
||||
ENDM
|
||||
|
||||
; The following macros are provided for comatibility with the
|
||||
; Expanded memory version. They just perform a LoadPage.
|
||||
|
||||
; Load code block
|
||||
LoadCode MACRO dst,src
|
||||
LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
%LoadPage0 MACRO dst,src
|
||||
%LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
%LoadPage1 MACRO dst,src
|
||||
%LoadPage dst,src
|
||||
ENDM
|
||||
|
||||
ENDIF
|
||||
|
||||
|
||||
;;;
|
||||
;;; Macros for protected mode version
|
||||
;;;
|
||||
|
||||
IFDEF PROMEM
|
||||
; get rid of default real mode definitions
|
||||
purge STORE_WORD_IN_CS,STORE_BYTE_IN_CS,XCHG_WORD_IN_CS
|
||||
|
||||
; Access to pagetabl for LoadPage macros
|
||||
extrn pagetabl:word
|
||||
|
||||
STORE_WORD_IN_CS MACRO SEG,OFFSET,VALUE
|
||||
push DS
|
||||
push AX
|
||||
mov AX,CS
|
||||
and AX,0FFF7H
|
||||
mov DS,AX
|
||||
pop AX
|
||||
assume DS:SEG
|
||||
mov word ptr DS:OFFSET,VALUE
|
||||
assume DS:DGROUP
|
||||
pop DS
|
||||
ENDM
|
||||
|
||||
STORE_BYTE_IN_CS MACRO SEG,OFFSET,VALUE
|
||||
push DS
|
||||
push AX
|
||||
mov AX,CS
|
||||
and AX,0FFF7H
|
||||
mov DS,AX
|
||||
pop AX
|
||||
assume DS:SEG
|
||||
mov byte ptr DS:OFFSET,VALUE
|
||||
assume DS:DGROUP
|
||||
pop DS
|
||||
ENDM
|
||||
|
||||
XCHG_WORD_IN_CS MACRO SEG,OFFSET,VALUE
|
||||
push DS
|
||||
push AX
|
||||
mov AX,CS
|
||||
and AX,0FFF7H
|
||||
mov DS,AX
|
||||
pop AX
|
||||
assume DS:SEG
|
||||
xchg word ptr DS:OFFSET,VALUE
|
||||
assume DS:DGROUP
|
||||
pop DS
|
||||
ENDM
|
||||
|
||||
|
||||
ENDIF
|
|
@ -0,0 +1,458 @@
|
|||
; =====> SOBJHASH.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* Object Hashing Routines *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 25 June 1985 *
|
||||
;* Last Modification: 3 November 1985 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
XGROUP group PROGX
|
||||
PGROUP group prog
|
||||
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
obj_cntr dw OHT_SIZE dup (1)
|
||||
branchtab dw ogc_list ; [0] List cells
|
||||
dw ogc_mark ; [1] Fixnums
|
||||
dw ogc_var ; [2] Flonums
|
||||
dw ogc_var ; [3] Bignums
|
||||
dw ogc_var ; [4] Symbols
|
||||
dw ogc_var ; [5] Strings
|
||||
dw ogc_var ; [6] Arrays
|
||||
dw ogc_var ; [7] Continuations
|
||||
dw ogc_var ; [8] Closures
|
||||
dw ogc_mark ; [9] Free page
|
||||
dw ogc_var ; [10] Code page
|
||||
dw ogc_mark ; [11] Reference cells <not anymore>
|
||||
dw ogc_var ; [12] Port data objects
|
||||
dw ogc_mark ; [13] Characters
|
||||
dw ogc_var ; [14] Environments
|
||||
ret_sav1 dw 0 ; return address save area
|
||||
ret_sav2 dw 0 ; return address save area
|
||||
data ends
|
||||
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to "lookup" Routine *
|
||||
;************************************************************************
|
||||
%lookup proc far
|
||||
extrn lookup:near
|
||||
call lookup
|
||||
ret
|
||||
%lookup endp
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to "cons" Routine *
|
||||
;************************************************************************
|
||||
public %cons
|
||||
%cons proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
mov AX,DS ; make ES point to the data segment
|
||||
mov ES,AX
|
||||
extrn cons:near
|
||||
call cons
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%cons endp
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to "alloc_block" Routine *
|
||||
;************************************************************************
|
||||
public %allocbl
|
||||
%allocbl proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
mov AX,DS ; make ES point to the data segment
|
||||
mov ES,AX
|
||||
extrn alloc_bl:near
|
||||
call alloc_bl
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%allocbl endp
|
||||
prog ends
|
||||
|
||||
PROGX segment byte public 'PROGX'
|
||||
assume CS:XGROUP
|
||||
;************************************************************************
|
||||
;* Object Hash *
|
||||
;************************************************************************
|
||||
oh_args struc
|
||||
oh_key dw ? ; computed hash key
|
||||
oh_key3 dw ? ; computed hash key * 3
|
||||
oh_disp dw ? ; page number component of a pointer
|
||||
oh_page dw ? ; displacement component of a pointer
|
||||
oh_reg dw ? ; pointer to argument register (s=d)
|
||||
oh_ctr dw ? ; bucket's current counter value
|
||||
oh_ctag db SPECFIX*2,? ; tag for counter
|
||||
oh_BP dw ? ; caller's BP
|
||||
dw ? ; caller's SI
|
||||
dw ? ; caller's ES
|
||||
dd ? ; return address (far call)
|
||||
dw ? ; return address (near call)
|
||||
oh_args ends
|
||||
|
||||
%objhash proc far
|
||||
lods byte ptr ES:[SI] ; fetch operand of object-hash
|
||||
push ES ; save the caller's ES register
|
||||
push SI ; save the location counter
|
||||
push BP ; save the caller's BP register
|
||||
sub SP,offset oh_BP ; allocate local storage
|
||||
mov BP,SP ; establish local addressability
|
||||
; load argument and compute hash index
|
||||
mov BX,AX ; copy dest=src register number to BX
|
||||
add BX,offset reg0 ; and compute the register's address
|
||||
mov [BP].oh_reg,BX ; save the register address
|
||||
;;;
|
||||
;;; Note: computing of hash value turned off 'cause relocation of
|
||||
;;; pointers screws things up. For now, all objects will
|
||||
;;; hash to a key of zero. (JCJ 2 OCT 85)
|
||||
;;; mov DX,[BX].C_page ; load the argument's page number
|
||||
;;; mov AX,[BX].C_disp ; load the argument's displacement
|
||||
;;; mov CL,AH ; copy high byte of displacement
|
||||
;;; xor AH,AH
|
||||
;;; xor CH,CH
|
||||
;;; add AX,CX
|
||||
;;; add AX,DX
|
||||
;;; mov CX,OHT_SIZE ; load the hash table size for divisor
|
||||
;;; cwd ; convert dividend to double word
|
||||
;;; div CX ; divide hash value by table size
|
||||
xor DX,DX ; ***TEMPORARY*** Load a hash key of zero
|
||||
;;;
|
||||
mov [BP].oh_key,DX ; save computed hash key
|
||||
mov SI,DX
|
||||
shl DX,1
|
||||
add SI,DX ; SI <- hash_key * 3
|
||||
mov [BP].oh_key3,SI
|
||||
|
||||
; if entries exist at this hash level, search bucket for object
|
||||
cmp obj_ht+[SI],0 ; anyone home in this bucket?
|
||||
je oh_nf ; if no entries exist, jump
|
||||
|
||||
; call "lookup" to search a-list
|
||||
mov AX,[BX].C_disp ; reload object's displacement
|
||||
mov DX,[BX].C_page ; and page for a-list search
|
||||
xor BX,BX
|
||||
mov BL,obj_ht+[SI]
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov SI,word ptr obj_ht+[SI]+1
|
||||
call %lookup ; search the a-list
|
||||
cmp BL,0
|
||||
je oh_nf
|
||||
|
||||
; object found in hash bucket's chain-- return it
|
||||
mov AX,ES:[DI].cdr ; load the hash counter
|
||||
mov [BP].oh_ctr,AX ; and save it in 'oh_ctr'
|
||||
jmp short oh_ret ; return hash value
|
||||
|
||||
; make a new entry in the current hash bucket
|
||||
oh_nf: mov DI,[BP].oh_key
|
||||
shl DI,1 ; multiply hash value by 2 for index
|
||||
mov AX,obj_cntr+[DI] ; load obj hash counter for this bucket
|
||||
inc obj_cntr+[DI] ; increment the obj hash counter
|
||||
mov [BP].oh_ctag,SPECFIX*2 ; convert hash counter to a fixnum
|
||||
mov [BP].oh_ctr,AX ; pointer
|
||||
lea BX,[BP].oh_ctr ; load hash counter's "reg" address
|
||||
mov AX,[BP].oh_reg ; load object's register address
|
||||
mov CX,offset tmp_reg ; load offset of temporary register
|
||||
pushm <BX,AX,CX> ; push arguments to call
|
||||
call %cons ; cons(tmp_reg, object, hash-counter)
|
||||
mov BX,offset nil_reg ; load address of "nil register"
|
||||
mov CX,offset tmp_reg ; load address of temporary register
|
||||
pushm <BX,CX,CX> ; push arguments to cons
|
||||
call %cons ; cons(tmp_reg, (cons obj hash), nil)
|
||||
mov SP,BP ; drop arguments from stack
|
||||
mov DI,[BP].oh_key3 ; load hash bucket number * 3
|
||||
mov BX,tmp_page ; load pointer to newest list cell
|
||||
mov AX,tmp_disp
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov SI,AX ; pointer is in ES:[SI]
|
||||
xchg obj_ht+[DI],BL ; header <- pointer to list cell
|
||||
xchg word ptr obj_ht+[DI]+1,AX
|
||||
mov ES:[SI].cdr_page,BL ; (set-cdr! list-cell chain-header)
|
||||
mov ES:[SI].cdr,AX
|
||||
|
||||
; create a bignum to hold the hash value
|
||||
oh_ret: mov AX,WORDINCR*2+1 ; load the size of bignum result
|
||||
push AX ; and push it for use as argument
|
||||
mov AX,BIGTYPE ; load type=bignum
|
||||
push AX ; and push it for use as argument
|
||||
push [BP].oh_reg ; push address of destination register
|
||||
mov AX,DS ; ES <- DS
|
||||
mov ES,AX
|
||||
call %allocbl ; allocate the bignum
|
||||
mov SP,BP ; drop arguments off the TIPC's stack
|
||||
mov BX,[BP].oh_reg ; load destination register's address
|
||||
mov SI,[BX].C_page ; load bignum's page number
|
||||
%LoadPage ES,SI ; load bignum page's paragraph address
|
||||
;;; mov ES,pagetabl+[SI] ; load bignum page's paragraph address
|
||||
mov SI,[BX].C_disp ; load bignum's displacement
|
||||
mov AX,[BP].oh_key ; load hash bucket number
|
||||
mov ES:[SI].big_data,AX ; and store it into LSW of bignum
|
||||
mov AX,[BP].oh_ctr ; load counter for this object
|
||||
mov ES:[SI].big_2nd,AX ; and store it into MSW of bignum
|
||||
mov ES:[SI].big_sign,0 ; sign <- 0 (positive number)
|
||||
|
||||
; return to caller
|
||||
add SP,offset oh_BP ; deallocate local storage
|
||||
pop BP ; restore caller's BP register
|
||||
pop SI ; restore the location pointer
|
||||
pop ES ; restore caller's ES register
|
||||
ret ; return to calling procedure
|
||||
%objhash endp
|
||||
|
||||
;************************************************************************
|
||||
;* Object Unhash *
|
||||
;************************************************************************
|
||||
unhs_arg struc
|
||||
un_reg dw ? ; argument register address
|
||||
un_BP dw ? ; caller's BP
|
||||
dw ? ; caller's SI
|
||||
dw ? ; caller's ES
|
||||
dd ? ; return address (far call)
|
||||
dw ? ; return address (near call)
|
||||
unhs_arg ends
|
||||
|
||||
%objunhs proc far
|
||||
lods byte ptr ES:[SI] ; load the operand for object-unhash
|
||||
push ES ; save the caller's ES register
|
||||
push SI ; save the location pointer
|
||||
push BP ; save the caller's BP register
|
||||
sub SP,offset un_BP ; allocate local storage
|
||||
mov BP,SP ; establish local addressability
|
||||
|
||||
; Begin the long process of validating the input
|
||||
mov SI,AX
|
||||
add SI,offset reg0
|
||||
mov [BP].un_reg,SI
|
||||
mov BX,[SI].C_page
|
||||
cmp byte ptr ptype+[BX],BIGTYPE*2
|
||||
je un_maybe
|
||||
|
||||
; This hash-key is invalid, or object not found-- return #!false
|
||||
un_false: xor AX,AX ; create a nil pointer
|
||||
mov SI,[BP].un_reg ; load destination register address
|
||||
mov byte ptr [SI].C_page,AL ; store nil pointer into
|
||||
mov [SI].C_disp,AX ; destination register
|
||||
|
||||
; Return to Scheme Interpreter
|
||||
un_ret: add SP,offset un_BP ; deallocate local storage
|
||||
pop BP ; restore caller's BP register
|
||||
pop SI ; restore the location pointer
|
||||
pop ES ; restore caller's ES register
|
||||
ret
|
||||
|
||||
; Continue checking bignum value
|
||||
un_maybe: mov SI,[SI].C_disp ; load bignum's offet
|
||||
%LoadPage ES,BX ; and paragraph address
|
||||
;;; mov ES,pagetabl+[BX] ; and paragraph address
|
||||
cmp ES:[SI].big_sign,0
|
||||
jne un_false ; if negative, not one of ours
|
||||
cmp ES:[SI].big_len,8
|
||||
jne un_false ; if more than four bytes of data, not ours
|
||||
mov DI,ES:[SI].big_data ; load least significant word (bucket no.)
|
||||
cmp DI,OHT_SIZE
|
||||
jae un_false ; hash bucket index too large? if so, jump
|
||||
mov DX,DI ; DX <- bucket number
|
||||
mov AX,ES:[SI].big_2nd
|
||||
shl DI,1 ; DI <- bucket number * 2
|
||||
cmp AX,obj_cntr+[DI] ; test against next available counter value
|
||||
jae un_false ; hash index too large? if so, jump
|
||||
; Note: Search index (key) is in AX
|
||||
add DI,DX ; DI <- bucket number * 3
|
||||
add DI,offset obj_ht
|
||||
mov DX,DS ; ES <- DS
|
||||
mov ES,DX
|
||||
; Note: Search list whose header is in ES:[DI]
|
||||
call oh_search ; search "ES:[DI]" for "AX"
|
||||
cmp BL,0 ; was index found?
|
||||
je un_false ; if not found, return #!false (jump)
|
||||
; Search successful-- object/hash-value pair pointed to by ES:[SI]
|
||||
mov DI,[BP].un_reg ; load destination register's address
|
||||
mov AX,ES:[SI].car ; copy car field of found pair into
|
||||
mov [DI].C_disp,AX ; the destination register
|
||||
mov AL,ES:[SI].car_page
|
||||
mov byte ptr [DI].C_page,AL
|
||||
jmp un_ret ; return to caller w/ object in dest reg
|
||||
%objunhs endp
|
||||
|
||||
;************************************************************************
|
||||
;* Local Support for Object Unhash *
|
||||
;************************************************************************
|
||||
oh_search proc near
|
||||
; Compute pointer to current entry and save it
|
||||
mov BL,ES:[DI].car_page
|
||||
cmp BL,0
|
||||
je oh_sret
|
||||
mov DI,ES:[DI].car
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov DX,ES ; save ES in DX
|
||||
; Compute pointer to object/hash-key pair
|
||||
mov BL,ES:[DI].car_page
|
||||
mov SI,ES:[DI].car
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
; Test cdr field (hash key) of pair for match
|
||||
cmp ES:[SI].cdr,AX
|
||||
jne oh_smore
|
||||
; A match!-- Return pair address in ES:[SI]
|
||||
oh_sret: ret
|
||||
|
||||
oh_smore: mov ES,DX ; restore ES
|
||||
add DI,PTRSIZE ; adjust pointer to cdr field of curr entry
|
||||
jmp oh_search ; iterate
|
||||
oh_search endp
|
||||
|
||||
;************************************************************************
|
||||
;* Object Hash Table Garbage Collection *
|
||||
;************************************************************************
|
||||
gc_args struc
|
||||
prev_ES dw ? ; ES for previous entry
|
||||
prev_off dw ? ; offset for previous entry
|
||||
curr_PG dw ? ; ES for current entry
|
||||
curr_off dw ? ; offset for current entry
|
||||
pair_PG dw ? ; ES for object/hash-key pair
|
||||
pair_off dw ? ; offset for object/hash-key pair
|
||||
gc_BP dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dd ? ; return address (far call)
|
||||
dw ? ; return address (near call)
|
||||
gc_args ends
|
||||
|
||||
%gc_oht proc far
|
||||
push ES ; save caller's ES register
|
||||
push BP ; save caller's BP register
|
||||
sub SP,offset gc_BP ; allocate local storage
|
||||
mov BP,SP ; establish addressibility for local storage
|
||||
|
||||
; Initialize parameters
|
||||
mov SI,offset obj_ht ; load address of object hash table
|
||||
mov CX,OHT_SIZE ; load number of entries in obj hash table
|
||||
gc_loop: mov AX,DS ; ES <- DS
|
||||
mov ES,AX
|
||||
push SI ; load current object hash table offset
|
||||
push CX ; save iteration counter
|
||||
call gc_nxt ; follow this entries chain
|
||||
pop CX ; restore iteration counter
|
||||
pop SI ; restore obj hash table offset
|
||||
add SI,PTRSIZE ; advance offset pointer
|
||||
loop gc_loop ; continue 'til all buckets processed
|
||||
|
||||
; Return to caller
|
||||
gc_xit: add SP,offset gc_BP ; release local storage
|
||||
pop BP ; restore the caller's BP register
|
||||
pop ES ; restore the caller's ES register
|
||||
ret ; return
|
||||
%gc_oht endp
|
||||
|
||||
;************************************************************************
|
||||
;* Local Support for Object Hash Table Garbage Collection *
|
||||
;************************************************************************
|
||||
gc_nxt proc near
|
||||
xor BX,BX ; clear register BX
|
||||
mov BL,ES:[SI].car_page ; load page number for next entry
|
||||
cmp BL,0 ; does entry exist?
|
||||
jne ogc_010 ; if null pointer, jump to exit
|
||||
ret ; return to gc_oht
|
||||
; save pointer to previous cell
|
||||
ogc_010: mov [BP].prev_ES,ES
|
||||
mov [BP].prev_off,SI
|
||||
; compute and save pointer to current cell
|
||||
mov DI,ES:[SI].car
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov [BP].curr_PG,BX
|
||||
mov [BP].curr_off,DI
|
||||
; compute and save pointer to object/hash-key pair
|
||||
mov BL,ES:[DI].car_page
|
||||
mov SI,ES:[DI].car
|
||||
test SI,08000h ; is current cell marked as referenced?
|
||||
jnz ogc_skip ; if marked, GC during OBJECT-HASH (jump)
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov [BP].pair_PG,BX
|
||||
mov [BP].pair_off,SI
|
||||
; see what object pointer points to
|
||||
mov BL,ES:[SI].car_page
|
||||
cmp BL,DEDPAGES*PAGEINCR ; is object a "special" one?
|
||||
jb ogc_mark ; if a non-gc'ed page, must keep entry
|
||||
mov SI,ES:[SI].car ; load object offset
|
||||
%LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load object's paragraph address
|
||||
mov DI,ptype+[BX] ; load type code for object
|
||||
jmp branchtab+[DI] ; jump to appropriate routine
|
||||
|
||||
; object is a list cell-- test to see if it's marked
|
||||
ogc_list: test byte ptr ES:[SI].list_gc,GC_BIT
|
||||
jnz ogc_mark
|
||||
jmp short ogc_del
|
||||
|
||||
; Variable length object
|
||||
ogc_var: test byte ptr ES:[SI].vec_gc,GC_BIT
|
||||
jnz ogc_mark
|
||||
|
||||
; Object not referenced-- delete object hash table entry for it
|
||||
ogc_del: %LoadPage ES,[BP].curr_PG ; reload pointer to current entry
|
||||
mov SI,[BP].curr_off
|
||||
mov AX,ES:[SI].cdr ; load cdr field of current entry
|
||||
mov BL,ES:[SI].cdr_page
|
||||
mov ES,[BP].prev_ES ; reload pointer to previous entry
|
||||
mov SI,[BP].prev_off
|
||||
mov ES:[SI].car,AX ; store cdr field of current entry into
|
||||
mov ES:[SI].car_page,BL ; previous entry
|
||||
jmp gc_nxt ; process next entry
|
||||
|
||||
; Object is marked as referenced-- mark obj hash table cells as referenced
|
||||
ogc_mark: %LoadPage ES,[BP].pair_PG ; load pointer to object/hash-key pair
|
||||
mov SI,[BP].pair_off
|
||||
or byte ptr ES:[SI].list_gc,GC_BIT ; mark pair entry referenced
|
||||
ogc_skip: %LoadPage ES,[BP].curr_PG ; load pointer to current entry
|
||||
mov SI,[BP].curr_off
|
||||
or byte ptr ES:[SI].list_gc,GC_BIT ; mark curr entry referenced
|
||||
add SI,PTRSIZE ; advance pointer to cdr field of curr entry
|
||||
jmp gc_nxt ; process next entry
|
||||
gc_nxt endp
|
||||
|
||||
PROGX ends
|
||||
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
;************************************************************************
|
||||
;* Linkage to Object Hash Routine *
|
||||
;************************************************************************
|
||||
public obj_hash
|
||||
obj_hash proc near
|
||||
call %objhash
|
||||
extrn next:near
|
||||
jmp next ; return to the Scheme interpreter
|
||||
obj_hash endp
|
||||
|
||||
public obj_unhs
|
||||
obj_unhs proc near
|
||||
call %objunhs
|
||||
jmp next ; return to the Scheme interpreter
|
||||
obj_unhs endp
|
||||
|
||||
public gc_oht
|
||||
gc_oht proc near
|
||||
call %gc_oht
|
||||
ret
|
||||
gc_oht endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/* -----> SPORT.H */
|
||||
/* TIPC Scheme Runtime Support - I/O Control Structure Definition
|
||||
Copyright 1985 by Texas Instruments Incorporated.
|
||||
All Rights Reserved.
|
||||
|
||||
Author: John C. Jensen
|
||||
Installation: Texas Instruments Incorporated, Dallas, Texas
|
||||
Division: Corporate Research Laboratories
|
||||
Cost Center: Computer Science Laboratory
|
||||
Project: Computer Architecture Branch
|
||||
Date Written: 1 February 1985
|
||||
Last Modification: 18 July 1985 by Mark Meyer
|
||||
22 Jan 1987 by dbs - added random i/o
|
||||
*/
|
||||
|
||||
/* The format of a window data object is:
|
||||
|
||||
+--------+--------+--------+
|
||||
0 |tag=port| length in bytes |
|
||||
+--------+-----------------+
|
||||
3 | pointer |
|
||||
+--------+--------+--------+--------+
|
||||
6 | port flags | handle |
|
||||
+-----------------+-----------------+
|
||||
10 | cursor line | cursor column |
|
||||
+-----------------+-----------------+
|
||||
14 | upper left line |upper left column|
|
||||
+-----------------+-----------------+
|
||||
18 | number of lines |number of columns|
|
||||
+-----------------+-----------------+
|
||||
22 |border attributes| text attributes |
|
||||
+-----------------+-----------------+
|
||||
26 | window flags | buffer position |
|
||||
+-----------------+-----------------+
|
||||
30 | buffer end |
|
||||
+--------+--------+--------+--------+----... -----+
|
||||
32 | input buffer |
|
||||
+--------+--------+-----------------+-------...---+
|
||||
| window label |
|
||||
+--------+--------+-----------------+---------...-+
|
||||
|
||||
7 6 5 4 3 2 1 0
|
||||
+-+-+-+-+-+-+---+
|
||||
port flags: | |s|b|t|o|w|mod|
|
||||
+-+-+-+-+-+-+---+
|
||||
|
||||
mod - mode: 0=read
|
||||
1=write
|
||||
2=read and write
|
||||
w - window/file: 0=file
|
||||
1=window
|
||||
o - open/closed: 0=closed
|
||||
1=open
|
||||
t - transcript: 0=disabled
|
||||
1=enabled
|
||||
b - binary flag: 0=text file/window
|
||||
1=binary file/window
|
||||
s - string I/O: 0=file or window
|
||||
1=I/O from/to string
|
||||
|
||||
7 6 5 4 3 2 1 0
|
||||
+-----------+-+-+
|
||||
window flags: | |e|w|
|
||||
+-----------+-+-+
|
||||
|
||||
w - wrap/clip: 0=clip
|
||||
1=wrap
|
||||
e - exposed: 0=exposed
|
||||
1=(partially) covered
|
||||
|
||||
The format of a file data object is:
|
||||
|
||||
+--------+--------+--------+
|
||||
0 |tag=port| length in bytes |
|
||||
+--------+-----------------+
|
||||
3 | null |
|
||||
+--------+--------+--------+--------+
|
||||
6 | port flags | handle |
|
||||
+-----------------+-----------------+
|
||||
10 | pathname offset | current column |
|
||||
+-----------------+-----------------+
|
||||
14 | chunk # | (reserved) |
|
||||
+-----------------+-----------------+
|
||||
18 |file size (high) |number of columns|
|
||||
+-----------------+-----------------+
|
||||
22 | file size (low) | (reserved) |
|
||||
+-----------------+-----------------+
|
||||
26 | (reserved) | buffer position |
|
||||
+-----------------+-----------------+
|
||||
30 | buffer end |
|
||||
+--------+--------+--------+--------+----... -----+
|
||||
32 | input/output buffer ... |
|
||||
+--------+--------+-----------------+-------... --+
|
||||
| file pathname ... |
|
||||
+--------+--------+-----------------+---------... +
|
||||
|
||||
*/
|
||||
#define READ 0x00
|
||||
#define WRITE 0x01
|
||||
#define APPEND 0x02
|
||||
#define READ_WRITE 0x02
|
||||
#define WINDOW 0x04
|
||||
#define OPEN 0x08
|
||||
#define TRANSCRIPT 0x10
|
||||
#define BINARY 0x20
|
||||
#define STRSRC 0x40
|
||||
|
||||
#define WRAP 0x01
|
||||
|
||||
#define MAX_LINES 25 /* number of lines on the VDT */
|
||||
#define MAX_COLUMNS 80 /* number of columns on the VDT */
|
||||
#define WINDSIZE 32-BLK_OVHD
|
||||
#define BUFFSIZE 256 /* input/output buffer size (bytes) */
|
||||
|
||||
#define STR_PTR 3 /* pointer to source string, if any */
|
||||
#define P_FLAGS 6 /* port flags */
|
||||
#define HANDLE 8 /* file/device handle */
|
||||
#define CUR_LINE 10 /* current line/record number */
|
||||
#define CUR_COL 12 /* current column/record number */
|
||||
#define UL_LINE 14 /* window: upper left corner's line number */
|
||||
/* file: chunk # */
|
||||
#define UL_COL 16 /* window: upper left corner's column number */
|
||||
#define N_LINES 18 /* window: number of lines */
|
||||
/* file: high word of file size */
|
||||
#define N_COLS 20 /* line length */
|
||||
#define B_ATTRIB 22 /* window: border attributes */
|
||||
/* file: low word of file size */
|
||||
#define T_ATTRIB 24 /* window: text attributes */
|
||||
#define W_FLAGS 26 /* window: flags */
|
||||
#define BUF_POS 28 /* current buffer position */
|
||||
#define BUF_END 30 /* current end of buffer offset */
|
||||
|
||||
#define BUFR 32 /* input/output buffer */
|
||||
#define LABEL 32+BUFFSIZE /* window label field */
|
||||
#define PATHNAME 32+BUFFSIZE /* file pathname field */
|
||||
|
|
@ -0,0 +1,753 @@
|
|||
; =====> SQUISH.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* Memory Compaction Routines *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 23 September 1985 *
|
||||
;* Last Modification: 22 October 1985 *
|
||||
;* *
|
||||
;* rb 2/ 2/88 - put in TC's GC fix *
|
||||
;* *
|
||||
;***************************************
|
||||
.286c ;; Utilize the expanded 80286 instruction set
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
XGROUP group PROGX
|
||||
PGROUP group prog
|
||||
|
||||
MSDOS equ 021h
|
||||
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
ret_sav1 dw 0 ; return address save area
|
||||
ret_sav2 dw 0 ; return address save area
|
||||
;;;msg db " Compacting Memory *",0
|
||||
;;;msg1a db "Moving List Cells",LF,0
|
||||
;;;msg1b db "Moving Flonums",LF,0
|
||||
;;;msg1c db "Moving Bignums",LF,0
|
||||
;;;msg1d db "Moving Closures",LF,0
|
||||
;;;msg1e db "Moving Code Blocks",LF,0
|
||||
;;;msg1f db "Moving Vectors",LF,0
|
||||
;;;msg1g db "Moving Continuations",LF,0
|
||||
;;;msg1h db "Moving Symbols",LF,0
|
||||
;;;msg1i db "Moving Strings",LF,0
|
||||
;;;msg2 db "About to Relocate Pointers",LF,0
|
||||
;;;msg3 db "Complementing GC Bits",LF,0
|
||||
;;;msg4 db "About to Sweep",LF,0
|
||||
data ends
|
||||
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
extrn %allocbl:far ; "alloc_block" linkage routine
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to SUM_SPACE *
|
||||
;************************************************************************
|
||||
%sumspac proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
extrn sum_spac:near
|
||||
call sum_spac
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%sumspac endp
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to GCSWEEP *
|
||||
;************************************************************************
|
||||
%gcsweep proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
extrn gcsweep:near
|
||||
call gcsweep
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%gcsweep endp
|
||||
|
||||
IFDEF EXPMEM
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to GCCLEAN *
|
||||
;************************************************************************
|
||||
%gcclean proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
extrn gcclean:near
|
||||
call gcclean
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%gcclean endp
|
||||
|
||||
ENDIF
|
||||
|
||||
;************************************************************************
|
||||
;* ***Temporary Long Linkage to PRINTF*** *
|
||||
;************************************************************************
|
||||
public %printf,%sdebug
|
||||
%printf proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
extrn printf:near
|
||||
call printf
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%printf endp
|
||||
|
||||
;************************************************************************
|
||||
;* ***Temporary Long Linkage to SDEBUG*** *
|
||||
;************************************************************************
|
||||
%sdebug proc far
|
||||
pop ret_sav1
|
||||
pop ret_sav2
|
||||
extrn sdebug:near
|
||||
call sdebug
|
||||
push ret_sav2
|
||||
push ret_sav1
|
||||
ret
|
||||
%sdebug endp
|
||||
|
||||
prog ends
|
||||
|
||||
PROGX segment byte public 'PROGX'
|
||||
assume CS:XGROUP
|
||||
|
||||
extrn srelocat:near ; pointer relocation routine
|
||||
extrn toggleGC:near ; complement GC bits
|
||||
|
||||
;************************************************************************
|
||||
;* Garbage Collection -- Compaction Phase *
|
||||
;************************************************************************
|
||||
sq_args struc
|
||||
sq_free dw NUMPAGES dup (?) ; amount of free space within each page
|
||||
sq_plist dw NUMPAGES dup (?) ; list of pages
|
||||
sq_BP dw ? ; caller's BP register
|
||||
dw ? ; caller's ES register
|
||||
dd ? ; return address (far call)
|
||||
dw ? ; return address (near call)
|
||||
sq_args ends
|
||||
|
||||
%squish proc far
|
||||
push ES ; save caller's ES register
|
||||
push BP ; and BP register
|
||||
sub SP,offset sq_BP ; allocate local storage
|
||||
mov BP,SP ; and establish addressability
|
||||
|
||||
; Compute the amount of free space in each page
|
||||
lea BX,[BP].sq_free ; load address of size array
|
||||
push BX ; and push as argument to "sum_space"
|
||||
call %sumspac ; determine available space in each page
|
||||
mov SP,BP ; drop argument from TIPC's stack
|
||||
|
||||
; Initialize table of page numbers
|
||||
mov AX,DS ; make ES point to the data
|
||||
mov ES,AX ; segment
|
||||
mov CX,NUMPAGES ; load page count
|
||||
lea DI,[BP].sq_plist ; load address of page number table
|
||||
xor AX,AX ; initialize page number index to zero
|
||||
pt_loop: stosw ; set page number to current position
|
||||
add AX,WORDINCR ; increment page index
|
||||
loop pt_loop ; process all page numbers
|
||||
|
||||
; Reset the similar page type chain headers
|
||||
mov CX,NUMTYPES
|
||||
mov AX,END_LIST
|
||||
mov DI,offset pagelist
|
||||
rep stosw
|
||||
|
||||
; Sort list of pages according to size available
|
||||
mov DX,DEDPAGES*WORDINCR
|
||||
sort_nxt: mov SI,DX
|
||||
mov DI,[BP].sq_plist+[SI]
|
||||
mov AX,[BP].sq_free+[DI] ; load amount of space in base page
|
||||
sort_mor: add SI,WORDINCR ; increment inner loop index
|
||||
mov DI,[BP].sq_plist+[SI] ; load page index
|
||||
cmp AX,[BP].sq_free+[DI] ; has current page less space?
|
||||
jbe sort_no ; if not, jump
|
||||
mov AX,[BP].sq_free+[DI] ; load size of smaller free space
|
||||
mov DI,DX
|
||||
mov CX,[BP].sq_plist+[SI] ; exchange base page index
|
||||
xchg CX,[BP].sq_plist+[DI] ; with current page
|
||||
mov [BP].sq_plist+[SI],CX ; index
|
||||
sort_no: cmp SI,NUMPAGES*WORDINCR-WORDINCR ; is inner loop complete?
|
||||
jl sort_mor ; if not, jump
|
||||
add DX,WORDINCR ; increment outer loop index
|
||||
cmp DX,NUMPAGES*WORDINCR-WORDINCR ; is outer loop complete?
|
||||
jl sort_nxt ; if not, keep on loopin'
|
||||
|
||||
; Update the similar page type chains
|
||||
mov DI,DEDPAGES*WORDINCR
|
||||
spt_loop: mov SI,[BP].sq_plist+[DI]
|
||||
test attrib+[SI],NOMEMORY
|
||||
jnz spt_end
|
||||
mov BX,ptype+[SI]
|
||||
mov AX,pagelist+[BX]
|
||||
mov pagelink+[SI],AX
|
||||
mov AX,SI
|
||||
CORRPAGE AX
|
||||
mov pagelist+[BX],AX
|
||||
spt_end: add DI,WORDINCR
|
||||
cmp DI,NUMPAGES*WORDINCR
|
||||
jl spt_loop
|
||||
|
||||
IFDEF EXPMEM
|
||||
call %gcclean ; Clean out Emm Page table for compaction
|
||||
ENDIF
|
||||
|
||||
; Note: If printing messages, make ES point to the data segment
|
||||
;;; mov AX,DS ;* Make ES point to the data
|
||||
;;; mov ES,AX ;* segment
|
||||
|
||||
; Compact List Cells
|
||||
;;; mov AX,offset msg1a ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting list cells
|
||||
call sq_list
|
||||
|
||||
; Compact Flonums
|
||||
;;; mov AX,offset msg1b ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting flonums
|
||||
call sq_flo
|
||||
|
||||
; Compact Bignums
|
||||
;;; mov AX,offset msg1c ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting bignums
|
||||
mov AX,BIGTYPE*2 ; load type code index for bignums
|
||||
push AX ; and push as argument to "sq_var"
|
||||
call sq_var
|
||||
mov SP,BP ; drop arguments from stack
|
||||
|
||||
; Compact Closures
|
||||
;;; mov AX,offset msg1d ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting closures
|
||||
mov AX,CLOSTYPE*2 ; load type code index for closures
|
||||
push AX ; and push as argument to "sq_var"
|
||||
call sq_var
|
||||
mov SP,BP ; drop arguments from stack
|
||||
|
||||
; Compact Code Blocks
|
||||
;;; mov AX,offset msg1e ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting code blocks
|
||||
mov AX,CODETYPE*2 ; load type index for code blocks
|
||||
push AX ; and push as argument to "sq_var"
|
||||
call sq_var
|
||||
mov SP,BP ; drop arguments from stack
|
||||
|
||||
; Compact Vectors
|
||||
;;; mov AX,offset msg1f ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting vectors
|
||||
mov AX,VECTTYPE*2 ; load type index for vectors
|
||||
push AX ; and push as argument to "sq_var"
|
||||
call sq_var
|
||||
mov SP,BP ; drop arguments from stack
|
||||
|
||||
; Compact Continuations
|
||||
;;; mov AX,offset msg1g ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting continuations
|
||||
mov AX,CONTTYPE*2 ; load type index for continuations
|
||||
push AX ; and push as argument to "sq_var"
|
||||
call sq_var
|
||||
mov SP,BP ; drop arguments from stack
|
||||
|
||||
;;; Note: Let's not compact symbols for now. There are a few "special"
|
||||
;;; symbols which mess things up in the runtime support if they
|
||||
;;; move. Notably, CONSOLE_ and QUOTE_reg(?)
|
||||
;;;; Compact Symbols
|
||||
;;; mov AX,offset msg1h ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting symbols
|
||||
;;; mov AX,SYMTYPE*2 ; load type index for symbols
|
||||
;;; push AX ; and push as argument to "sq_var"
|
||||
;;; call sq_var
|
||||
;;; mov SP,BP ; drop arguments from stack
|
||||
|
||||
; Compact Strings
|
||||
;;; mov AX,offset msg1i ;*
|
||||
;;; push AX ; * print message indicating we're
|
||||
;;; call %printf ;* compacting strings
|
||||
mov AX,STRTYPE*2 ; load type index for strings
|
||||
push AX ; and push as argument to "sq_var"
|
||||
call sq_var
|
||||
mov SP,BP ; drop arguments from stack
|
||||
|
||||
; Relocate all moved pointers
|
||||
;;; mov AX,offset msg2 ;*
|
||||
;;; push AX ; * print a message that we're about
|
||||
;;; call %printf ;* to perform pointer relocation
|
||||
call srelocat ; relocate all pointers
|
||||
|
||||
; Toggle the GC bits used to denote forwarding
|
||||
;;; mov AX,offset msg3 ;*
|
||||
;;; push AX ; * print a message that we're
|
||||
;;; call %printf ; * complementing the GC bits
|
||||
call toggleGC ; complement the GC (forwarding) bits
|
||||
|
||||
IFDEF EXPMEM
|
||||
call %gcclean ; Clean out Emm Page table
|
||||
ENDIF
|
||||
|
||||
; Invoke the "sweep" portion of the garbage collector to reclaim memory
|
||||
;;; mov AX,offset msg4 ;*
|
||||
;;; push AX ; * print a message that it's
|
||||
;;; call %printf ; * "sweep" time
|
||||
call %gcsweep ; reclaim all freed memory
|
||||
|
||||
; Return to caller
|
||||
mov SP,BP ; deallocate stack temporaries
|
||||
add SP,offset sq_BP ; release local storage
|
||||
pop BP ; restore caller's BP register
|
||||
pop ES ; and ES register
|
||||
ret ; return
|
||||
%squish endp
|
||||
|
||||
;************************************************************************
|
||||
;* Macro Support for List/Flonum Compaction *
|
||||
;* *
|
||||
;* Register usage during "move" phase of this routine: *
|
||||
;* AX - backward chain header (destination page index) *
|
||||
;* BX - (scratch register) *
|
||||
;* CX - word count for block move *
|
||||
;* DX - forward chain header (source page index) *
|
||||
;* DS:[SI] - source list cell *
|
||||
;* ES:[DI] - destination list cell *
|
||||
;************************************************************************
|
||||
sql_arg struc
|
||||
sql_rev dw NUMPAGES dup (?) ; reversed linked list of list pages
|
||||
sql_bptr dw ? ; reversed list header
|
||||
sql_BP dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; return address
|
||||
sql_type dw ? ; type code index (for variable len objects)
|
||||
sql_arg ends
|
||||
|
||||
sq_L_F macro uppercase,lowercase
|
||||
local sql_go,sql_010,sql_020,sql_025,sql_030,sql_035
|
||||
local sql_040,sql_050,sql_060,sql_070,sql_done,sql_ret
|
||||
push ES ; save caller's ES
|
||||
push BP ; save caller's BP
|
||||
sub SP,offset sql_BP ; allocate local storage
|
||||
mov BP,SP ; establish local addressability
|
||||
|
||||
; Create a reverse order linked list of pages
|
||||
lea BX,[BP].sql_rev ; load addr of reverse linked list array
|
||||
mov AX,uppercase&TYPE*2 ; load type code
|
||||
pushm <AX,BX> ; push type code, array addr as arguments
|
||||
call sq_rever ; create the reverse linked list
|
||||
mov SP,BP ; drop arguments off TIPC's stack
|
||||
cmp AX,END_LIST ; is list of pages empty?
|
||||
jne sql_go ; if list non-empty, continue (jump)
|
||||
jmp sql_ret ; if empty list, return
|
||||
sql_go: ADJPAGE AX ; convert list header to page index value
|
||||
|
||||
; Move list cells from least dense pages to most dense pages
|
||||
mov DX,lowercase&page ; load page number of least dense
|
||||
ADJPAGE DX ; page and convert to page index
|
||||
mov BX,DX ; copy page index into BX
|
||||
push DS ; save DS register
|
||||
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
; * * * WARNING: The DS Register Doesn't Point to the Data Segment * * *
|
||||
; * * * in the code which follows: * * *
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
||||
%LoadPage0 DS,BX ; load paragraph address of source page
|
||||
|
||||
mov SI,-uppercase&SIZE ; load source page index
|
||||
jmp short sql_020 ; jump
|
||||
|
||||
; Follow backward chain to get new destination page
|
||||
sql_010: mov BX,AX ; set next available cell address to
|
||||
mov SS:nextcell+[BX],DI ; END_LIST
|
||||
mov BX,BP ; calculate address of current element in
|
||||
add BX,AX ; reversed page list
|
||||
mov AX,SS:[BX].sql_rev ; load next page in backward chain
|
||||
ADJPAGE AX ; convert page number to page index
|
||||
sql_020: cmp AX,DX ; another destination page available?
|
||||
jne sql_025
|
||||
jmp sql_done ; if source page = destination page, jump
|
||||
sql_025:
|
||||
mov BX,AX ; copy destination page index to BX
|
||||
|
||||
%LoadPage1 ES,BX ; load paragraph address of dest page
|
||||
mov DI,SS:nextcell+[BX] ; load free cell header
|
||||
IFDEF EXTMEM
|
||||
mov BX,DX ; reload dest. page so it won't ever
|
||||
%LoadPage0 DS,BX ; get swapped out
|
||||
ENDIF
|
||||
|
||||
; Make sure a cell is available in the destination page
|
||||
sql_030: cmp DI,END_LIST
|
||||
je sql_010
|
||||
|
||||
; Is there a cell to move from the source page?
|
||||
sql_040: mov BX,DX
|
||||
mov BX,SS:psize+[BX] ; load the page size and
|
||||
sub BX,uppercase&SIZE ; compute end of page boundary
|
||||
sql_050: add SI,uppercase&SIZE ; increment source page offset
|
||||
cmp SI,BX ; end of source page?
|
||||
ja sql_070 ; if end of page, jump
|
||||
cmp [SI].car_page,0FFh ; is this cell referenced?
|
||||
je sql_050 ; if an unreferenced cell, jump
|
||||
|
||||
; Move the cell from source page to destination page
|
||||
sql_060: mov BX,ES:[DI].car ; load offset of next free cell in dest page
|
||||
IF uppercase&SIZE - (uppercase&SIZE/2)*2
|
||||
mov CX,uppercase&SIZE
|
||||
rep movsb
|
||||
ELSE
|
||||
mov CX,uppercase&SIZE/WORDINCR ; load number of words to move
|
||||
rep movsw ; copy the contents of the list cell
|
||||
ENDIF
|
||||
sub SI,uppercase&SIZE ; back up the source and destination
|
||||
sub DI,uppercase&SIZE ; pointers
|
||||
IFIDN <uppercase>,<LIST>
|
||||
mov [SI].car_page,AL ; store a forwarding pointer into the car
|
||||
mov [SI].car,DI ; field of the source list cell
|
||||
ELSE
|
||||
IFIDN <uppercase>,<FLO>
|
||||
mov [SI].flo_data,AL
|
||||
mov word ptr [SI].flo_data+1,DI
|
||||
ELSE
|
||||
OOPS invalid data type: uppercase
|
||||
ENDIF
|
||||
ENDIF
|
||||
or byte ptr [SI].&lowercase&_gc,GC_BIT ; set GC bit to indicate
|
||||
; forward
|
||||
mov DI,BX ; copy next free cell offset into DI
|
||||
jmp sql_030 ; process next move
|
||||
|
||||
; Follow forward pointer to get a next source page
|
||||
sql_070: mov BX,DX ; copy forward chain header to BX
|
||||
mov DX,SS:pagelink+[BX] ; load next page in forward chain
|
||||
ADJPAGE DX ; convert page number to page index
|
||||
mov BX,DX
|
||||
|
||||
%LoadPage0 DS,BX ; load paragraph address of source page
|
||||
IFDEF EXTMEM
|
||||
mov BX,AX ; reload dest. page so it won't ever
|
||||
%LoadPage1 ES,BX ; get swapped out
|
||||
ENDIF
|
||||
|
||||
mov SI,-uppercase&SIZE ; initialize source page index
|
||||
cmp AX,DX ; does source page = destination page?
|
||||
je sql_035
|
||||
jmp sql_040 ; if not, keep on moving cells (jump)
|
||||
sql_035:
|
||||
; No more cells to move-- update destination page available cell header
|
||||
mov BX,AX ; update next available cell pointer
|
||||
mov SS:nextcell+[BX],DI ; in the destination page
|
||||
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
; * * * WARNING: The DS Register Doesn't Point to the Data Segment * * *
|
||||
; * * * in the code above * * *
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
||||
; Copying complete
|
||||
sql_done: pop DS ; restore data segment register (DS)
|
||||
|
||||
sql_ret: mov SP,BP ; clean up TIPC's stack
|
||||
add SP,offset sql_BP ; deallocate local storage
|
||||
pop BP ; restore caller's BP
|
||||
pop ES ; restore caller's ES
|
||||
ret ; return to caller
|
||||
endm
|
||||
|
||||
;************************************************************************
|
||||
;* List Cell Compaction *
|
||||
;************************************************************************
|
||||
sq_list proc near
|
||||
sq_L_F LIST,list
|
||||
sq_list endp
|
||||
|
||||
;************************************************************************
|
||||
;* Flonum Compaction *
|
||||
;************************************************************************
|
||||
sq_flo proc near
|
||||
sq_L_F FLO,flo
|
||||
sq_flo endp
|
||||
|
||||
;************************************************************************
|
||||
;* Variable Length Object Compaction *
|
||||
;* *
|
||||
;* Register usage during "move" phase of this routine: *
|
||||
;* AX - backward chain header (destination page index) *
|
||||
;* BX - (scratch register) *
|
||||
;* CX - word count for block move *
|
||||
;* DX - forward chain header (source page index) *
|
||||
;* DS:[SI] - source list cell *
|
||||
;* ES:[DI] - destination list cell *
|
||||
;* *
|
||||
;* Notes: *
|
||||
;* *
|
||||
;* 1. Any object which is less than 6 bytes in length cannot be moved *
|
||||
;* because there's no place to put a forwarding pointer. If a *
|
||||
;* page is encountered with such an object (e.g., a zero length *
|
||||
;* vector) that object, and the remaining objects in that page are *
|
||||
;* not copied. Processing continues with the next source page. *
|
||||
;* *
|
||||
;* 2. The current code block cannot be relocated, since the offset *
|
||||
;* into the current code block is held in register SI in most of *
|
||||
;* the code of the Scheme Virtual Machine emulator. Since it is *
|
||||
;* not possible to update this offset, the page containing the *
|
||||
;* current code block is skipped, if encountered during *
|
||||
;* compaction. *
|
||||
;************************************************************************
|
||||
sq_var proc near
|
||||
push ES ; save caller's ES
|
||||
push BP ; save caller's BP
|
||||
sub SP,offset sql_BP ; allocate local storage
|
||||
mov BP,SP ; establish local addressability
|
||||
|
||||
; Create a reverse order linked list of pages
|
||||
lea BX,[BP].sql_rev ; load addr of reverse linked list array
|
||||
pushm <[BP].sql_type,BX> ; push type code, array addr as arguments
|
||||
call sq_rever ; create the reverse linked list
|
||||
mov SP,BP ; drop arguments off TIPC's stack
|
||||
cmp AX,END_LIST ; is list of pages empty?
|
||||
jne sqv_020 ; if list non-empty, continue (jump)
|
||||
sqv_010: jmp sqv_ret ; if empty list, return
|
||||
sqv_020: ADJPAGE AX ; convert list header to page index value
|
||||
mov [BP].sql_bptr,AX ; save destination list header
|
||||
|
||||
; Move list cells from least dense pages to most dense pages
|
||||
mov BX,[BP].sql_type ; load type index for page type
|
||||
mov DX,pagelist+[BX] ; load page number of least dense
|
||||
ADJPAGE DX ; page and convert to page index
|
||||
cmp AX,DX ; destination page available?
|
||||
je sqv_010 ; if source page = destination page, jump
|
||||
mov BX,DX ; copy page index into BX
|
||||
push DS ; save DS register
|
||||
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
; * * * WARNING: The DS Register Doesn't Point to the Data Segment * * *
|
||||
; * * * in the code which follows: * * *
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
||||
cmp DL,byte ptr CB_pag ; does page contain current code block?
|
||||
je sqv_052 ; if so, skip it
|
||||
IFDEF EXPMEM
|
||||
cmp psize+[BX],MIN_PAGESIZE ; page size greater than minimum?
|
||||
jne sqv_052
|
||||
ENDIF
|
||||
%LoadPage0 DS,BX ; load paragraph address of source page
|
||||
;;; mov DS,pagetabl,[BX] ; load paragraph address of source page
|
||||
xor SI,SI ; load source page index
|
||||
|
||||
; Is there an object to move from the source page?
|
||||
sqv_040: mov BX,DX
|
||||
mov BX,SS:psize+[BX] ; load the page size and
|
||||
sub BX,BLK_OVHD ; compute end of page boundary
|
||||
sqv_050: cmp SI,BX ; end of source page?
|
||||
ja sqv_052 ; if end of page, jump
|
||||
cmp [SI].car_page,FREETYPE ; is this object referenced?
|
||||
jne sqv_060 ; if a referenced object, jump
|
||||
add SI,[SI].vec_len
|
||||
jmp sqv_050
|
||||
|
||||
sqv_052: jmp sqv_070 ; process next source page
|
||||
|
||||
; Find next possible destination page
|
||||
sqv_054: mov BX,AX
|
||||
add BX,BP
|
||||
mov AX,SS:[BX].sql_rev
|
||||
ADJPAGE AX
|
||||
cmp AX,DX
|
||||
jne sqv_061
|
||||
jmp sqv_done
|
||||
|
||||
; Find a block into which to move the referenced object
|
||||
sqv_060: mov CX,[SI].vec_len ; load length of object
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge sqv_001
|
||||
mov CX,BLK_OVHD+PTRSIZE ;;; get the right value
|
||||
sqv_001: cmp CX,BLK_OVHD+PTRSIZE ; is object "too small" to relocate?
|
||||
jae sqv001
|
||||
jmp sqv_070 ; if "too small", abandon this page
|
||||
sqv001: mov AX,[BP].sql_bptr ; load destination page list header
|
||||
sqv_061: mov BX,AX ; copy index for destination page
|
||||
IFDEF EXPMEM
|
||||
cmp psize+[BX],MIN_PAGESIZE ; page size greater than minimum?
|
||||
jne sqv_054
|
||||
ENDIF
|
||||
%LoadPage1 ES,BX ; load paragraph address of dest page
|
||||
IFDEF EXTMEM
|
||||
%LoadPage0 DS,DX ; reload src page so it won't get swapped out
|
||||
ENDIF
|
||||
xor DI,DI ; page and initialize its index pointer
|
||||
mov BX,SS:psize+[BX] ; load page size and
|
||||
sub BX,BLK_OVHD ; adjust for boundary check
|
||||
jmp short sqv_064 ; jump over increment
|
||||
sqv_062: cmp ES:[DI].vec_len,0 ;;; check for small string
|
||||
jge sqv_002
|
||||
add DI,BLK_OVHD+PTRSIZE ;;; add the exact length
|
||||
jmp sqv_064
|
||||
sqv_002: add DI,ES:[DI].vec_len ; advance destination page index
|
||||
sqv_064: cmp DI,BX ; end of page?
|
||||
ja sqv_054 ; if end of page, jump
|
||||
cmp ES:[DI].vec_type,FREETYPE ; free block?
|
||||
jne sqv_062 ; if not a free block, keep looking (jump)
|
||||
; Free block found-- is it big enough?
|
||||
cmp CX,ES:[DI].vec_len
|
||||
ja sqv_062
|
||||
je sqv_068 ; if an exact fit, jump
|
||||
sub CX,ES:[DI].vec_len
|
||||
neg CX
|
||||
cmp CX,BLK_OVHD
|
||||
jge sqv_066
|
||||
mov CX,[SI].vec_len
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge sqv_062
|
||||
mov CX,BLK_OVHD+PTRSIZE ;;; get the right value
|
||||
jmp sqv_062
|
||||
sqv_066: cmp [SI].vec_len,0 ;;; check for small string
|
||||
jge sqv_003
|
||||
add DI,BLK_OVHD+PTRSIZE ;;; add the right value
|
||||
jmp sqv_004
|
||||
sqv_003: add DI,[SI].vec_len
|
||||
sqv_004: mov ES:[DI].vec_type,FREETYPE
|
||||
mov ES:[DI].vec_len,CX
|
||||
mov CX,[SI].vec_len
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge sqv_005
|
||||
mov CX,BLK_OVHD+PTRSIZE
|
||||
sqv_005: sub DI,CX
|
||||
|
||||
; Move the cell from source page to destination page
|
||||
sqv_068: mov BX,CX ; save the number of bytes moved
|
||||
rep movsb ; copy object from source page to dest page
|
||||
sub SI,BX ; back up the source and destination
|
||||
sub DI,BX ; pointers
|
||||
mov [SI].vec_page,AL ; store a forwarding pointer into the car
|
||||
mov [SI].vec_disp,DI ; field of the source object
|
||||
or byte ptr [SI].vec_gc,GC_BIT ; set GC bit to indicate forward
|
||||
add SI,BX ; advance source page index to next object
|
||||
sqv_069: jmp sqv_040 ; process next move
|
||||
|
||||
; Follow forward pointer to get a next source page
|
||||
sqv_070: mov BX,DX ; copy forward chain header to BX
|
||||
mov DX,SS:pagelink+[BX] ; load next page in forward chain
|
||||
ADJPAGE DX ; convert page number to page index
|
||||
cmp AX,DX ; source = destination? ;rb for tc
|
||||
je sqv_done ; yes, jump ;rb for tc
|
||||
cmp DL,SS:byte ptr CB_pag ; current code block in this page?
|
||||
je sqv_070 ; we can't relocate the current code block
|
||||
mov BX,DX
|
||||
IFDEF EXPMEM
|
||||
cmp psize+[BX],MIN_PAGESIZE ; page size greater than minimum?
|
||||
jne sqv_070
|
||||
ENDIF
|
||||
%LoadPage0 DS,BX ; load paragraph address of source page
|
||||
IFDEF EXTMEM
|
||||
%LoadPage1 ES,AX ; reload dest page so it won't get swapped
|
||||
ENDIF
|
||||
xor SI,SI ; initialize source page index
|
||||
cmp AX,DX ; does source page = destination page?
|
||||
jne sqv_069 ; if not, keep on moving objects (jump)
|
||||
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
; * * * WARNING: The DS Register Doesn't Point to the Data Segment * * *
|
||||
; * * * in the code above * * *
|
||||
; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
||||
; Copying complete
|
||||
sqv_done: pop DS ; restore data segment register (DS)
|
||||
|
||||
sqv_ret: mov SP,BP ; clean up TIPC's stack
|
||||
add SP,offset sql_BP ; deallocate local storage
|
||||
pop BP ; restore caller's BP
|
||||
pop ES ; restore caller's ES
|
||||
ret ; return to caller
|
||||
sq_var endp
|
||||
|
||||
;************************************************************************
|
||||
;* Local Support-- Create Reverse Linked List *
|
||||
|
||||
;* *
|
||||
;* Purpose: To create a reversed copy of the similar page list for *
|
||||
;* pages of a given type. *
|
||||
;* *
|
||||
;* Calling Sequence: header = sq_rever(dest_array, type_index) *
|
||||
;* header = header pointer of reversed list. *
|
||||
;* dest_array = array to hold the pointers of the reversed *
|
||||
;* linked list. *
|
||||
;* type_index = type index (type*2) of the page type for *
|
||||
;* which the similar page linked list is *
|
||||
;* to be reversed (e.g., LISTTYPE*2 causes *
|
||||
;* the linked list for list cell pages to *
|
||||
;* be reversed. *
|
||||
;************************************************************************
|
||||
sqr_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
sqr_ary dw ? ; pointer to reversed list array
|
||||
sqr_typ dw ? ; type code for desired page type
|
||||
sqr_args ends
|
||||
|
||||
sq_rever proc near
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP ; establish addressability
|
||||
mov BX,[BP].sqr_ary ; load address of destination array
|
||||
mov SI,[BP].sqr_typ ; load type code for list to reverse
|
||||
mov SI,pagelist+[SI] ; load list header to appropriate page type
|
||||
mov AX,END_LIST ; load an end of list indicator
|
||||
sqr_loop: cmp SI,END_LIST ; end of list?
|
||||
je sqr_ret ; if end of list, return
|
||||
mov DX,SI ; save current page number in DX
|
||||
ADJPAGE SI ; convert page number to page index
|
||||
mov [BX]+[SI],AX ; store prev page number into reversed array
|
||||
mov SI,pagelink+[SI] ; fetch next page in linked list
|
||||
mov AX,DX ; prev page number <- current page number
|
||||
jmp sqr_loop ; continue 'til end of list
|
||||
sqr_ret: pop BP ; restore caller's BP
|
||||
ret ; return with reversed list header in AX
|
||||
sq_rever endp
|
||||
|
||||
PROGX ends
|
||||
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
;************************************************************************
|
||||
;* Long Linkage to gcsquish *
|
||||
;* *
|
||||
;* Note: The lines which are commented out in the following code were *
|
||||
;* used to print the "* compacting memory *" message in the *
|
||||
;* who-line. Since it's a real pain in the a.. to allow the *
|
||||
;* user to change the GC messages, it was decided that no *
|
||||
;* message was the best way to go. *
|
||||
;************************************************************************
|
||||
public gcsquish
|
||||
gcsquish proc near
|
||||
push ES ; save caller's ES register
|
||||
push BP ; save caller's BP register
|
||||
mov BP,SP
|
||||
mov AX,DS ; make sure ES points to the data segment
|
||||
mov ES,AX
|
||||
C_call gc_on ; light up the "garbage collecting" message
|
||||
;;; mov AX,offset msg ; load address of compaction message
|
||||
;;; push AX ; and push as argument
|
||||
;;; C_call who_writ ; display "compacting memory" message
|
||||
;;; mov SP,BP ; drop argument from stack
|
||||
call %squish ; perform memory compaction
|
||||
C_call gc_off ; reset the garbage collection message
|
||||
pop BP ; restore caller's BP
|
||||
pop ES ; restore caller's ES
|
||||
ret ; return to caller
|
||||
gcsquish endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,490 @@
|
|||
; =====> SRELOCAT.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* GC Pointer Relocation Routines *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 23 September 1985 *
|
||||
;* Last Modification: 18 October 1985 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
XGROUP group PROGX
|
||||
PGROUP group prog
|
||||
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
|
||||
msg_relp db "[VM INTERNAL ERROR] rel_ptr: invalid %x:%04x (unadjusted)"
|
||||
db LF,0
|
||||
|
||||
page_sav dw ? ; Page number save area
|
||||
|
||||
; Branch table for processing each data type
|
||||
btable dw rel_list ; [0] List cells
|
||||
dw rel_fix ; [1] Fixnums
|
||||
dw rel_flo ; [2] Flonums
|
||||
dw rel_big ; [3] Bignums
|
||||
dw rel_sym ; [4] Symbols
|
||||
dw rel_str ; [5] Strings
|
||||
dw rel_ary ; [6] Arrays
|
||||
dw rel_cont ; [7] Continuations
|
||||
dw rel_clos ; [8] Closures
|
||||
dw rel_free ; [9] Free space (unallocated)
|
||||
dw rel_code ; [10] Code
|
||||
dw rel_ref ; [11] Reference cells
|
||||
dw rel_port ; [12] Port data objects
|
||||
dw rel_char ; [13] Characters
|
||||
dw rel_env ; [14] Environments
|
||||
|
||||
ctable dw rep_list ; [0] List cells
|
||||
dw rep_fix ; [1] Fixnums
|
||||
dw rep_flo ; [2] Flonums
|
||||
dw rep_big ; [3] Bignums
|
||||
dw rep_sym ; [4] Symbols
|
||||
dw rep_str ; [5] Strings
|
||||
dw rep_ary ; [6] Arrays
|
||||
dw rep_cont ; [7] Continuations
|
||||
dw rep_clos ; [8] Closures
|
||||
dw rep_free ; [9] Free space (unallocated)
|
||||
dw rep_code ; [10] Code
|
||||
dw rep_ref ; [11] Reference cells
|
||||
dw rep_port ; [12] Port data objects
|
||||
dw rep_char ; [13] Characters
|
||||
dw rep_env ; [14] Environments
|
||||
|
||||
dtable dw fwd_list ; [0] List cells
|
||||
dw fwd_fix ; [1] Fixnums
|
||||
dw fwd_flo ; [2] Flonums
|
||||
dw fwd_big ; [3] Bignums
|
||||
dw fwd_sym ; [4] Symbols
|
||||
dw fwd_str ; [5] Strings
|
||||
dw fwd_ary ; [6] Arrays
|
||||
dw fwd_cont ; [7] Continuations
|
||||
dw fwd_clos ; [8] Closures
|
||||
dw fwd_free ; [9] Free space (unallocated)
|
||||
dw fwd_code ; [10] Code
|
||||
dw fwd_ref ; [11] Reference cells
|
||||
dw fwd_port ; [12] Port data objects
|
||||
dw fwd_char ; [13] Characters
|
||||
dw fwd_env ; [14] Environments
|
||||
data ends
|
||||
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
extrn %printf:far
|
||||
|
||||
;************************************************************************
|
||||
;* Far Linkage to FORCE_DEBUG *
|
||||
;************************************************************************
|
||||
%forcede proc far
|
||||
extrn force_de:near
|
||||
call force_de
|
||||
ret
|
||||
%forcede endp
|
||||
|
||||
prog ends
|
||||
|
||||
PROGX segment byte public 'PROGX'
|
||||
assume CS:XGROUP
|
||||
|
||||
;************************************************************************
|
||||
;* Garbage Collection -- Pointer Relocation Phase *
|
||||
;************************************************************************
|
||||
public srelocat
|
||||
srelocat proc near
|
||||
push ES ; save caller's ES register
|
||||
push BP ; and BP register
|
||||
mov BP,SP ; and establish addressability
|
||||
|
||||
; relocate the pointers within each page
|
||||
mov BX,DEDPAGES*WORDINCR ; initialize page counter
|
||||
srel_lop: test attrib+[BX],NOMEMORY
|
||||
jnz srel_nxt
|
||||
mov DI,SS:ptype+[BX] ; get data type for page
|
||||
cmp DI,FREETYPE*2 ; Free Page?
|
||||
je srel_nxt ; Yes...continue
|
||||
push BX ; save the page counter
|
||||
call rel_page ; relocate pointers in current page
|
||||
pop BX ; restore page counter
|
||||
srel_nxt: add BX,WORDINCR ; increment page counter
|
||||
cmp BX,NUMPAGES*WORDINCR ; all pages processed?
|
||||
jb srel_lop ; if more pages, jump
|
||||
|
||||
; relocate registers R1-R63
|
||||
xor BX,BX ; clear BX
|
||||
mov CX,NUM_REGS-1 ; load number of registers ('cept for R0)
|
||||
mov DI,offset reg0 + size C_ptr ; load address of R1
|
||||
srel_reg: call rel_reg ; relocate register Rn
|
||||
add DI,size C_ptr ; increment pointer to next reigster
|
||||
loop srel_reg ; loop until R1-R63 relocated
|
||||
|
||||
; relocate the other internal registers
|
||||
mov DI,offset FNV_reg
|
||||
call rel_reg ; relocate FNV_reg
|
||||
mov DI,offset GNV_reg
|
||||
call rel_reg ; relocate GNV_reg
|
||||
mov DI,offset PREV_reg
|
||||
call rel_reg ; relocate PREV_reg
|
||||
mov DI,offset CB_reg
|
||||
call rel_reg ; relocate CB_reg
|
||||
mov DI,offset TRNS_reg
|
||||
call rel_reg ; relocate TRNS_reg
|
||||
mov DI,offset tmp_reg
|
||||
call rel_reg ; relocate tmp_reg
|
||||
mov DI,offset tm2_reg
|
||||
call rel_reg ; relocate tm2_reg
|
||||
mov DI,offset FNV_save
|
||||
call rel_reg ; relocate FNV_save
|
||||
mov DI,offset STL_save
|
||||
call rel_reg ; relocate STL_save
|
||||
|
||||
; relocate the system oblist and the property lists
|
||||
mov CX,HT_SIZE ; load iteration count
|
||||
xor DX,DX ; zero the index
|
||||
rel_tab: mov DI,DX ; copy loop index to DI
|
||||
mov BL,hash_pag+[DI] ; fetch hash table entry page number
|
||||
shl DI,1 ; double index value for use as word index
|
||||
mov SI,hash_dis+[DI] ; fetch hash table entry displacement
|
||||
call rel_ptr ; relocate the pointer
|
||||
mov hash_dis+[DI],SI ; store the relocated
|
||||
mov SI,DX ; pointer back into the
|
||||
mov hash_pag+[SI],BL ; system hash table
|
||||
mov BL,prop_pag+[SI] ; fetch property list entry page number
|
||||
mov SI,prop_dis+[DI] ; and displacement
|
||||
call rel_ptr ; relocate the property list entry pointer
|
||||
mov prop_dis+[DI],SI ; store the relocated
|
||||
mov DI,DX ; pointer back into the
|
||||
mov prop_pag+[DI],BL ; system property list table
|
||||
inc DX ; increment the loop index
|
||||
loop rel_tab ; continue 'til all entries processed
|
||||
|
||||
; Relocate the pointers in the runtime stack
|
||||
mov DI,offset S_stack ; load address of stack buffer
|
||||
mov DX,TOS ; load current top of stack and
|
||||
add DX,DI ; compute stack's ending address
|
||||
rel_stk: mov BL,[DI].car_page ; load next stack entry from the
|
||||
mov SI,[DI].car ; stack buffer
|
||||
call rel_ptr ; relocate the pointer
|
||||
mov [DI].car_page,BL ; store the relocated pointer back into
|
||||
mov [DI].car,SI ; the stack buffer
|
||||
add DI,PTRSIZE ; increment the stack buffer pointer
|
||||
cmp DI,DX ; end of active stack buffer?
|
||||
jbe rel_stk ; if more entries in stack, jump
|
||||
|
||||
; Relocate the pointers in the object hash table
|
||||
mov CX,OHT_SIZE ; load count of object hash table entries
|
||||
mov DI,offset obj_ht ; load address of object hash table
|
||||
rel_oht: mov BL,[DI].car_page ; load next entry in the
|
||||
mov SI,[DI].car ; object hash table
|
||||
call rel_ptr ; relocate the pointer
|
||||
mov [DI].car_page,BL ; store the relocated pointer back
|
||||
mov [DI].car,SI ; into the object hash table
|
||||
add DI,PTRSIZE ; increment the loop index
|
||||
loop rel_oht ; continue until all entries processed
|
||||
|
||||
; Return to caller
|
||||
rel_rtn: pop BP ; restore caller's BP register
|
||||
pop ES ; and ES register
|
||||
ret ; return
|
||||
srelocat endp
|
||||
|
||||
;************************************************************************
|
||||
;* Local Support-- Relocate pointers in a single page *
|
||||
;************************************************************************
|
||||
rel_page proc near
|
||||
mov page_sav,BX ; Save this page number
|
||||
%LoadPage ES,BX ; load the page's paragraph address
|
||||
;;; mov ES,pagetabl+[BX] ; load the page's paragraph address
|
||||
mov DX,psize+[BX] ; load the current page size
|
||||
sub DX,PTRSIZE ; and adjust for end of page boundary
|
||||
mov SI,ptype+[BX]
|
||||
xor DI,DI ; zero the page index
|
||||
xor BX,BX ; zero BX
|
||||
jmp btable+[SI]
|
||||
|
||||
rel_list: ; [0] List cells
|
||||
sub DX,LISTSIZE-PTRSIZE
|
||||
rel_l010: mov BL,ES:[DI].car_page ; fetch the car field's page number
|
||||
cmp BL,0FFh ; unused list cell?
|
||||
je rel_l020 ; if unused, jump
|
||||
test byte ptr ES:[DI].list_gc,GC_BIT ; is this a relocated pointer?
|
||||
jnz rel_l020 ; if a relocated ptr, leave it alone
|
||||
mov SI,ES:[DI].car ; fetch the car field's displacement field
|
||||
call rel_ptr ; relocate the pointer
|
||||
%LoadPage ES,page_sav ; Re-load source page
|
||||
mov ES:[DI].car_page,BL ; store the relocated car pointer
|
||||
mov ES:[DI].car,SI ; back into the list cell
|
||||
mov BL,ES:[DI].cdr_page ; fetch the cdr field from
|
||||
mov SI,ES:[DI].cdr ; the list cell
|
||||
call rel_ptr ; relocate the pointer
|
||||
%LoadPage ES,page_sav ; Re-load source page
|
||||
mov ES:[DI].cdr_page,BL ; store the relocated cdr pointer
|
||||
mov ES:[DI].cdr,SI ; back into the list cell
|
||||
rel_l020: add DI,LISTSIZE ; increment the page index
|
||||
cmp DI,DX ; end of page?
|
||||
jbe rel_l010 ; if more list cells to process, jump
|
||||
jmp rel_ret ; return
|
||||
|
||||
rel_sym: ; [4] Symbols
|
||||
rel_port: ; [12] Port data objects
|
||||
rel_s010: cmp ES:[DI].sym_type,FREETYPE ; free block?
|
||||
je rel_s020 ; if free block, jump
|
||||
test ES:[DI].sym_gc,GC_BIT ; is this a relocated object?
|
||||
jnz rel_s020 ; if a forwarding pointer, jump
|
||||
mov BL,ES:[DI].sym_page ; load pointer operand from the
|
||||
mov SI,ES:[DI].sym_disp ; port or symbol object
|
||||
call rel_ptr ; relocate the pointer, if needed
|
||||
%LoadPage ES,page_sav ; Re-load source page
|
||||
mov ES:[DI].sym_page,BL ; store relocated pointer back in
|
||||
mov ES:[DI].sym_disp,SI ; the port or symbol
|
||||
rel_s020: add DI,ES:[DI].sym_len ; increment the page index
|
||||
cmp DI,DX ; end of page?
|
||||
jbe rel_s010 ; if not end of page, jump
|
||||
jmp rel_ret ; return
|
||||
|
||||
|
||||
rel_code: ; [10] Code
|
||||
rel_c010: cmp ES:[DI].cod_type,FREETYPE ; is this a free block?
|
||||
je rel_c030 ; if unused block, jump
|
||||
test ES:[DI].cod_gc,GC_BIT ; is this a relocated code block?
|
||||
jnz rel_c030 ; if a forwarding pointer, jump
|
||||
mov AX,DI ; save starting offset of object
|
||||
mov CX,ES:[DI].cod_entr ; load the entry point
|
||||
add CX,DI ; and compute ending offset
|
||||
sub CX,BLK_OVHD+PTRSIZE
|
||||
jmp short rel_c025 ; test for code block with no constants
|
||||
rel_c020: mov BL,ES:[DI].cod_cpag ; load next pointer from the
|
||||
mov SI,ES:[DI].cod_cdis ; object
|
||||
call rel_ptr ; relocate pointer, if needed
|
||||
%LoadPage ES,page_sav ; Re-load source page
|
||||
mov ES:[DI].cod_cpag,BL ; store the relocated pointer
|
||||
mov ES:[DI].cod_cdis,SI ; back into the object
|
||||
add DI,PTRSIZE ; increment the page index
|
||||
rel_c025: cmp DI,CX ; all pointers updated?
|
||||
jb rel_c020 ; if more pointers, jump
|
||||
mov DI,AX ; restore starting offset of object
|
||||
rel_c030: add DI,ES:[DI].cod_len ; adjust index for free area
|
||||
cmp DI,DX ; end of page?
|
||||
jbe rel_c010 ; if not end of page, jump
|
||||
jmp rel_ret ; return
|
||||
|
||||
rel_ary: ; [6] Arrays
|
||||
rel_cont: ; [7] Continuations
|
||||
rel_clos: ; [8] Closures
|
||||
rel_env: ; [14] Environments
|
||||
rel_v010: cmp ES:[DI].vec_type,FREETYPE ; is this a free block?
|
||||
je rel_v030 ; if unused block, jump
|
||||
test ES:[DI].vec_gc,GC_BIT ; has object been relocated?
|
||||
jnz rel_v030 ; if a forwarding pointer, jump
|
||||
mov AX,DI ; save starting offset of object
|
||||
mov CX,ES:[DI].vec_len ; load the object's length
|
||||
add CX,DI ; and compute ending offset
|
||||
sub CX,BLK_OVHD ; adjust ending offset for block header
|
||||
jmp short rel_v025 ; test for zero length object
|
||||
rel_v020: mov BL,ES:[DI].vec_page ; load next pointer from the
|
||||
mov SI,ES:[DI].vec_disp ; object
|
||||
call rel_ptr ; relocate pointer, if needed
|
||||
%LoadPage ES,page_sav ; Re-load source page
|
||||
mov ES:[DI].vec_page,BL ; store the relocated pointer
|
||||
mov ES:[DI].vec_disp,SI ; back into the object
|
||||
add DI,PTRSIZE ; increment the page index
|
||||
rel_v025: cmp DI,CX ; all pointers updated?
|
||||
jb rel_v020 ; if more pointers, jump
|
||||
mov DI,AX ; restore starting offset of object
|
||||
rel_v030: add DI,ES:[DI].vec_len ; adjust index for free area
|
||||
cmp DI,DX ; end of page?
|
||||
jbe rel_v010 ; if not end of page, jump
|
||||
jmp rel_ret ; return
|
||||
|
||||
rel_fix: ; [1] Fixnums
|
||||
rel_flo: ; [2] Flonums
|
||||
rel_big: ; [3] Bignums
|
||||
rel_str: ; [5] Strings
|
||||
rel_free: ; [9] Free space (unallocated)
|
||||
rel_ref: ; [11] Reference cells (hope not...)
|
||||
rel_char: ; [13] Characters
|
||||
|
||||
rel_ret: ret ; return to caller
|
||||
rel_page endp
|
||||
|
||||
;************************************************************************
|
||||
;* Local Support-- Relocate a pointer contained in a register *
|
||||
;* *
|
||||
;* Parameters: DI - address of register *
|
||||
;************************************************************************
|
||||
rel_reg proc near
|
||||
xor BX,BX ; clear BX
|
||||
mov BL,byte ptr [DI].C_page ; fetch the register's
|
||||
mov SI,[DI].C_disp ; contents
|
||||
call rel_ptr ; relocate the pointer
|
||||
mov byte ptr [DI].C_page,BL ; store the relocated pointer
|
||||
mov [DI].C_disp,SI ; back into the register
|
||||
ret ; return
|
||||
rel_reg endp
|
||||
|
||||
;************************************************************************
|
||||
;* Local Support-- Relocate a single pointer *
|
||||
;* *
|
||||
;* Parameters: BX - page number index (page*2) *
|
||||
;* SI - displacement *
|
||||
;************************************************************************
|
||||
rel_ptr proc near
|
||||
cmp BX,DEDPAGES*WORDINCR ; is this a special non-GCed page?
|
||||
jl rep_ret1 ; if special page, no relocation done
|
||||
push ES ; save caller's ES
|
||||
push DI ; and save caller's DI
|
||||
%LoadPage ES,BX ; load the paragraph address for ptr's page
|
||||
;;; mov ES,pagetabl+[BX] ; load paragraph address for pointer's page
|
||||
mov DI,ptype+[BX]
|
||||
cmp DI,NUMTYPES*2
|
||||
jae rel_oops
|
||||
jmp ctable+[DI] ; jump according to pointer type
|
||||
|
||||
; ***error-- invalid type/length code***
|
||||
rel_oops: pushm <AX,CX,DX,SI,BX> ; save registers; push page:disp
|
||||
mov AX,offset msg_relp ; move address of "format"
|
||||
push AX ; and push as argument to printf
|
||||
mov AX,DS ; make ES point to the data segment
|
||||
mov ES,AX
|
||||
call %printf ; print the error message
|
||||
call %forcede ; invoke the VM debugger with next instr.
|
||||
popm <AX,BX,SI,DX,CX,AX> ; restore registers
|
||||
jmp short rep_ret ; return
|
||||
|
||||
rep_list: ; [0] List Cells
|
||||
test byte ptr ES:[SI].list_gc,GC_BIT ; has cell been relocated?
|
||||
jz rep_ret ; if not moved, return (jump)
|
||||
mov BL,ES:[SI].car_page ; replace original pointer with
|
||||
mov SI,ES:[SI].car ; the updated pointer
|
||||
and SI,07FFFh ; clear the GC bit
|
||||
jmp short rep_ret ; return
|
||||
|
||||
rep_flo: ; [2] Flonums
|
||||
test byte ptr ES:[SI].flo_gc,GC_bit ; has flonum been relocated?
|
||||
jz rep_ret ; if not moved, return (jump)
|
||||
mov BL,ES:[SI].flo_data ; replace original pointer with
|
||||
mov SI,word ptr ES:[SI].flo_data+1 ; the updated pointer
|
||||
jmp short rep_ret ; return
|
||||
|
||||
rep_big: ; [3] Bignums
|
||||
rep_sym: ; [4] Symbols
|
||||
rep_str: ; [5] Strings
|
||||
rep_ary: ; [6] Arrays
|
||||
rep_cont: ; [7] Continuations
|
||||
rep_clos: ; [8] Closures
|
||||
rep_code: ; [10] Code
|
||||
rep_port: ; [12] Port data objects
|
||||
rep_env: ; [14] Environments
|
||||
test byte ptr ES:[SI].vec_gc,GC_bit ; has object been relocated?
|
||||
jz rep_ret ; if not moved, return (jump)
|
||||
mov BL,ES:[SI].vec_page ; replace original pointer with
|
||||
mov SI,ES:[SI].vec_disp ; the updated pointer
|
||||
jmp rep_ret ; return
|
||||
|
||||
rep_fix: ; [1] Fixnums
|
||||
rep_free: ; [9] Free space (unallocated)
|
||||
rep_ref: ; [11] Reference cells (hope not...)
|
||||
rep_char: ; [13] Characters
|
||||
|
||||
rep_ret: pop DI ; restore caller's DI
|
||||
pop ES ; restore caller's ES
|
||||
rep_ret1: ret ; return to caller
|
||||
rel_ptr endp
|
||||
|
||||
;************************************************************************
|
||||
;* Complement GC (forwarding) Bits *
|
||||
;************************************************************************
|
||||
public toggleGC
|
||||
toggleGC proc near
|
||||
push ES ; save caller's ES register
|
||||
push BP ; and BP register
|
||||
mov BP,SP ; and establish addressability
|
||||
mov BX,DEDPAGES*WORDINCR ; initialize page counter
|
||||
togl_lop: test attrib+[BX],NOMEMORY
|
||||
jnz togl_nxt
|
||||
mov DI,SS:ptype+[BX] ; get data type for page
|
||||
cmp DI,FREETYPE*2 ; Free Page?
|
||||
je togl_nxt ; Yes...continue
|
||||
push BX ; save the page counter
|
||||
call togl_pag ; complement GC bits in current page
|
||||
pop BX ; restore page counter
|
||||
togl_nxt: add BX,WORDINCR ; increment page counter
|
||||
cmp BX,NUMPAGES*WORDINCR ; all pages processed?
|
||||
jb togl_lop ; if more pages, jump
|
||||
mov SP,BP
|
||||
pop BP
|
||||
pop ES
|
||||
ret
|
||||
toggleGC endp
|
||||
|
||||
|
||||
togl_pag proc near
|
||||
%LoadPage ES,BX ; load the page's paragraph address
|
||||
;;; mov ES,pagetabl+[BX] ; load the page's paragraph address
|
||||
mov DX,psize+[BX] ; load the current page size
|
||||
sub DX,PTRSIZE ; and adjust for end of page boundary
|
||||
mov SI,ptype+[BX]
|
||||
xor DI,DI ; zero the page index
|
||||
xor BX,BX ; zero BX
|
||||
jmp dtable+[SI]
|
||||
|
||||
fwd_list: ; [0] List cells
|
||||
sub DX,LISTSIZE-PTRSIZE
|
||||
fwd_l010: cmp ES:[DI].car_page,0FFh ; unused list cell?
|
||||
je fwd_l020 ; if unused, jump
|
||||
xor byte ptr ES:[DI].list_gc,GC_BIT ; toggle the GC (forward) bit
|
||||
fwd_l020: add DI,LISTSIZE ; increment the page index
|
||||
cmp DI,DX ; end of page?
|
||||
jbe fwd_l010 ; if more list cells to process, jump
|
||||
jmp togl_ret ; return
|
||||
|
||||
|
||||
fwd_flo: ; [2] Flonums
|
||||
sub DX,FLOSIZE-PTRSIZE
|
||||
fwd_f010: cmp byte ptr ES:[DI].flo_type,0FFh ; unused flonum?
|
||||
je fwd_f020 ; if unused, jump
|
||||
xor byte ptr ES:[DI].flo_gc,GC_BIT ; toggle the GC (forward) bit
|
||||
fwd_f020: add DI,FLOSIZE ; increment the page index
|
||||
cmp DI,DX ; end of page?
|
||||
jbe fwd_f010 ; if more flonums to process, jump
|
||||
jmp togl_ret ; return
|
||||
|
||||
|
||||
fwd_str: ; [5] Strings
|
||||
|
||||
fwd_big: ; [3] Bignums
|
||||
fwd_sym: ; [4] Symbols
|
||||
fwd_ary: ; [6] Arrays
|
||||
fwd_cont: ; [7] Continuations
|
||||
fwd_clos: ; [8] Closures
|
||||
fwd_code: ; [10] Code
|
||||
fwd_port: ; [12] Port data objects
|
||||
fwd_env: ; [14] Environments
|
||||
fwd_v010: cmp ES:[DI].vec_type,FREETYPE ; is this a free block?
|
||||
je fwd_v030 ; if unused block, jump
|
||||
xor ES:[DI].vec_gc,GC_BIT ; toggle GC (forward) bit
|
||||
fwd_v030: mov CX,ES:[DI].vec_len ; adjust index for free area
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge fwd_v040
|
||||
mov CX,BLK_OVHD+PTRSIZE
|
||||
fwd_v040: add DI,CX
|
||||
cmp DI,DX ; end of page?
|
||||
jbe fwd_v010 ; if not end of page, jump
|
||||
jmp togl_ret ; return
|
||||
|
||||
fwd_fix: ; [1] Fixnums
|
||||
fwd_free: ; [9] Free space (unallocated)
|
||||
fwd_ref: ; [11] Reference cells
|
||||
fwd_char: ; [13] Characters
|
||||
|
||||
togl_ret: ret ; return to caller
|
||||
togl_pag endp
|
||||
|
||||
PROGX ends
|
||||
end
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,518 @@
|
|||
; =====> SSTRING.ASM
|
||||
;************************************************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* Interpreter -- String Operations *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 18 January 1985 *
|
||||
;* Last Modification: *
|
||||
;* 4/27/88 (tc) - removed case conversion from characters in the range *
|
||||
;* of 128 through 167 (see locases, hicases, collate). *
|
||||
;* Our previous assumptions did not work for some inter-*
|
||||
;* national character sets. *
|
||||
;************************************************************************
|
||||
include scheme.equ
|
||||
include sinterp.mac
|
||||
|
||||
include sinterp.arg
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
|
||||
; Local data definitions
|
||||
m_ch_eq db "CHAR=?",0
|
||||
m_ceq_ci db "CHAR-CI=?",0
|
||||
m_ch_lt db "CHAR<?",0
|
||||
m_chl_ci db "CHAR-CI<?",0
|
||||
m_ch_up db "CHAR-UPCASE",0
|
||||
m_ch_dwn db "CHAR-DOWNCASE",0
|
||||
m_mk_str db "MAKE-STRING",0
|
||||
m_st_fl db "FILL-STRING!",0
|
||||
m_st_ref db "STRING-REF",0
|
||||
m_st_set db "STRING-SET!",0
|
||||
m_one dw 1 ; a constant "one" (1)
|
||||
m_two dw 2 ; a constant "two" (2)
|
||||
m_soff dw STRING_OFFSET_ERROR ; error code
|
||||
|
||||
; Case tables (for characters between 40h and 0bfh)
|
||||
public locases,hicases,collate
|
||||
|
||||
locases db 000,001,002,003,004,005,006,007
|
||||
db 008,009,010,011,012,013,014,015
|
||||
db 016,017,018,019,020,021,022,023
|
||||
db 024,025,026,027,028,029,030,031
|
||||
db " ","!",'"',"#","$","%","&","'"
|
||||
db "(",")","*","+",",","-",".","/"
|
||||
db "0","1","2","3","4","5","6","7"
|
||||
db "8","9",":",";","<","=",">","?"
|
||||
|
||||
db "@","a","b","c","d","e","f","g"
|
||||
db "h","i","j","k","l","m","n","o"
|
||||
db "p","q","r","s","t","u","v","w"
|
||||
db "x","y","z","[","\","]","^","_"
|
||||
db "`","a","b","c","d","e","f","g"
|
||||
db "h","i","j","k","l","m","n","o"
|
||||
db "p","q","r","s","t","u","v","w"
|
||||
db "x","y","z","{","|","}","~",127
|
||||
; C .. ' ^ .. ` o c
|
||||
; ' u e a a a a '
|
||||
db 128,129,130,131,132,133,134,135 ;135,129,130,131,132,133,134,135
|
||||
; ^ .. ` .. ^ ` .. o
|
||||
; e e e i i i A A
|
||||
db 136,137,138,139,140,141,142,143 ;136,137,138,139,140,141,132,134
|
||||
; ' ^ .. ` ^ `
|
||||
; E ae AE o o o u u
|
||||
db 144,145,146,147,148,149,150,151 ;130,145,145,147,148,149,150,151
|
||||
; .. .. ..
|
||||
; y O U (currency symbols)
|
||||
db 152,153,154,155,156,157,158,159 ;152,148,129,155,156,157,158,159
|
||||
; ' ' ' ' ~ ~
|
||||
; a i o u n N
|
||||
db 160,161,162,163,164,165,166,167 ;160,161,162,163,164,164,166,167
|
||||
db 168,169,170,171,172,173,174,175
|
||||
db 176,177,178,179,180,181,182,183
|
||||
db 184,185,186,187,188,189,190,191
|
||||
|
||||
db 192,193,194,195,196,197,198,199
|
||||
db 200,201,202,203,204,205,206,207
|
||||
db 208,209,210,211,212,213,214,215
|
||||
db 216,217,218,219,220,221,222,223
|
||||
; beta
|
||||
db 224,225,226,227,228,229,230,231
|
||||
db 232,233,234,235,236,237,238,239
|
||||
db 240,241,242,243,244,245,246,247
|
||||
db 248,249,250,251,252,253,254,255
|
||||
|
||||
hicases db 000,001,002,003,004,005,006,007
|
||||
db 008,009,010,011,012,013,014,015
|
||||
db 016,017,018,019,020,021,022,023
|
||||
db 024,025,026,027,028,029,030,031
|
||||
db " ","!",'"',"#","$","%","&","'"
|
||||
db "(",")","*","+",",","-",".","/"
|
||||
db "0","1","2","3","4","5","6","7"
|
||||
db "8","9",":",";","<","=",">","?"
|
||||
|
||||
db "@","A","B","C","D","E","F","G"
|
||||
db "H","I","J","K","L","M","N","O"
|
||||
db "P","Q","R","S","T","U","V","W"
|
||||
db "X","Y","Z","[","\","]","^","_"
|
||||
db "`","A","B","C","D","E","F","G"
|
||||
db "H","I","J","K","L","M","N","O"
|
||||
db "P","Q","R","S","T","U","V","W"
|
||||
db "X","Y","Z","{","|","}","~",127
|
||||
; C .. ' ^ .. ` o c
|
||||
; ' u e a a a a '
|
||||
db 128,129,130,131,132,133,134,135 ;128,154,144,"A",142,"A",143,128
|
||||
; ^ .. ` .. ^ ` .. o
|
||||
; e e e i i i A A
|
||||
db 136,137,138,139,140,141,142,143 ;"E","E","E","I","I","I",142,143
|
||||
; ' ^ .. ` ^ `
|
||||
; E ae AE o o o u u
|
||||
db 144,145,146,147,148,149,150,151 ;144,146,146,"O",153,"O","U","U"
|
||||
;.. .. ..
|
||||
; y O U (currency symbols)
|
||||
db 152,153,154,155,156,157,158,159 ;"Y",153,154,155,156,157,158,159
|
||||
; ' ' ' ' ~ ~
|
||||
; a i o u n N
|
||||
db 160,161,162,163,164,165,166,167 ;"A","I","O","U",165,165,166,167
|
||||
db 168,169,170,171,172,173,174,175
|
||||
db 176,177,178,179,180,181,182,183
|
||||
db 184,185,186,187,188,189,190,191
|
||||
|
||||
db 192,193,194,195,196,197,198,199
|
||||
db 200,201,202,203,204,205,206,207
|
||||
db 208,209,210,211,212,213,214,215
|
||||
db 216,217,218,219,220,221,222,223
|
||||
; beta
|
||||
db 224,225,226,227,228,229,230,231
|
||||
db 232,233,234,235,236,237,238,239
|
||||
db 240,241,242,243,244,245,246,247
|
||||
db 248,249,250,251,252,253,254,255
|
||||
|
||||
collate db 000,001,002,003,004,005,006,007
|
||||
db 008,009,010,011,012,013,014,015
|
||||
db 016,017,018,019,020,021,022,023
|
||||
db 024,025,026,027,028,029,030,031
|
||||
db " ","!",'"',"#","$","%","&","'"
|
||||
db "(",")","*","+",",","-",".","/"
|
||||
db "0","1","2","3","4","5","6","7"
|
||||
db "8","9",":",";","<","=",">","?"
|
||||
|
||||
db "@","A","B","C","D","E","F","G"
|
||||
db "H","I","J","K","L","M","N","O"
|
||||
db "P","Q","R","S","T","U","V","W"
|
||||
db "X","Y","Z","[","\","]","^","_"
|
||||
db "`","a","b","c","d","e","f","g"
|
||||
db "h","i","j","k","l","m","n","o"
|
||||
db "p","q","r","s","t","u","v","w"
|
||||
db "x","y","z","{","|","}","~",127
|
||||
; C .. ' ^ .. ` o c
|
||||
; ' u e a a a a '
|
||||
db 128,129,130,131,132,133,134,135 ;"C","u","e","a","a","a","a","c"
|
||||
; ^ .. ` .. ^ ` .. o
|
||||
; e e e i i i A A
|
||||
db 136,137,138,139,140,141,142,143 ;"e","e","e","i","i","i","A","A"
|
||||
; ' ^ .. ` ^ `
|
||||
; E ae AE o o o u u
|
||||
db 144,145,146,147,148,149,150,151 ;"E","a","A","o","o","o","u","u"
|
||||
; .. .. ..
|
||||
;y O U (currency symbols)
|
||||
db 152,153,154,155,156,157,158,159 ;"y","O","U","$","$","$","$","$"
|
||||
; ' ' ' ' ~ ~
|
||||
; a i o u n N
|
||||
db 160,161,162,163,164,165,166,177 ;"a","i","o","u","n","N",166,167
|
||||
db 168,169,170,171,172,173,174,175 ;"?",169,170,171,172,"!",'"','"'
|
||||
db 176,177,178,179,180,181,182,183
|
||||
db 184,185,186,187,188,189,190,191
|
||||
|
||||
db 192,193,194,195,196,197,198,199
|
||||
db 200,201,202,203,204,205,206,207
|
||||
db 208,209,210,211,212,213,214,215
|
||||
db 216,217,218,219,220,221,222,223
|
||||
; beta
|
||||
db 224,"s",226,227,228,229,230,231
|
||||
db 232,233,234,235,236,237,238,239
|
||||
db 240,241,242,243,244,245,246,247
|
||||
db 248,249,250,251,252,253,254,255
|
||||
|
||||
data ends
|
||||
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
str_int proc near
|
||||
|
||||
; Entry points defined in "sinterp.asm"
|
||||
extrn next:near ; Top of interpreter
|
||||
extrn next_PC:near ; Reload ES,SI at top of interpreter
|
||||
extrn next_SP:near ; mov SP,BP before next_PC
|
||||
extrn src_err:near ; Source (operand) error print routine
|
||||
extrn sch_err:near ; link to Scheme debugger
|
||||
|
||||
char_cmp macro comparison,case,operation
|
||||
local w,x,y,z
|
||||
lods word ptr ES:[SI] ; load operands
|
||||
xor BX,BX
|
||||
mov BL,AL ; copy the destination=source1 register
|
||||
mov DI,BX ; number, copy into DI, and compute
|
||||
add DI,offset reg0 ; the register's address
|
||||
mov BL,AH ; copy the source2 register number
|
||||
mov AL,byte ptr reg0_pag+[BX] ; load tag of src2 operand
|
||||
cmp AL,SPECCHAR*2 ; is source2 a character?
|
||||
jne z ; if not, error (jump)
|
||||
cmp AL,byte ptr [DI].C_page ; is source1 a character?
|
||||
jne z ; if not, error (jump)
|
||||
IFIDN <case>,<CI>
|
||||
mov AL,byte ptr reg0_dis+[BX] ; move character value of source2
|
||||
mov BX,offset locases ; Fetch lower-case equivalents
|
||||
xlat
|
||||
mov AH,AL ; Save equivalent in AH
|
||||
mov AL,byte ptr[DI].C_disp ; move char value of source1
|
||||
xlat ; Fetch lower-case eqivalent
|
||||
ELSE
|
||||
mov AL,byte ptr [DI].C_disp ; Fetch characters
|
||||
mov AH,byte ptr reg0_dis+[BX]
|
||||
ENDIF
|
||||
mov BX,offset collate ; Get collation values of chars
|
||||
xlat
|
||||
xchg AL,AH
|
||||
xlat
|
||||
cmp AH,AL ; Compare
|
||||
j&comparison y ; jump, if test is satisfied
|
||||
xor AX,AX ; place 'nil in destination
|
||||
mov byte ptr [DI].C_page,AL ; register
|
||||
mov [DI].C_disp,AX
|
||||
jmp next ; return to interpreter
|
||||
y: mov byte ptr [DI].C_page,T_PAGE*2 ; place 't in
|
||||
mov [DI].C_disp,T_DISP ; destination register
|
||||
jmp next ; return to interpreter
|
||||
; ***error-- one (or both) operands aren't characters***
|
||||
z: mov AX,offset operation
|
||||
IFIDN <operation>,<m_ch_eq>
|
||||
error_2: add BX,offset reg0 ; compute address of source 2
|
||||
pushm <BX,DI,m_two,AX> ; push source 2, source 1, operation name
|
||||
C_call set_src_,<SI>,Load_ES ; call: set_source_error
|
||||
jmp sch_err ; link to Scheme debugger
|
||||
ELSE
|
||||
jmp error_2
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (char-= char1 char2) char-= dest,src *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for comparing the equality of *
|
||||
;* character data objects. *
|
||||
;* *
|
||||
;* Description: The tags (page numbers) or the objects are compared *
|
||||
;* for equality. If they are not equal, at least one of *
|
||||
;* the operands is not a character, and an error is *
|
||||
;* signaled. If they are equal, a second check to make *
|
||||
;* sure both are characters is performed. *
|
||||
;* *
|
||||
;* After validating the tag fields, the displacement fields*
|
||||
;* are compared for equality. If they are identical, the *
|
||||
;* characters are equal and 't is returned in the destina- *
|
||||
;* tion register. If not equal, 'nil is returned in the *
|
||||
;* destination register. *
|
||||
;************************************************************************
|
||||
public ch_eq_p
|
||||
ch_eq_p: char_cmp e,CS,m_ch_eq
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (char-equal? char1 char2) char-eq? dest,src *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for comparing the equality of *
|
||||
;* character data objects ignoring case. *
|
||||
;* *
|
||||
;* Description: The tags (page numbers) or the objects are compared *
|
||||
;* for equality. If they are not equal, at least one of *
|
||||
;* the operands is not a character, and an error is *
|
||||
;* signaled. If they are equal, a second check to make *
|
||||
;* sure both are characters is performed. *
|
||||
;* *
|
||||
;* The displacements of both operands are loaded and *
|
||||
;* mapped to uppercase. They are then compared for *
|
||||
;* equality. If equal, 't is returned in the destination *
|
||||
;* registers. Otherwise, 'nil is returned. *
|
||||
;************************************************************************
|
||||
public ch_eq_ci
|
||||
ch_eq_ci: char_cmp e,CI,m_ceq_ci
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (char-<char1 char2) char-< dest,src *
|
||||
;************************************************************************
|
||||
public ch_lt_p
|
||||
ch_lt_p: char_cmp b,CS,m_ch_lt
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (char-less? char1 char2) char-less? dest,src *
|
||||
;************************************************************************
|
||||
public ch_lt_ci
|
||||
ch_lt_ci: char_cmp b,CI,m_chl_ci
|
||||
|
||||
purge char_cmp
|
||||
|
||||
ch_case macro direction,name
|
||||
local y
|
||||
lods byte ptr ES:[SI]
|
||||
mov DI,AX
|
||||
add DI,offset reg0
|
||||
cmp byte ptr [DI].C_page,SPECCHAR*2 ; is input char?
|
||||
jne y ; if not a character, error (jump)
|
||||
mov AL,byte ptr [DI].C_disp ; Put char in AL
|
||||
IFIDN <direction>,<UP>
|
||||
mov BX,offset hicases
|
||||
ELSE
|
||||
IFIDN <direction>,<DOWN>
|
||||
mov BX,offset locases
|
||||
ELSE
|
||||
***error*** Invalid: direction
|
||||
ENDIF
|
||||
ENDIF
|
||||
xlat ; Fetch alternate case
|
||||
mov byte ptr [DI].C_disp,AL ; and store into dest register
|
||||
jmp next
|
||||
; ***error-- invalid source operand***
|
||||
y: mov AX,offset name ; load the instruction's name text
|
||||
IFIDN <direction>,<UP>
|
||||
error_1: pushm <DI,m_one,AX> ; push operand, operand count, instr. name
|
||||
C_call set_src_,<SI>,Load_ES ; call set_source_error
|
||||
jmp sch_err ; link to Scheme debugger
|
||||
ELSE
|
||||
jmp error_1 ; jump to error routine
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
;************************************************************************
|
||||
;* AL *
|
||||
;* (char-upcase char) char-upcase dest *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for conversion of characters *
|
||||
;* to uppercase *
|
||||
;************************************************************************
|
||||
public ch_up
|
||||
ch_up: ch_case UP,m_ch_up
|
||||
|
||||
;************************************************************************
|
||||
;* AL *
|
||||
;* (char-downcase char) char-downcase dest *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for conversion of characters *
|
||||
;* to lowercase *
|
||||
;************************************************************************
|
||||
public ch_down
|
||||
ch_down: ch_case DOWN,m_ch_dwn
|
||||
|
||||
purge ch_case
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (make-string len init) make-string len,init*
|
||||
;************************************************************************
|
||||
public make_str
|
||||
make_str: lods word ptr ES:[SI] ; load the operands of the instruction
|
||||
save <AX,SI> ; save the operands and location pointer
|
||||
xor BX,BX
|
||||
mov BL,AL ; copy the destination register number
|
||||
add BX,offset reg0 ; into BX and compute its address
|
||||
cmp byte ptr [BX].C_page,SPECFIX*2 ; is length a fixnum?
|
||||
jne mk_st_er ; if not, error (jump)
|
||||
mov AX,[BX].C_disp ; load the immediate value for the size
|
||||
shl AX,1 ; and sign extend it
|
||||
sar AX,1
|
||||
jl mk_st_er ; if size is negative, error
|
||||
mov CX,STRTYPE ; load the tag value for the string object
|
||||
pushm <AX,CX,BX> ; push arguments to "alloc_block"
|
||||
C_call alloc_bl,,Load_ES ; call: alloc_block(reg, STRTYPE, len)
|
||||
pop BX ; restore destination register address
|
||||
mov DI,[BX].C_disp ; load a pointer to the newly allocated
|
||||
mov BX,[BX].C_page ; string object
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
restore <AX> ; reload operands to instruction
|
||||
mov BL,AH ; copy initial value register number
|
||||
mov AL,byte ptr reg0_pag+[BX] ; load page number of init value
|
||||
cmp AL,SPECCHAR*2 ; init value a character?
|
||||
je st_fl_3 ; if a character, jump
|
||||
cmp AL,NIL_PAGE*2 ; use default value? (nil?)
|
||||
jne mk_st_er ; if not nil, error (jump)
|
||||
mov AL," " ; load default string fill character
|
||||
jmp short st_fl_4
|
||||
mk_st_er: lea BX,m_mk_str ; load address of "make-string" text
|
||||
jmp src_err ; display "source operand error" message
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (string-fill! string char) string-fill! str,char *
|
||||
;************************************************************************
|
||||
public str_fill
|
||||
str_fill: lods word ptr ES:[SI] ; load string-fill operands
|
||||
save <SI> ; save current location pointer
|
||||
xor BX,BX
|
||||
mov BL,AL ; copy string register number
|
||||
mov DI,BX
|
||||
mov BL,byte ptr reg0_pag+[DI]
|
||||
cmp byte ptr ptype+[BX],STRTYPE*2 ; is 1st operand a string?
|
||||
jne st_fl_er ; if not, error (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load a pointer to the string object
|
||||
mov DI,reg0_dis+[DI]
|
||||
mov BL,AH ; copy initialization value register number
|
||||
cmp reg0_pag+[BX],SPECCHAR*2 ; is it a char?
|
||||
jne st_fl_er ; if not, error
|
||||
st_fl_3: mov AL,byte ptr reg0_dis+[BX] ; load initialization character
|
||||
st_fl_4: mov CX,ES:[DI].str_len ; load length of string object
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge st_010
|
||||
add CX,BLK_OVHD+PTRSIZE ;;; adjust for small string
|
||||
st_010: sub CX,offset str_data ; compute number of characters
|
||||
add DI,offset str_data ; advance index to 1st character position
|
||||
rep stosb ; fill string object with init character
|
||||
jmp next_SP ; return to interpreter
|
||||
st_fl_er: lea BX,m_st_fl ; load address of "fill-string" text
|
||||
jmp src_err ; display "source operand error" message
|
||||
|
||||
str_int endp
|
||||
|
||||
;************************************************************************
|
||||
;* Macro Support for String ref/set *
|
||||
;************************************************************************
|
||||
st_thing macro ref_or_set,message
|
||||
local w,x,y,z
|
||||
lods word ptr ES:[SI] ; load string pointer and index regs
|
||||
xor BX,BX
|
||||
mov BL,AL ; copy string/dest reg number into DI
|
||||
mov DI,BX
|
||||
IFIDN <ref_or_set>,<SET>
|
||||
lods byte ptr ES:[SI] ; load source operand register number
|
||||
mov DL,AL ; and save it in TIPC register DL
|
||||
ENDIF
|
||||
save <SI> ; save the location pointer
|
||||
mov BL,byte ptr reg0_pag+[DI] ; load string page number
|
||||
cmp byte ptr ptype+[BX],STRTYPE*2 ; is it a string?
|
||||
jne y ; if not a string, error (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov BL,AH ; copy index register number
|
||||
cmp byte ptr reg0_pag+[BX],SPECFIX*2 ; is index a fixnum?
|
||||
jne y ; if not a fixnum, error (jump)
|
||||
mov AX,reg0_dis+[BX] ; load immediate value and
|
||||
shl AX,1 ; sign extend to 16 bits
|
||||
sar AX,1
|
||||
jl z ; if index negative, error (jump)
|
||||
add AX,offset str_data ; advance pointer past string header
|
||||
mov SI,reg0_dis+[DI] ; load pointer to string object
|
||||
mov CX,ES:[SI].str_len ; compare index with string length
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge w
|
||||
add CX,BLK_OVHD+PTRSIZE ;;; adjust for small string
|
||||
w: cmp AX,CX
|
||||
jge z ; if index too large, error (jump)
|
||||
add SI,AX ; add index to string pointer
|
||||
IFIDN <ref_or_set>,<REF>
|
||||
mov byte ptr reg0_pag+[DI],SPECCHAR*2 ; set tag=character
|
||||
mov BL,ES:[SI] ; fetch desired character
|
||||
mov reg0_dis+[DI],BX ; and store into destination register
|
||||
ELSE
|
||||
IFIDN <ref_or_set>,<SET>
|
||||
mov BL,DL ; copy source value register number
|
||||
cmp byte ptr reg0_pag+[BX],SPECCHAR*2 ; is source a character?
|
||||
jne y ; if not a character, error (jump)
|
||||
mov AL,byte ptr reg0_dis+[BX] ; store source character into
|
||||
mov ES:[SI],AL ; string at desired offset
|
||||
ELSE
|
||||
***error*** Invalid: ref_or_set
|
||||
ENDIF
|
||||
ENDIF
|
||||
jmp next_PC ; return to interpreter
|
||||
; ***error-- invalid source operand***
|
||||
y: lea BX,message ; load address of operation name text
|
||||
jmp src_err ; display "source operand error" message
|
||||
; ***error-- invalid string offset***
|
||||
z: mov BX,offset message ; load address of instruction name
|
||||
IFIDN <ref_or_set>,<REF>
|
||||
mov DX,3 ; STRING-REF is 3 bytes long
|
||||
s_out_bn: restore <SI> ; load location pointer and
|
||||
sub SI,DX ; back up to start of instruction in error
|
||||
pushm <SI,BX> ; push instruction's offset, name
|
||||
C_call disassem,,Load_ES ; disassemble instruction for *irritant*
|
||||
pushm <tmp_adr,m_soff,m_one> ; push args to "set_numeric_error"
|
||||
C_call set_nume ; set_numeric_error(1,ST_OFF_ERR,tmp_reg);
|
||||
restore <SI> ; load offset of next instruction
|
||||
jmp sch_err ; Link to Scheme debugger
|
||||
ELSE
|
||||
mov DX,4 ; STRING-SET! is 4 bytes long
|
||||
jmp s_out_bn ; continue error processing
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (string-ref string index) string-ref str,index *
|
||||
;************************************************************************
|
||||
public st_ref
|
||||
st_ref: st_thing REF,m_st_ref
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH AL *
|
||||
;* (string-set! string index char) string-set! str,index,char *
|
||||
;************************************************************************
|
||||
public st_set
|
||||
st_set: st_thing SET,m_st_set
|
||||
|
||||
purge st_thing
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
; =====> STACKF.EQU
|
||||
; Copyright 1984,1985 by Texas Instruments Incorporated.
|
||||
; All Rights Reserved.
|
||||
;
|
||||
; Last Modification: 4 August 1985
|
||||
|
||||
; Stack Frame
|
||||
;
|
||||
; +------------------+
|
||||
; Stack base -> | stack for prev |
|
||||
; : dynamic levels :
|
||||
; |------------------|
|
||||
; Frame pointer ->| code base -> | \
|
||||
; |------------------| | return address
|
||||
; | return addr disp | /
|
||||
; |------------------|
|
||||
; | dynamic link | caller's FP
|
||||
; |------------------|
|
||||
; | environment | current environment
|
||||
; |------------------|
|
||||
; | static link | lexical parent's FP
|
||||
; |------------------|
|
||||
; | closure ptr | pointer to routine's closure object
|
||||
; |------------------| (or nil, if an open call)
|
||||
; | local |
|
||||
; : variable :
|
||||
; top of stack -> | allocation |
|
||||
; +------------------+
|
||||
sf_def struc
|
||||
|
||||
sf_cb_pag db ? ; code base pointer page number
|
||||
sf_cb_dis dw ? ; code base pointer displacement
|
||||
|
||||
sf_rtag db SPECFIX*2 ; return address tag=fixnum
|
||||
sf_ret dw ? ; return address displacement
|
||||
|
||||
sf_dtag db SPECFIX*2 ; dynamic link tag=fixnum
|
||||
sf_ddisp dw ? ; dynamic link displacement
|
||||
|
||||
sf_hpage db ? ; heap environment page number
|
||||
sf_hdisp dw ? ; heap environment displacement
|
||||
|
||||
sf_stag db SPECFIX*2 ; lex parent's static link tag=fixnum
|
||||
sf_sdisp dw ? ; lex parent's static link displacement
|
||||
|
||||
sf_cl_pg db ? ; closure pointer page number
|
||||
sf_cl_ds dw ? ; closure pointer page number
|
||||
|
||||
; start of local variable allocation area
|
||||
sf_dat_p db ? ; local variable's page number
|
||||
sf_dat_d dw ? ; local variable's displacement
|
||||
|
||||
sf_def ends
|
||||
SF_OVHD equ sf_dat_p-sf_cb_pag ; size of stack frame header
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
*
|
||||
* This header file defines the information used by the standard I/O
|
||||
* package.
|
||||
*
|
||||
**/
|
||||
#define _BUFSIZ 512 /* standard buffer size */
|
||||
#define BUFSIZ 512 /* standard buffer size */
|
||||
#define _NFILE 20 /* maximum number of files */
|
||||
|
||||
struct _iobuf
|
||||
{
|
||||
unsigned char *_ptr; /* current buffer pointer */
|
||||
int _rcnt; /* current byte count for reading */
|
||||
int _wcnt; /* current byte count for writing */
|
||||
unsigned char *_base; /* base address of I/O buffer */
|
||||
int _size; /* size of buffer */
|
||||
int _flag; /* control flags */
|
||||
unsigned char _file; /* file number */
|
||||
unsigned char _cbuff; /* single char buffer */
|
||||
};
|
||||
|
||||
extern struct _iobuf _iob[_NFILE];
|
||||
|
||||
/**
|
||||
*
|
||||
* Definitions associated with _iobuf._flag
|
||||
*
|
||||
*/
|
||||
#define _IOFBF 0 /* fully buffered (for setvbuf) */
|
||||
#define _IOREAD 1 /* read flag */
|
||||
#define _IOWRT 2 /* write flag */
|
||||
#define _IONBF 4 /* non-buffered flag */
|
||||
#define _IOMYBUF 8 /* private buffer flag */
|
||||
#define _IOEOF 16 /* end-of-file flag */
|
||||
#define _IOERR 32 /* error flag */
|
||||
#define _IOLBF 64 /* line-buffered flag */
|
||||
#define _IORW 128 /* read-write (update) flag */
|
||||
#define _IOAPP 0x4000 /* append flag */
|
||||
#define _IOXLAT 0x8000 /* translation flag */
|
||||
|
||||
#ifndef NULL
|
||||
#if SPTR
|
||||
#define NULL 0 /* null pointer value */
|
||||
#else
|
||||
#define NULL 0L
|
||||
#endif
|
||||
#endif
|
||||
#define FILE struct _iobuf /* shorthand */
|
||||
#define EOF (-1) /* end-of-file code */
|
||||
|
||||
|
||||
#define stdin (&_iob[0]) /* standard input file pointer */
|
||||
#define stdout (&_iob[1]) /* standard output file pointer */
|
||||
#define stderr (&_iob[2]) /* standard error file pointer */
|
||||
#define stdaux (&_iob[3]) /* standard auxiliary file pointer */
|
||||
#define stdprt (&_iob[4]) /* standard printer file pointer */
|
||||
|
||||
|
||||
#define getc(p) (--(p)->_rcnt>=0? *(p)->_ptr++:_filbf(p))
|
||||
#define getchar() getc(stdin)
|
||||
#define putc(c,p) (--(p)->_wcnt>=0? ((int)(*(p)->_ptr++=(c))):_flsbf((c),p))
|
||||
#define putchar(c) putc(c,stdout)
|
||||
#define feof(p) (((p)->_flag&_IOEOF)!=0)
|
||||
#define ferror(p) (((p)->_flag&_IOERR)!=0)
|
||||
#define fileno(p) (p)->_file
|
||||
#define rewind(fp) fseek(fp,0L,0)
|
||||
#define fflush(fp) _flsbf(-1,fp)
|
||||
#define clearerr(fp) clrerr(fp)
|
||||
|
||||
#ifndef NARGS
|
||||
extern void clrerr(FILE *);
|
||||
extern int cprintf(char *, );
|
||||
extern int cscanf(char *, );
|
||||
extern int fclose(FILE *);
|
||||
extern int fcloseall(void);
|
||||
extern FILE *fdopen(int, char *);
|
||||
extern int fgetc(FILE *);
|
||||
extern int fgetchar(void);
|
||||
extern char *fgets(char *, int, FILE *);
|
||||
extern int flushall(void);
|
||||
extern int fmode(FILE *, int);
|
||||
extern FILE *fopen(char *, char *);
|
||||
extern FILE *fopene(char *, char *, char *);
|
||||
extern int fprintf(FILE *, char *, );
|
||||
extern int fputc(int, FILE *);
|
||||
extern int fputchar(int);
|
||||
extern int fputs(char *, FILE *);
|
||||
extern int fread(char *, int, int, FILE *);
|
||||
extern FILE *freopen(char *, char *, FILE *);
|
||||
extern int fscanf(FILE*, char *, );
|
||||
extern int fseek(FILE *, long, int);
|
||||
extern long ftell(FILE *);
|
||||
extern int fwrite(char *, int, int, FILE *);
|
||||
extern char *gets(char *);
|
||||
extern int printf(char *, );
|
||||
extern int puts(char *);
|
||||
extern scanf(char *, );
|
||||
extern int setbuf(FILE *, char *);
|
||||
extern int setnbf(FILE *);
|
||||
extern int setvbuf(FILE*, char *, int, int);
|
||||
extern int sprintf(char *, char *, );
|
||||
extern sscanf(char *, char *, );
|
||||
extern int ungetc(int, FILE *);
|
||||
extern int _filbf(FILE *);
|
||||
extern int _flsbf(int, FILE *);
|
||||
|
||||
#else
|
||||
extern void clrerr();
|
||||
extern int cprintf();
|
||||
extern int cscanf();
|
||||
extern int fclose();
|
||||
extern int fcloseall();
|
||||
extern FILE *fdopen();
|
||||
extern int fgetc();
|
||||
extern int fgetchar();
|
||||
extern char *fgets();
|
||||
extern int flushall();
|
||||
extern int fmode();
|
||||
extern FILE *fopen();
|
||||
extern FILE *fopene();
|
||||
extern int fprintf();
|
||||
extern int fputc();
|
||||
extern int fputchar();
|
||||
extern int fputs();
|
||||
extern int fread();
|
||||
extern FILE *freopen();
|
||||
extern int fscanf();
|
||||
extern int fseek();
|
||||
extern long ftell();
|
||||
extern int fwrite();
|
||||
extern char *gets();
|
||||
extern int printf();
|
||||
extern int puts();
|
||||
extern scanf();
|
||||
extern int setbuf();
|
||||
extern int setnbf();
|
||||
extern int setvbuf();
|
||||
extern int sprintf();
|
||||
extern sscanf();
|
||||
extern int ungetc();
|
||||
extern int _filbf();
|
||||
extern int _flsbf();
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Miscellaneous I/O services
|
||||
*
|
||||
*/
|
||||
#ifndef NARGS
|
||||
extern int access(char *, int);
|
||||
extern int chdir(char *);
|
||||
extern int chmod(char *, int);
|
||||
extern char *getcwd(char *, int);
|
||||
extern int mkdir(char *);
|
||||
extern int perror(char *);
|
||||
extern int rename(char *, char *);
|
||||
extern int rmdir(char *);
|
||||
extern char *tmpnam(char *);
|
||||
#else
|
||||
extern int access();
|
||||
extern int chdir();
|
||||
extern int chmod();
|
||||
extern char *getcwd();
|
||||
extern int mkdir();
|
||||
extern int perror();
|
||||
extern int rename();
|
||||
extern int rmdir();
|
||||
extern char *tmpnam();
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
; =====> STIMER.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Engine Timer *
|
||||
;* Utilities *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: June 1985 *
|
||||
;* Last Modification: 30 July 1985 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
timer_int db 58h ;40 Hz timer interrupt number
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
dos_func equ 21h ;DOS function call interrupt number
|
||||
get_vec equ 35h ;DOS call to retrieve interrupt vector
|
||||
set_vec equ 25h ;Call to set vector
|
||||
|
||||
public tickstat
|
||||
tickstat db -1 ;0=timeout, 1=engine running,
|
||||
; -1=no engine running (normal)
|
||||
clk_ptr dw 0,0 ;Former timer vector
|
||||
lo_time dw 0 ;Timer ticks
|
||||
hi_time dw 0
|
||||
|
||||
; Start timer running
|
||||
; Calling sequence: set_timer(hi,lo)
|
||||
; Where ---- hi,lo: upper,lower words of initial timer value
|
||||
; Returns nonzero iff the set was during normal VM running mode
|
||||
set_args struc
|
||||
dw ? ;Caller's BP
|
||||
dw ? ;Return address
|
||||
hi dw ? ;High word
|
||||
lo dw ? ;Low word
|
||||
set_args ends
|
||||
public settimer
|
||||
settimer proc near
|
||||
cmp PC_MAKE,252 ;Is computer an IBM variant?
|
||||
jb nochange ;Jump if not
|
||||
mov timer_int,1ch ;Otherwise, set to IBM's vector
|
||||
nochange: xor AX,AX ;Clear AX
|
||||
cmp CS:tickstat,-1 ;Check for normal run mode
|
||||
jne no_set ;Abort if timeout or engine running
|
||||
push BP
|
||||
mov BP,SP
|
||||
push ES ;Save ES
|
||||
mov AH,get_vec ;Put present timer interrupt vector
|
||||
mov AL,timer_int ; into ES:BX
|
||||
int dos_func
|
||||
mov CS:clk_ptr,BX ;Save vector
|
||||
mov CS:clk_ptr+2,ES
|
||||
pop ES ;Restore ES
|
||||
mov AX,[BP].hi ;Set timer
|
||||
mov CS:hi_time,AX
|
||||
mov AX,[BP].lo
|
||||
mov CS:lo_time,AX
|
||||
push DS ;Save DS
|
||||
mov AH,set_vec ;Set new interrupt vector
|
||||
mov AL,timer_int
|
||||
push CS ;Put vector segment number in DS
|
||||
pop DS
|
||||
mov DX,offset tick ;Vector offset in DX
|
||||
int dos_func
|
||||
pop DS ;Restore DS
|
||||
mov AL,1 ;Denote engine running
|
||||
mov CS:tickstat,AL
|
||||
pop BP ;Restore BP
|
||||
no_set: ret
|
||||
settimer endp
|
||||
|
||||
; Stop the timer
|
||||
; Calling sequence: rst_timer();
|
||||
; Returns the number in the counter at the time of reset
|
||||
public rsttimer
|
||||
rsttimer proc near
|
||||
cmp CS:tickstat,1 ;Only if timeout or engine running
|
||||
ja no_reset ;Otherwise forget it
|
||||
mov AH,set_vec ;Prepare to reset timer interrupt
|
||||
mov AL,timer_int
|
||||
push DS ;Save DS
|
||||
lds DX,dword ptr CS:clk_ptr ;Put original vector into DS:DX
|
||||
int dos_func
|
||||
pop DS ;Restore DS
|
||||
mov CS:tickstat,-1 ;Denote normal mode
|
||||
no_reset: mov AX,CS:hi_time ;Return 32-bit clock value
|
||||
mov BX,CS:lo_time
|
||||
ret
|
||||
rsttimer endp
|
||||
|
||||
;The new timer code
|
||||
tick proc near
|
||||
sti ;Re-enable interrupts
|
||||
cmp CS:tickstat,0 ;If timeout, do nothing special
|
||||
je norm_vec
|
||||
sub CS:lo_time,1 ;Otherwise decrement counter
|
||||
sbb CS:hi_time,0
|
||||
jnz norm_vec ;If not zero, jump ahead
|
||||
cmp CS:lo_time,0
|
||||
jnz norm_vec
|
||||
mov CS:tickstat,0 ;Otherwise, record timeout event
|
||||
C_call force_ti ;Force a timeout condition
|
||||
norm_vec: jmp dword ptr CS:clk_ptr ;Jump to original timer code
|
||||
tick endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,679 @@
|
|||
; =====> STIMER.ASM
|
||||
;***************************************
|
||||
;* TIPC Scheme '84 Things That Could *
|
||||
;* Have Been Done in C but Why Waste *
|
||||
;* Execution Time and Codespace? *
|
||||
;* *
|
||||
;* (C) Copyright 1984,1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: July 1985 *
|
||||
;* Last Modification: 8 October 1985 *
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
;Table of strange characters
|
||||
stranges db " ,'"
|
||||
db ';":()`'
|
||||
db 13,12,11,10,9,0
|
||||
|
||||
;Random number registers
|
||||
krala dw 22425
|
||||
kralb dw 30029 ;RANDOMIZE puts seed value here
|
||||
;Random number table
|
||||
kraltbl dw 4053,32361,7773,17385,11177,20413,27513,16501
|
||||
dw 5953,17673,20725,12247,28429,30861,16849,22375
|
||||
;Copy of random number registers and table.
|
||||
krala1 dw 22425
|
||||
kralb2 dw 30029
|
||||
kraltbl1 dw 4053,32361,7773,17385,11177,20413,27513,16501
|
||||
dw 5953,17673,20725,12247,28429,30861,16849,22375
|
||||
kral_len equ krala1-krala
|
||||
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;For space and performance reasons, some procedures have been written in the
|
||||
; following style: the arguments are popped off the stack, and the
|
||||
; procedure may end in an indirect JMP instead of a RET. In this source file,
|
||||
; the following are such procedures:
|
||||
; toblock, gvchars, blk2pbuf, putlong, thefix, ldlong, msubstr,
|
||||
; mcmpstr, ldreg, pt_flds4, pt_flds6, str2str, adj4bord
|
||||
|
||||
; Convert flonum to bignum
|
||||
; Calling sequence: flotobig(flo,bigbuf)
|
||||
; Where ---- flo: double-length flonum such that abs(flo)>=1
|
||||
; bigbuf: pointer to buffer for bignum formation
|
||||
fbargs struc
|
||||
dw ? ;Return address
|
||||
flo dw ?,?,?,? ;Flonum
|
||||
bigbuf dw ? ;Pointer to bignum buffer
|
||||
fbargs ends
|
||||
public flotobig
|
||||
flotobig proc near
|
||||
mov BX,SP
|
||||
lea SI,[BX].flo ;Fetch pointer to flonum
|
||||
mov DI,[BX].bigbuf ;Fetch buffer pointer
|
||||
inc DI ;Point DI to sign byte
|
||||
inc DI
|
||||
cld ;Direction forward
|
||||
mov AX,[BX+6].flo ;Fetch exponent word to CX
|
||||
mov CX,AX
|
||||
and AX,0fh ;Save mantissa part back
|
||||
or AL,10h
|
||||
mov [BX+6].flo,AX
|
||||
mov AL,AH ;Zero AL
|
||||
test CH,80h ;Negative flonum?
|
||||
jz ftb1 ;Jump if not
|
||||
inc AL ;Otherwise, set AL to 1
|
||||
ftb1: stosb ;Store sign byte
|
||||
mov BX,DI ;Save address of first word in BX
|
||||
mov AL,AH ;Zero AL again
|
||||
and CX,7ff0h ;Discard sign byte and mantissa
|
||||
sub CX,3ff0h ;Remove exponent bias
|
||||
shl CX,1
|
||||
;At this stage, CH+1==number of bytes for bignum, CL shows how much to
|
||||
; shift mantissa left (once per 20h)
|
||||
mov DX,CX ;Use DX to count the shifts
|
||||
xor DH,DH ;Set up shift count
|
||||
add DX,80h ;Account for placing leading 1 in high byte
|
||||
ftb2: shl word ptr[SI],1 ;Shift mantissa left
|
||||
rcl word ptr[SI+2],1
|
||||
rcl word ptr[SI+4],1
|
||||
rcl word ptr[SI+6],1
|
||||
sub DX,20h ;Repeat until done
|
||||
jnz ftb2
|
||||
mov CL,CH ;Set CX to number of bignum bytes
|
||||
xor CH,CH
|
||||
inc CX
|
||||
sub CX,8 ;Check for leading zeros
|
||||
js ftb3 ;Jump if not all the mantissa will be done
|
||||
jz ftb3 ;Jump if no trailing zeros exist
|
||||
rep stosb ;Else store as many zeros as necessary
|
||||
ftb3: sub SI,CX ;Point SI to eligible part of mantissa
|
||||
add CX,8 ;Set mantissa byte count
|
||||
rep movsb ;Copy flonum mantissa to bignum
|
||||
mov CX,DI ;Find number of bytes in bignum proper
|
||||
sub CX,BX
|
||||
shr CX,1 ;Find number of words
|
||||
jnc ftb4 ;If a whole number of words, do nothing
|
||||
mov byte ptr[DI],0 ;Otherwise, pad with a 0
|
||||
inc CX ;Adjust word count
|
||||
ftb4: mov [BX-3],CX ;Save size of bignum
|
||||
ret
|
||||
flotobig endp
|
||||
|
||||
; Find the size of a flonum
|
||||
; Calling sequence: flosiz(flo);
|
||||
; Where ---- flo: double-length flonum
|
||||
; Returns the number of bytes needed for a working flonum formed from
|
||||
; trunc(flonum)
|
||||
fsargs struc
|
||||
dw ? ;Return address
|
||||
fl dw ?,?,?,? ;Double-length flonum
|
||||
fsargs ends
|
||||
public flosiz
|
||||
flosiz proc near
|
||||
mov SI,SP
|
||||
mov AX,[SI+6].fl ;Fetch word containing exponent
|
||||
and AX,7ff0h ;Drop sign and mantissa
|
||||
sub AX,3ff0h ;Is abs(flo) < 1?
|
||||
jc small ;Jump if small
|
||||
mov AL,AH ;Otherwise, return number of bytes
|
||||
xor AH,AH
|
||||
shl AL,1
|
||||
add AL,5
|
||||
ret
|
||||
small: xor AX,AX ;Return 0 for smallness
|
||||
ret
|
||||
flosiz endp
|
||||
|
||||
; Move bytes from buffer to allocated Scheme block
|
||||
; Calling sequence: toblock(reg,offs,buf,q)
|
||||
; Where ---- reg: Scheme register pointing to block
|
||||
; offs: Offset into block to begin transfer
|
||||
; buf: Buffer pointer
|
||||
; q: Number of bytes to move
|
||||
;Stack elements in order of popping:
|
||||
; Return address, register, offset, buffer address, number of bytes
|
||||
public toblock
|
||||
toblock proc near
|
||||
pop DX ;Save return address in DX
|
||||
pop BX ;Get register address
|
||||
mov DI,[BX].C_disp ;Put 8088 address in ES:DI
|
||||
mov BX,[BX].C_page
|
||||
mov AX,ES
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
pop CX ;Get offset
|
||||
add DI,CX ;Add to DI
|
||||
pop SI ;Get source address (buffer ptr)
|
||||
pop CX ;Get number of bytes
|
||||
jcxz tbskip ;If no bytes, don't move
|
||||
cld ;Direction forward
|
||||
rep movsb ;Move bytes
|
||||
tbskip: mov ES,AX ;Restore ES
|
||||
jmp DX ;Return
|
||||
toblock endp
|
||||
|
||||
IFNDEF PROMEM
|
||||
; Give characters from a C string
|
||||
; Calling sequence: gvchars(str,len)
|
||||
; Where ---- str: C string address
|
||||
; len: Number of characters to give
|
||||
;Stack elements in order of popping:
|
||||
; Return address, string address, number of chars
|
||||
extrn givechar:near
|
||||
public gvchars
|
||||
gvchars proc near
|
||||
pop DI ;Get return address
|
||||
pop SI ;Get string address
|
||||
pop CX ;Get number of chars
|
||||
push DI ;Put return address back
|
||||
jcxz given ;If no chars, stop
|
||||
cld ;Direction forward
|
||||
gvlp: push CX ;Save count
|
||||
lodsb ;Fetch string character
|
||||
push SI ;Save pointer to next char
|
||||
push AX
|
||||
call givechar ;Give it
|
||||
inc SP ;Restore stack
|
||||
inc SP
|
||||
pop SI ;Restore address and count
|
||||
pop CX
|
||||
loop gvlp ;Give 'til done
|
||||
given: ret ;Return
|
||||
gvchars endp
|
||||
|
||||
; Move characters from block (symbol or string) to print buffer
|
||||
; Calling sequence: blk2pbuf(pg,ds,buf,len,ch,display)
|
||||
; Where ---- pg: logical page of the block
|
||||
; ds: block displacement
|
||||
; buf: address of print buffer
|
||||
; len: number of chars in the block
|
||||
; ch: character to escape (| for syms, " for strs)
|
||||
; display: whether to use escape characters
|
||||
; Returns the number 2n+s, where n is the number of characters in the
|
||||
; print buffer, and s=1 if strange chars were encountered, 0 otherwise.
|
||||
; Popping order: return address, pg, ds, buf, len, ch, display
|
||||
public blk2pbuf
|
||||
extrn hicases:byte
|
||||
blk2pbuf proc near
|
||||
pop DX ;Pop return address
|
||||
pop BX ;Pop page
|
||||
shl BX,1 ;Put segment of block in DS
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
pop SI ;Pop block displacement
|
||||
pop DI ;Pop print buffer
|
||||
pop CX ;Pop character count
|
||||
pop BX ;Pop must-be-escaped character
|
||||
pop AX ;Pop whether to use escapes
|
||||
mov BH,AL ;Save escape boolean in BX
|
||||
and BH,7fh ;Save bit in BH for strangeness
|
||||
push DX ;Push return address
|
||||
push ES ; Save caller's ES register
|
||||
mov DX,DI ;Save start address of print buffer in DX
|
||||
jcxz zstrng ;If len=0, mark strangeness
|
||||
cmp BL,'"' ;Are we looking at a string?
|
||||
jne b2plp ;Skip if not
|
||||
zstrng: or BH,80h ;Otherwise, mark as strange
|
||||
jcxz done ;If len=0, forget everything else
|
||||
b2plp: lodsb ;Fetch char from block
|
||||
test BH,7fh ;Are we displaying escape chars?
|
||||
jz storit ;Jump if not
|
||||
cmp AL,BL ;Does the char need escaping?
|
||||
je escit ;If needed, do so
|
||||
cmp AL,'\'
|
||||
jne storit ;If not, just store it
|
||||
escit: mov AH,AL ;Save char in AH
|
||||
mov AL,'\' ;Store escape character
|
||||
stosb
|
||||
mov AL,AH ;Restore char
|
||||
storit: stosb ;Store it
|
||||
test BH,80h ;Do we already know that atom's strange?
|
||||
jnz skptest ;If so, don't bother testing
|
||||
push SI ;Else save SI
|
||||
mov SI,offset DGROUP:hicases ;Point SI to table of upper cases
|
||||
xchg BX,SI
|
||||
mov AH,AL ;Save char in AH
|
||||
xlat ES:hicases ;Fetch upper-case equivalent
|
||||
xchg BX,SI ;Restore BX
|
||||
cmp AH,AL
|
||||
jne mrkstrng ;If chars different, mark as strange
|
||||
mov SI,offset stranges ;Point SI to strange-character string
|
||||
strnglp: lods byte ptr ES:[SI] ;Fetch strange char
|
||||
or AL,AL ;End of string?
|
||||
jz notstrng ;Jump if so
|
||||
cmp AH,AL ;Is AH strange?
|
||||
jne strnglp ;If not, try again
|
||||
mrkstrng: or BH,80h ;Mark strange bit
|
||||
notstrng: pop SI ;Restore SI
|
||||
skptest: loop b2plp ;Repeat until done
|
||||
done: push ES ;Restore DS
|
||||
pop DS
|
||||
pop ES ; Restore caller's ES register
|
||||
mov byte ptr[DI],0 ;Put null at end of string
|
||||
mov AX,DI ;Return 2*(# of chars in string)+strangeness
|
||||
sub AX,DX
|
||||
shl BH,1
|
||||
rcl AX,1
|
||||
ret ;Return
|
||||
blk2pbuf endp
|
||||
ENDIF
|
||||
|
||||
; Load bignum block with long integer
|
||||
; Calling sequence: putlong(reg,longi)
|
||||
; Where ----- reg: register pointing to a bignum block
|
||||
; longi: 32-bit integer to store
|
||||
; Popping order: return address, register address, low & high integer words
|
||||
public putlong
|
||||
putlong proc near
|
||||
pop DX ;Fetch return address
|
||||
pop DI ;Fetch register address
|
||||
mov BX,[DI].C_page ;Point ES:DI to bignum block
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov DI,[DI].C_disp
|
||||
add DI,3 ;Point ES:DI to block data area
|
||||
pop BX ;Put long integer in CX:BX
|
||||
pop CX
|
||||
xor AL,AL ;Sign byte - default positive
|
||||
test CH,80h ;Integer negative?
|
||||
jz poslong ;Jump if not
|
||||
inc AL ;Otherwise, set sign negative
|
||||
xor BX,-1 ;Negate long integer
|
||||
xor CX,-1
|
||||
add BX,1
|
||||
adc CX,0
|
||||
poslong: cld ;Direction forward
|
||||
stosb ;Store sign byte
|
||||
mov AX,BX ;Store least significant word
|
||||
stosw
|
||||
jcxz notlong ;If most signif. word=0, don't store it
|
||||
mov AX,CX
|
||||
stosw
|
||||
notlong: push DS ;Restore ES
|
||||
pop ES
|
||||
jmp DX ;Return
|
||||
putlong endp
|
||||
|
||||
|
||||
; Add word of zeros, if necessary, to bignum buffer
|
||||
; Calling sequence: thefix(buf)
|
||||
; Where ----- buf: address of bignum buffer
|
||||
; THEFIX is intended to alleviate a problem in the bignum division package.
|
||||
; Popping order: return address, buf
|
||||
public thefix
|
||||
thefix proc near
|
||||
pop DI ;Return address in DX
|
||||
pop SI ;Fetch bignum buffer address
|
||||
mov BX,[SI] ;Get bignum size in words
|
||||
inc BX ;Point BX+SI to last bignum byte
|
||||
shl BX,1
|
||||
test byte ptr[BX+SI],80h ;Is most signif. bit set?
|
||||
jz fixed ;If not, nothing to fix
|
||||
inc word ptr[SI] ;Otherwise, increase bignum size
|
||||
inc BX ;Add word of 0 to most significant end
|
||||
mov word ptr[BX+SI],0
|
||||
fixed: jmp DI ;Return
|
||||
thefix endp
|
||||
|
||||
|
||||
; Load a long integer value with a bignum
|
||||
; Calling sequence: ldlong(v, reg)
|
||||
; Where ----- v: pointer to a long integer
|
||||
; reg: register pointing to a bignum
|
||||
; Returns 0 if the load was successful, 1 otherwise
|
||||
; Popping order: return address, v, reg
|
||||
public ldlong
|
||||
ldlong proc near
|
||||
pop DX ;Pop return address
|
||||
pop DI ;Pop longint destination
|
||||
pop BX ;Pop register address
|
||||
push DS ;Save DS
|
||||
mov SI,[BX].C_disp ;Point DS:SI to bignum object
|
||||
mov BX,[BX].C_page
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
cld ;Direction forward
|
||||
inc SI ;Put bignum length in CX
|
||||
lodsw
|
||||
mov CX,AX
|
||||
lodsb ;Put bignum sign in BL
|
||||
mov BL,AL
|
||||
cmp CX,6 ;Check size
|
||||
je big6
|
||||
cmp CX,8
|
||||
je big8
|
||||
mov AX,1 ;If here, bignum wrong size: error
|
||||
pop DS ;Restore DS
|
||||
jmp DX ;Return
|
||||
big6: lodsw ;Put bignum in CX:AX
|
||||
xor CX,CX
|
||||
jmp short havenum
|
||||
big8: lodsw ;Put bignum in CX:AX
|
||||
mov CX,AX
|
||||
lodsw
|
||||
xchg CX,AX
|
||||
havenum: test BL,1 ;Was bignum negative?
|
||||
jz storenum ;No, skip
|
||||
xor CX,-1 ;Otherwise, negate
|
||||
xor AX,-1
|
||||
add AX,1
|
||||
adc CX,0
|
||||
storenum: stosw ;Store to long integer
|
||||
mov AX,CX
|
||||
stosw
|
||||
xor AX,AX ;All's well
|
||||
pop DS ;Restore DS
|
||||
jmp DX ;Return
|
||||
ldlong endp
|
||||
|
||||
|
||||
; Move string bytes from one part of PCS memory to another
|
||||
; Calling sequence: msubstr(to_reg, from_reg, start, end)
|
||||
; Where ----- to_reg: register pointing to destination string
|
||||
; from_reg: register pointing to source string
|
||||
; start: offset at which to start copying
|
||||
; end: byte after the last to be copied
|
||||
; Popping order: return address, from_reg, to_reg, start, end
|
||||
public msubstr
|
||||
msubstr proc near
|
||||
pop DX ;Pop return address (temporarily)
|
||||
pop DI ;Pop destination register address
|
||||
pop SI ;Pop source register address
|
||||
pop AX ;Pop start index
|
||||
pop CX ;Pop end index
|
||||
push DS ;Save caller's DS & ES
|
||||
push ES
|
||||
mov BX,[DI].C_page ;Point ES:DI to destination object
|
||||
mov DI,[DI].C_disp
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
add DI,BLK_OVHD ;Adjust DI past string overhead
|
||||
mov BX,[SI].C_page ;Point DS:SI to source object
|
||||
mov SI,[SI].C_disp
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
add SI,BLK_OVHD ;Adjust SI past string overhead
|
||||
add SI,AX ;Point SI to start of substring
|
||||
sub CX,AX ;Set number of bytes to move
|
||||
cld ;Direction forward
|
||||
rep movsb
|
||||
pop ES ;Restore caller's DS & ES
|
||||
pop DS
|
||||
jmp DX ;Return
|
||||
msubstr endp
|
||||
|
||||
; Compare two Scheme bignums or strings for equal?-ness
|
||||
; Calling sequence: mcmpstr(reg1,reg2)
|
||||
; Where ----- reg1,reg2: registers pointing to objects to be compared
|
||||
; Returns 1 if the objects are equal?, 0 otherwise
|
||||
public mcmpstr
|
||||
mcmpstr proc near
|
||||
pop DX ;Pop return address
|
||||
pop SI ;Pop register addresses
|
||||
pop DI
|
||||
push DS ;Save caller's DS and ES
|
||||
push ES
|
||||
mov BX,[DI].C_page ;Point ES:DI to second object
|
||||
mov DI,[DI].C_disp
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
mov BX,[SI].C_page ;Point DS:SI to the first object
|
||||
mov SI,[SI].C_disp
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
mov CX,[SI].str_len ;Fetch byte count from source's length
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge mcm_010
|
||||
add CX,BLK_OVHD+PTRSIZE
|
||||
mcm_010: xor AX,AX ;Default AX to FALSE
|
||||
cld ;Direction forward
|
||||
repe cmpsb ;Compare
|
||||
jne cmpskp ;If not equal, return FALSE
|
||||
inc AX ;Otherwise return TRUE
|
||||
cmpskp: pop ES ;Restore caller's ES and DS
|
||||
pop DS
|
||||
jmp DX ;Return
|
||||
mcmpstr endp
|
||||
|
||||
|
||||
; Load a register with a pointer from Scheme memory
|
||||
; Calling sequence: ldreg(reg,pg,ds)
|
||||
; Where ----- reg: register to be loaded
|
||||
; pg,ds: page and displacement of Scheme pointer
|
||||
; Popping order: return address, reg, pg, ds
|
||||
public ldreg
|
||||
ldreg proc near
|
||||
pop DX ;Pop return address
|
||||
pop DI ;Pop destination register
|
||||
pop BX ;Pop page and displacement
|
||||
pop SI
|
||||
mov CX,DS ;Save caller's DS
|
||||
shl BX,1 ;Point DS:SI to Scheme pointer
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
cld ;Direction forward
|
||||
lodsb ;Load register's page field
|
||||
xor AH,AH
|
||||
mov ES:[DI].C_page,AX
|
||||
lodsw ;Load displacement field
|
||||
mov ES:[DI].C_disp,AX
|
||||
mov DS,CX ;Restore caller's DS
|
||||
jmp DX ;Return
|
||||
ldreg endp
|
||||
|
||||
|
||||
; Generate pseudorandom numbers in the range 0-16,383
|
||||
;
|
||||
; Author: John C. Jensen (converted to assembly lang. by Mark Meyer)
|
||||
; Date Written: 9 January 1985
|
||||
; Last Modification: 9 July 1985
|
||||
;
|
||||
; Calling Sequence: krandom()
|
||||
;
|
||||
; Note: the following random number generator is due to Jaroslav
|
||||
; Kral. It was adapted to 16 bit words and proven both efficient
|
||||
; and statistically satisfactory by Overstreet and Nance of SMU.
|
||||
; See Karl's paper for initialization values for other word
|
||||
; lengths.
|
||||
;
|
||||
; -- Kral, Jaroslav. "A New Additive Pseudorandom Number
|
||||
; Generator for Extremely Short Word-Lengths," Information
|
||||
; Processing Letters, 1 (1972), 164-167 (erratum noted in 1
|
||||
; (1972), 216).
|
||||
;
|
||||
; -- Overstreet, C. and Nance, R.E., "A Random Number Generator
|
||||
; for Small Word-Length Computers," Proceedings of the ACM '73
|
||||
; Conference, p. 219-223.
|
||||
;
|
||||
public krandom
|
||||
krandom proc near
|
||||
mov AX,krala ;Put old KRALA in AX, old KRALB in BX
|
||||
mov BX,kralb
|
||||
mov CX,BX ;KRALC = KRALB
|
||||
add BX,AX ;KRALB = (KRALA+KRALB) mod 2^n
|
||||
and BH,3fh ; (Currently, n=14)
|
||||
mov kralb,BX
|
||||
mov BL,BH ;J = KRALB / 2^(n-4)
|
||||
shr BL,1
|
||||
and BX,01eh
|
||||
mov AX,[BX]+offset kraltbl ;KRALA = KRALTBL[J]
|
||||
mov krala,AX
|
||||
add AX,CX ;KRALTBL[J] = (KRALA+KRALC) mod 2^n
|
||||
and AH,3fh
|
||||
mov [BX]+offset kraltbl,AX
|
||||
ret ;Return KRALTBL[J]
|
||||
krandom endp
|
||||
|
||||
; RANDOMIZE - Reset the random number registers and table back to their
|
||||
; original values, then put the seed value into "kralb".
|
||||
; Calling sequence: randomize(seed) ;seed = normal C int
|
||||
public randomiz
|
||||
randz_args struc
|
||||
dw ? ;caller's ES
|
||||
dw ? ;caller's BP
|
||||
dw ? ;return address
|
||||
rseed dw ? ;argument 1 (seed)
|
||||
randz_args ends
|
||||
randomiz proc near
|
||||
push BP ;save caller's BP
|
||||
push ES ;save ES
|
||||
mov BP,SP ;establish local addressability
|
||||
mov AX,DS ;copy DS to ES
|
||||
mov ES,AX
|
||||
mov CX,kral_len/2 ;restore random state to its original state
|
||||
lea SI,krala1
|
||||
lea DI,krala
|
||||
rep movsw
|
||||
mov BX,[BP].rseed ;get seed
|
||||
cmp BX,0 ;is it zero?
|
||||
jnz randz_1 ;no, jump; use the seed directly
|
||||
mov AX,2C00h ;get the time from DOS
|
||||
int 21h
|
||||
push DX ;tempsave DX (seconds, hundredths)
|
||||
xor AX,AX
|
||||
mov AL,CH ;determine #sec-in-hours
|
||||
mov DX,3600
|
||||
mul DX
|
||||
mov BX,AX
|
||||
xor AX,AX
|
||||
mov AL,CL ;determine #sec-in-minutes
|
||||
mov DX,60
|
||||
mul DX
|
||||
add BX,AX ;#sec-in-hours + #sec-in-minutes
|
||||
pop DX ;restore seconds (and hundredths, but ignore it)
|
||||
xchg DH,DL
|
||||
mov DH,0
|
||||
add BX,DX ;add in seconds
|
||||
randz_1: mov kralb,BX ;set seed
|
||||
pop ES ;wrap up
|
||||
pop BP
|
||||
ret
|
||||
randomiz endp
|
||||
|
||||
|
||||
; Set the cdr field of a list cell
|
||||
; Calling sequence: asetcdr(creg, preg)
|
||||
; Where ---- creg: register pointing to cell
|
||||
; preg: register holding new pointer
|
||||
; Popping order: Return address, destination register, pointer register
|
||||
public asetcdr
|
||||
asetcdr proc near
|
||||
pop DX ;Pop return address
|
||||
pop DI ;Pop address of register
|
||||
mov CX,ES ;Save caller's ES
|
||||
mov BX,[DI].C_page ;Point ES:DI to list cell
|
||||
mov DI,[DI].C_disp
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
add DI,PTRSIZE ;Adjust for cdr field
|
||||
pop SI ;Pop address of pointer
|
||||
cld ;Direction forward
|
||||
mov AX,[SI].C_page ;Store into cdr field
|
||||
stosb
|
||||
mov AX,[SI].C_disp
|
||||
stosw
|
||||
mov ES,CX ;Restore ES
|
||||
jmp DX ;Return
|
||||
asetcdr endp
|
||||
|
||||
|
||||
; Get field values from a port object
|
||||
; Calling sequence: pt_flds4(reg, &ull, &ulc, &nl, &nc)
|
||||
; pt_flds6(reg, &cl, &cc, &ull, &ulc, &nl, &nc)
|
||||
; Where ----- reg: register pointing to port
|
||||
; cl: variable to receive CUR_LINE value
|
||||
; cc: ... CUR_COL value
|
||||
; ull: ... UL_LINE value
|
||||
; ulc: ... UL_COL value
|
||||
; nl: ... N_LINES value
|
||||
; nc: ... N_COLS value
|
||||
; Warning: This routine expects these six fields to be contiguous
|
||||
; Popping order: return address, reg, (&cl, &cc,) &ull, &ulc, &nl, &nc
|
||||
public pt_flds4,pt_flds6
|
||||
pt_flds proc near
|
||||
pt_flds6: mov CX,pt_cline ;Set CX to offset of first field
|
||||
jmp fldsmrg
|
||||
pt_flds4: mov CX,pt_ullin ;Set CX to offset of first field
|
||||
fldsmrg: pop DX ;Pop return address
|
||||
mov AX,DS ;Save caller's DS
|
||||
pop BX ;Pop register address
|
||||
mov SI,[BX].C_disp ;Point DS:SI to first field
|
||||
mov BX,[BX].C_page
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
add SI,CX
|
||||
cld ;Direction forward
|
||||
sub CX,pt_cline ;Set CX to number of fields to do
|
||||
shr CX,1 ; (6 - (1/2)(CX - pt_cline))
|
||||
neg CX
|
||||
add CX,6
|
||||
fldslp: pop DI ;Pop destination variable address
|
||||
movsw ;Transfer value
|
||||
loop fldslp ;Repeat until done
|
||||
mov DS,AX ;Restore DS
|
||||
jmp DX ;Return
|
||||
pt_flds endp
|
||||
|
||||
; Copy bytes from one C location to another
|
||||
; Calling sequence: str2str(dest_adr, src_adr, n)
|
||||
; Where ----- dest_adr: destination address
|
||||
; src_adr: source address
|
||||
; n: number of bytes to copy
|
||||
; Popping order: return address, dest_adr, src_adr, n
|
||||
public str2str
|
||||
str2str proc near
|
||||
pop DX ;Pop return address
|
||||
pop DI
|
||||
pop SI
|
||||
pop CX
|
||||
cld ;Direction forward
|
||||
rep movsb ;Copy bytes
|
||||
jmp DX ;Return
|
||||
str2str endp
|
||||
|
||||
; Adjust window region variables for presence of a border
|
||||
; Calling sequence: adj4bord(&ull, &nl, &ulc, &nc)
|
||||
; Where ----- ull: Upper-left-line variable
|
||||
; nl: Number-of-lines variable
|
||||
; ulc: Upper-left-column variable
|
||||
; nc: Number-of-columns variable
|
||||
; Popping order: return address, &ull, &nl, &ulc, &nc
|
||||
public adj4bord
|
||||
max_lines equ 25
|
||||
max_cols equ 80
|
||||
adj4bord proc near
|
||||
pop DX ;Pop return address
|
||||
mov BX,max_lines ;Expand HEIGHT of window region
|
||||
expand: pop SI ;Pop upper-left parameter
|
||||
pop DI ;Pop extent parameter
|
||||
mov AX,[SI] ;Get value of upper-left parm
|
||||
or AX,AX ;If zero,
|
||||
jz expand1 ; skip next two instructions
|
||||
dec word ptr[SI] ;Else, expand backward
|
||||
inc word ptr[DI]
|
||||
dec AX ;Adjust AX to match upper-left parm
|
||||
expand1: add AX,[DI] ;Find opposite edge
|
||||
cmp AX,BX ;If edge too far,
|
||||
jae expand2 ; skip next instruction
|
||||
inc word ptr[DI] ;Else, expand forward
|
||||
expand2: cmp BX,max_cols ;If we're finished,
|
||||
je adjex ; jump out
|
||||
mov BX,max_cols ;Else, expand WIDTH of window region
|
||||
jmp expand
|
||||
adjex: jmp DX ;Return
|
||||
adj4bord endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,802 @@
|
|||
; =====> SUTIL.ASM
|
||||
;***************************************
|
||||
;* PC Scheme Runtime Support *
|
||||
;* Misc Utilities *
|
||||
;* *
|
||||
;* (C) Copyright 1984.1985,1986 by *
|
||||
;* Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: April 1984 *
|
||||
;* Last Modification: 26 February 1986*
|
||||
;***************************************
|
||||
include scheme.equ
|
||||
include pcmake.equ
|
||||
|
||||
;* Modification History:
|
||||
;* 27 Jan 86 - Changed the code which looks for the TI Copyright notice
|
||||
;* (JCJ) (when determining machine type) to search two areas instead
|
||||
;* of just one. Now, checks are made at segment (paragraph)
|
||||
;* offsets FC00 and FE00.
|
||||
;*
|
||||
;* 25 Feb 86 - Added the routine "put_ptr" to combine the "put_byte/put_word"
|
||||
;* (JCJ) operations when a pointer is being stored into memory.
|
||||
;*
|
||||
;* 17 Feb 88 - Conditionally assemble XPCTYPE and PC_TYPE for Protected Memory
|
||||
;* (TC) Scheme. These routines can be found in PRO2REAL.ASM and
|
||||
;* REALIO.ASM for PROMEM
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
extrn _base:word
|
||||
data ends
|
||||
|
||||
|
||||
IFNDEF PROMEM
|
||||
|
||||
; See PRO2REAL.ASM for protected mode scheme
|
||||
|
||||
XGROUP group PROGX
|
||||
PROGX segment para public 'PROGX'
|
||||
assume CS:XGROUP,DS:DGROUP
|
||||
;************************************************************************
|
||||
;* Determine PC's Manufacturer *
|
||||
;* *
|
||||
;* Purpose: To determine whether or not we're running on a TIPC or *
|
||||
;* another brand and set the "PC_MAKE" variable accordingly. *
|
||||
;* Returns: PC_MAKE will contain 1 for TIPC or Business Pro in TI mode*
|
||||
;* FF for IBM-PC *
|
||||
;* FE for IBM-PC/XT *
|
||||
;* FD for IBM-PC/jr *
|
||||
;* FC for IBM-PC/AT or B-P in IBM mode *
|
||||
;* 0 for undeterminable *
|
||||
;************************************************************************
|
||||
public pc_type
|
||||
XPCTYPE proc far
|
||||
push ES ; save caller's ES register
|
||||
push DI
|
||||
mov AX,0FC00h ; move paragraph address of copyright
|
||||
pc_002: mov ES,AX ; notice into ES
|
||||
xor DI,DI ; Clear DI; 0 is lowest address in ROM @ES:
|
||||
xor BX,BX ; Flag for "PC_MAKE" variable
|
||||
mov CX,40h ; This'll be as far as I go...
|
||||
mov AL,'T' ; look for beginning of "Texas Instruments"
|
||||
cli ; Stop interrupts - bug in old 8088's
|
||||
again:
|
||||
repne scas byte ptr es:[di] ; SEARCH
|
||||
or CX,CX ; Reach my limit?
|
||||
jz short pc_005 ; quit if we've exhausted search
|
||||
cmp byte ptr ES:[di],'e' ; make sure this is it
|
||||
jne again ; use defaults if not found
|
||||
cmp byte ptr ES:[di]+1,'x' ; really make sure this is it
|
||||
jne again
|
||||
push DS
|
||||
mov DS,BX ; 0->DS for addressing low mem.
|
||||
inc BX ; BX==1 => TIPC
|
||||
mov AX,DS:word ptr [01A2h] ; If TIPC then what kind?
|
||||
pop DS ; get DS back
|
||||
add AL,AH ; checkout vector 68 bytes 2 & 3
|
||||
cmp AL,0F0h ; if AL==F0 then TIPC=Business Pro
|
||||
jne pc_010 ; jump if not a B-P
|
||||
in AL,068h ; Read from port
|
||||
push AX ; Save for later
|
||||
and AL,0FBh ; Enable CMOS
|
||||
out 068h,AL ; Write back out
|
||||
mov DX,8296h ; I/O address for B-P's mode byte
|
||||
in AL,DX ; TI or IBM Mode on the B-P?
|
||||
cmp AL,0 ; if not zero then B-P emulates a TIPC
|
||||
pop AX ; Restore original port value
|
||||
out 068h,AL ; and write back out
|
||||
jne pc_010 ; jump if TIPC else IBM machine code is
|
||||
; where it should be.
|
||||
jmp short pc_007
|
||||
pc_005:
|
||||
mov AX,ES
|
||||
cmp AH,0FEh ; test for segment offset FE00
|
||||
jae pc_007 ; two checks made? if so, jump
|
||||
add AH,2 ; go back and check segment offset
|
||||
jmp pc_002 ; FE00
|
||||
pc_007: mov AX,0F000h
|
||||
mov ES,AX
|
||||
mov al,byte ptr ES:0FFFEh ; IBM's machine code is @F000:FFFE
|
||||
cmp AL,IBMTYPE ; Is this suckah an IBM?
|
||||
jb pc_010 ; Jump if AL is below F0 (BX will be 0)
|
||||
mov BL,AL
|
||||
pc_010: sti ; Turn interrups back on
|
||||
mov PC_MAKE,BX ; set variable PC_MAKE
|
||||
pop DI
|
||||
pop ES ; restore caller's ES register
|
||||
ret ; return to caller
|
||||
XPCTYPE endp
|
||||
PROGX ends
|
||||
|
||||
; See PRO2REAL.ASM for above definition
|
||||
|
||||
ENDIF
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;For space and performance reasons, some procedures have been written in the
|
||||
; following style: the arguments are popped off the stack, and the
|
||||
; procedure ends in an indirect JMP instead of a RET. In this source file,
|
||||
; the following are such procedures:
|
||||
; zero_pag, zero_blk, get_byte, get_word, put_byte, put_word,
|
||||
; get_flo, put_flo, get_str, put_str, get_sym, put_sym,
|
||||
; make_ptr, alloc_fi, take_car, take_cdr
|
||||
|
||||
; Return Value of Stack Segment Register (SS:)
|
||||
;;; public _SS
|
||||
;;;_SS proc near
|
||||
;;; mov AX,SS
|
||||
;;; ret
|
||||
;;;_SS endp
|
||||
|
||||
;;;; Return Value of Extra Segment Register (ES:)
|
||||
;;; public _ES
|
||||
;;;_ES proc near
|
||||
;;; mov AX,ES
|
||||
;;; ret
|
||||
;;;_ES endp
|
||||
|
||||
;;;; Return Value of Code Segment Register (CS:)
|
||||
;;; public _CS
|
||||
;;;_CS proc near
|
||||
;;; mov AX,CS
|
||||
;;; ret
|
||||
;;;_CS endp
|
||||
|
||||
; Return Value of Data Segment Register (DS:)
|
||||
public _DS
|
||||
_DS proc near
|
||||
mov AX,DS
|
||||
ret
|
||||
_DS endp
|
||||
|
||||
; Zero a page in memory - Calling sequence: zero_page(page_no)
|
||||
public zero_pag
|
||||
zero_arg struc
|
||||
dw ? ; Return address
|
||||
zero_pg dw ? ; Page number
|
||||
zero_arg ends
|
||||
zero_pag proc near
|
||||
pop DX ;Pop return address
|
||||
pop BX ;Pop page number
|
||||
push ES ;Save ES
|
||||
sal BX,1
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,DGROUP:pagetabl+[BX]
|
||||
xor AX,AX
|
||||
xor DI,DI
|
||||
mov CX,psize+[BX]
|
||||
shr CX,1
|
||||
cld
|
||||
rep stosw
|
||||
pop ES ;Restore ES
|
||||
jmp DX
|
||||
zero_pag endp
|
||||
|
||||
;************************************************************************
|
||||
;* Zero a block of memory *
|
||||
;* *
|
||||
;* Purpose: To initialize a variable length block of memory to zero. *
|
||||
;* *
|
||||
;* Description: The block is zeroed using the 8088's "store string" *
|
||||
;* instruction using a repeat count. For *
|
||||
;* efficiency reasons, the zeroing is done by *
|
||||
;* words, with a fixup to account for blocks with *
|
||||
;* an odd number of bytes. *
|
||||
;* *
|
||||
;* Calling sequence: zero_blk(page_no, disp) *
|
||||
;* where page_no = page number (C's unshifted *
|
||||
;* page number) *
|
||||
;* disp = displacement of block within *
|
||||
;* the page *
|
||||
;************************************************************************
|
||||
public zero_blk
|
||||
zb_args struc
|
||||
dw ? ; Return address
|
||||
zb_page dw ? ; Page number
|
||||
zb_disp dw ? ; Displacement
|
||||
zb_args ends
|
||||
|
||||
zero_blk proc near
|
||||
pop SI ;Pop return address
|
||||
pop BX ; Pop the page number for the block
|
||||
shl BX,1 ; and adjust for use as index
|
||||
pop DI ; Pop the displacement of the block
|
||||
push ES ; save the caller's ES register
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,DGROUP:pagetabl+[BX] ; load page's paragraph address
|
||||
mov CX,ES:[DI].vec_len ; and the block's length
|
||||
add DI,BLK_OVHD ; and advance pointer past block header
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge zero_010
|
||||
add CX,PTRSIZE
|
||||
jmp zero_020
|
||||
zero_010: sub CX,BLK_OVHD ; subtract block overhead from the length
|
||||
zero_020: mov DX,CX ; copy the length in bytes, and
|
||||
and DX,1 ; isolate the least significant bit
|
||||
shr CX,1 ; convert number of bytes to number of words
|
||||
xor AX,AX ; load a value of zero into AX
|
||||
cld ; set forward direction
|
||||
rep stosw ; zero the block
|
||||
mov CX,DX ; copy the fixup byte count
|
||||
rep stosb ; zero the last byte, if odd number of bytes
|
||||
pop ES ; restore ES register
|
||||
jmp SI ; return to caller
|
||||
zero_blk endp
|
||||
|
||||
; Fetch/Store byte/word
|
||||
get_args struc ; Arguments Template
|
||||
dw ? ; return address
|
||||
get_page dw ? ; page number
|
||||
get_disp dw ? ; displacement into page
|
||||
get_val dw ? ; value (if a store operation)
|
||||
get_args ends
|
||||
|
||||
; Get a byte of data
|
||||
; Calling sequence: data = get_byte(page, disp)
|
||||
; where: page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
public get_byte
|
||||
get_byte proc near
|
||||
mov CX,ES ; save caller's ES in CX
|
||||
pop SI ; get return address
|
||||
pop BX ; get page argument
|
||||
shl BX,1 ; adjust it for segment lookup
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; get page segment
|
||||
pop BX ; get displacement
|
||||
mov AL,ES:[BX] ; get byte
|
||||
xor AH,AH ; and only a byte
|
||||
mov ES,CX ; restore ES
|
||||
jmp SI ; return
|
||||
get_byte endp
|
||||
|
||||
; Get a word of data
|
||||
; Calling sequence: data = get_word(page, disp)
|
||||
; where: page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
public get_word
|
||||
get_word proc near
|
||||
mov CX,ES ; save caller's ES in CX
|
||||
pop SI ; get return address
|
||||
pop BX ; get page argument
|
||||
shl BX,1 ; adjust it for segment lookup
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; get page segment
|
||||
pop BX ; get displacement
|
||||
mov AX,ES:[BX] ; get word
|
||||
mov ES,CX ; restore ES
|
||||
jmp SI ; return
|
||||
get_word endp
|
||||
|
||||
; Put a byte of data
|
||||
; Calling sequence: put_byte(page, disp, value)
|
||||
; where: page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
; value ---- value to be stored (low order 8 bits)
|
||||
public put_byte
|
||||
put_byte proc near
|
||||
mov CX,ES ; save caller's ES in CX
|
||||
pop SI ; get return address
|
||||
pop BX ; get page
|
||||
sal BX,1 ; double page number for use as index
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load page's paragraph address
|
||||
pop BX ; get displacement
|
||||
pop AX ; load byte to store
|
||||
mov byte ptr ES:[BX],AL ; store new data
|
||||
mov ES,CX ; restore segment register ES
|
||||
jmp SI ; return
|
||||
put_byte endp
|
||||
|
||||
; Put a word of data
|
||||
; Calling sequence: put_word(page, disp, value)
|
||||
; where: page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
; value ---- value to be stored (16 bits)
|
||||
public put_word
|
||||
put_word proc near
|
||||
mov CX,ES ; save caller's ES in CX
|
||||
pop SI ; get return address
|
||||
pop BX ; load the page number
|
||||
sal BX,1 ; double page number for use as index
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load page's paragraph address
|
||||
pop BX ; load displacement
|
||||
pop AX ; load word to store
|
||||
mov word ptr ES:[BX],AX ; store new data
|
||||
mov ES,CX ; restore segment register ES
|
||||
jmp SI ; return
|
||||
put_word endp
|
||||
|
||||
; Exchange a byte of data
|
||||
; Calling sequence: old_data = xch_byte(page, disp, value)
|
||||
; where: old_data - original data (overwritten)
|
||||
; page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
; value ---- value to be stored (low order 8 bits)
|
||||
; public xch_byte
|
||||
;xch_byte proc near
|
||||
; mov CX,ES ; save caller's ES in CX
|
||||
; pop SI ; get return address
|
||||
; pop BX ; get page
|
||||
; sal BX,1 ; double page number for use as index
|
||||
; mov ES,pagetabl+[BX] ; load page's paragraph address
|
||||
; pop BX ; get displacement
|
||||
; pop AX ; load byte to store
|
||||
; xchg AL,byte ptr ES:[BX] ; swap old and new data
|
||||
; xor AH,AH ; clear high order byte of AX
|
||||
; mov ES,CX ; restore segment register ES
|
||||
; jmp SI ; return
|
||||
;xch_byte endp
|
||||
|
||||
; Exchange a word of data
|
||||
; Calling sequence: old_data = xch_word(page, disp, value)
|
||||
; where: old_data - original data (overwritten)
|
||||
; page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
; value ---- value to be stored (16 bits)
|
||||
; public xch_word
|
||||
;xch_word proc near
|
||||
; mov CX,ES ; save caller's ES in CX
|
||||
; pop SI ; get return address
|
||||
; pop BX ; load the page number
|
||||
; sal BX,1 ; double page number for use as index
|
||||
; mov ES,pagetabl+[BX] ; load page's paragraph address
|
||||
; pop BX ; load displacement
|
||||
; pop AX ; load word to store
|
||||
; xchg AX,word ptr ES:[BX] ; swap old and new data
|
||||
; mov ES,CX ; restore segment register ES
|
||||
; jmp SI ; return
|
||||
;xch_word endp
|
||||
|
||||
; Put a pointer
|
||||
; Calling sequence: put_word(page, disp, pg_value, ds_value)
|
||||
; where: old_data - original data (overwritten)
|
||||
; page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
; pg_value ---- value of page number to store (16 bits)
|
||||
; ds_value ---- value of displacement to store (16 bits)
|
||||
public put_ptr
|
||||
put_ptr proc near
|
||||
mov CX,ES ; save caller's ES in CX
|
||||
pop SI ; get return address
|
||||
pop BX ; load the page number
|
||||
sal BX,1 ; double page number for use as index
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load page's paragraph address
|
||||
pop BX ; load displacement
|
||||
pop AX ; load page number value to store
|
||||
mov byte ptr ES:[BX],AL ; store page number
|
||||
pop AX ; load displacement value to store
|
||||
mov word ptr ES:[BX]+1,AX ; store page number
|
||||
mov ES,CX ; restore segment register ES
|
||||
jmp SI ; return
|
||||
put_ptr endp
|
||||
|
||||
; Fetch/Store Flonum
|
||||
getf_arg struc ; Arguments Template
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
getf_pag dw ? ; page number
|
||||
getf_dis dw ? ; displacement into page
|
||||
getf_val dw ? ; value (if a store operation)
|
||||
getf_arg ends
|
||||
|
||||
; Get a floating point value
|
||||
; Calling sequence: fdata = get_flo(page, disp)
|
||||
; where: page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
public get_flo
|
||||
get_flo proc near
|
||||
pop DI ;Pop return address
|
||||
pop BX ; load the page number
|
||||
sal BX,1 ; double page number for use as index
|
||||
pop SI ; load displacement
|
||||
inc SI ; and advance page flonum's tag
|
||||
push DS ; save the caller's DS segment register
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX] ; load page's paragraph address
|
||||
cld ;Direction forward
|
||||
lodsw ;Put the flonum in AX:BX:CX:DX
|
||||
mov DX,AX
|
||||
lodsw
|
||||
mov CX,AX
|
||||
lodsw
|
||||
mov BX,AX
|
||||
lodsw
|
||||
pop DS ; restore caller's DS segment register
|
||||
jmp DI ; return
|
||||
get_flo endp
|
||||
|
||||
; Put a flonum value into Scheme's memory
|
||||
; Calling sequence: put_flo(page, disp, value)
|
||||
; where: page ----- page number
|
||||
; disp ----- (byte) displacement within page
|
||||
; value ---- flonum value to be stored (4 words)
|
||||
public put_flo
|
||||
put_flo proc near
|
||||
pop DX ;Pop return address
|
||||
pop BX ; load the page number
|
||||
sal BX,1 ; double page number for use as index
|
||||
pop DI ; load displacement
|
||||
inc DI ; and advance offset past flonum's tag
|
||||
mov SI,SP ;SP points to flonum - point SI to it too
|
||||
push ES ; save the caller's ES segment register
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load page's paragraph address
|
||||
mov CX,FLOSIZE/WORDINCR ; load number of words to store
|
||||
cld ; clear direction flag
|
||||
rep movsw ; move the words of the flonum
|
||||
pop ES ; restore the ES segment register
|
||||
jmp DX ; return to caller
|
||||
put_flo endp
|
||||
|
||||
; Transfer string to/from Scheme's memory
|
||||
s_args struc
|
||||
dw ? ; Caller's BP
|
||||
dw ? ; Return address
|
||||
sptr dw ? ; Pointer to string in C's memory
|
||||
spage dw ? ; page number
|
||||
sdisp dw ? ; displacement in page
|
||||
lpage dw ? ; link field page number (for symbols)
|
||||
ldisp dw ? ; link field displacement (for symbols)
|
||||
hash_key dw ? ; hash value (for symbols)
|
||||
s_args ends
|
||||
|
||||
public get_str,get_sym
|
||||
get_str proc near
|
||||
pop DX ;Pop return address
|
||||
pop DI ; Fetch destination string's displacement
|
||||
pop BX ; Fetch source page number
|
||||
shl BX,1 ; Adjust page number for use as index
|
||||
pop SI ; Fetch source string's displacement
|
||||
push DS ;Save caller's DS
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX] ; Get source page's paragraph address
|
||||
mov CX,[SI].vec_len ; Fetch length of string/symbol
|
||||
add SI,offset vec_data ; Adjust for string header
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge get_010
|
||||
add CX,PTRSIZE
|
||||
jmp get_mrg
|
||||
get_010: sub CX,offset vec_data ; Adjust length for string header
|
||||
get_mrg: cld ; clear string direction
|
||||
rep movsb ; move 'em out
|
||||
pop DS ; Restore DS segment register
|
||||
jmp DX ;Return
|
||||
get_str endp
|
||||
|
||||
get_sym proc near
|
||||
pop DX ;Pop return address
|
||||
pop DI ; Fetch destination string's displacement
|
||||
pop BX ; Fetch source page number
|
||||
shl BX,1 ; Adjust page number for use as index
|
||||
pop SI ; Fetch source string's displacement
|
||||
push DS ;Save caller's DS
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX] ; Get source page's paragraph address
|
||||
mov CX,[SI].sym_len ; Fetch length of string/symbol
|
||||
add SI,offset sym_data ; Adjust offset for symbol header
|
||||
sub CX,offset sym_data ; Adjust length for symbol header
|
||||
jmp get_mrg ;Get pname bytes
|
||||
get_sym endp
|
||||
|
||||
public put_str,put_sym
|
||||
put_str proc near
|
||||
pop DX ;Pop return address
|
||||
pop SI ; Load source string offset
|
||||
pop BX ; Load destination page number,
|
||||
pop DI ; and displacement
|
||||
shl BX,1 ; Adjust page number for use as index
|
||||
push ES ; Save caller's ES segment register
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; Load destination page paragraph address
|
||||
mov CX,ES:[DI].vec_len ; Load string length
|
||||
add DI,offset vec_data ; Adjust pointer for string header
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge put_010
|
||||
add CX,PTRSIZE ;;; get the right string length
|
||||
jmp putmrg
|
||||
put_010: sub CX,offset vec_data ; Adjust length for string header
|
||||
putmrg: cld ; Clear direction flag
|
||||
rep movsb ; Move 'em in
|
||||
pop ES ; Restore caller's ES
|
||||
jmp DX ; Return
|
||||
put_str endp
|
||||
|
||||
put_sym proc near
|
||||
pop DX ;Pop return address
|
||||
pop SI ; Load source string offset
|
||||
pop BX ; Load destination page number,
|
||||
pop DI ; and displacement
|
||||
shl BX,1 ; Adjust page number for use as index
|
||||
mov CX,ES ;Save caller's ES in CX
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; Load destination page paragraph address
|
||||
pop AX ; Load link field page number and
|
||||
mov ES:[DI].sym_page,AL ; and move into symbol structure
|
||||
pop ES:[DI].sym_disp ; Store link field displacement
|
||||
pop AX ; move hash value into symbol data object
|
||||
mov ES:[DI].sym_hkey,AL
|
||||
push CX ;Now move caller's ES to stack
|
||||
mov CX,ES:[DI].sym_len ; Load string length
|
||||
add DI,offset sym_data ; Adjust displacement for symbol header
|
||||
sub CX,offset sym_data ; Adjust length for symbol header
|
||||
jmp putmrg ; Move 'em in
|
||||
put_sym endp
|
||||
|
||||
; Convert page, displacement values to a long integer
|
||||
public make_ptr
|
||||
make_args struc
|
||||
dw ? ; return address
|
||||
mak_page dw ? ; page number
|
||||
mak_disp dw ? ; pointer displacement
|
||||
make_args ends
|
||||
|
||||
make_ptr proc near
|
||||
pop DI
|
||||
pop AX
|
||||
adjpage AX
|
||||
pop BX
|
||||
jmp DI
|
||||
make_ptr endp
|
||||
|
||||
; Allocate a cell for a fixnum (actually, return an immediate value)
|
||||
; Calling sequence: alloc_fixnum(®, value)
|
||||
a_fix_arg struc
|
||||
dw ? ; Return address
|
||||
a_reg dw ? ; Address of register to hold pointer
|
||||
a_val dw ? ; Fixnum value
|
||||
a_fix_arg ends
|
||||
|
||||
public alloc_fi
|
||||
alloc_fi proc near
|
||||
pop DI ;Pop return address
|
||||
pop SI ; Pop address of return register
|
||||
pop DX ; Pop fixnum value
|
||||
sal DX,1 ; Shift out high order bit
|
||||
jo a_fix_ov
|
||||
a_fix_ov: ; Ignore overflow for now (create a bignum later)
|
||||
shr DX,1 ; Position 15 bit quantity
|
||||
mov [SI].C_disp,DX ; Store immediate value into register
|
||||
mov [SI].C_page,SPECFIX*2 ; Store immediate tag
|
||||
jmp DI ;Return
|
||||
alloc_fi endp
|
||||
|
||||
;************************************************************************
|
||||
;* Copy Variable Length Data Object *
|
||||
;* *
|
||||
;* Purpose: To create a copy of a variable length Scheme data object. *
|
||||
;* *
|
||||
;* Calling Sequence: copy_blk(&dest, &src) *
|
||||
;* where &dest - address of VM register into which *
|
||||
;* pointer to new copy is to be *
|
||||
;* placed *
|
||||
;* &src - address of VM register containing *
|
||||
;* block to be copied *
|
||||
;************************************************************************
|
||||
cpy_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; return address
|
||||
cpy_dest dw ? ; address of destination register
|
||||
cpy_src dw ? ; address of source register
|
||||
cpy_args ends
|
||||
|
||||
public copy_blk
|
||||
copy_blk proc near
|
||||
push ES ; save caller's ES
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
|
||||
; allocate new block
|
||||
mov SI,[BP].cpy_src ; load address of source register
|
||||
mov BX,[SI].C_page ; load pointer to object to be copied
|
||||
mov DI,[SI].C_disp
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
|
||||
mov AX,ES:[DI].vec_len ; load length of object
|
||||
cmp AX,0 ;;; check for small string
|
||||
jge copy_010
|
||||
add AX,PTRSIZE ;;; adjust for small string
|
||||
jmp copy_011
|
||||
copy_010: sub AX,BLK_OVHD ; adjust size for block header
|
||||
copy_011: push AX ; push length of "data" in block
|
||||
|
||||
xor AX,AX ; load type field from source block
|
||||
mov AL,ES:[DI].vec_type
|
||||
push AX
|
||||
|
||||
push [BP].cpy_dest ; push address of destination register
|
||||
mov AX,DS ; make ES point to the current data
|
||||
mov ES,AX ; segment
|
||||
C_call alloc_bl ; allocate new block
|
||||
mov SP,BP ; drop arguments off stack
|
||||
|
||||
; copy contents of source block into newly created block
|
||||
mov BX,[BP].cpy_dest ; make ES:[DI] point to newly created
|
||||
mov DI,[BX].C_disp ; block
|
||||
mov BX,[BX].C_page
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
|
||||
mov BX,[BP].cpy_src ; make DS:[SI] point to source block
|
||||
mov SI,[BX].C_disp
|
||||
mov BX,[BX].C_page
|
||||
push DS
|
||||
LoadPage DS,BX
|
||||
;;; mov DS,pagetabl+[BX]
|
||||
|
||||
mov CX,[SI].vec_len ; load length of source block
|
||||
cmp CX,0 ;;; check for small string
|
||||
jge copy_020
|
||||
add CX,PTRSIZE
|
||||
jmp copy_021
|
||||
copy_020: sub CX,BLK_OVHD ; and subtract off size of block header
|
||||
copy_021: mov DX,CX ; copy length (in bytes) into DX
|
||||
and DX,1 ; and isolate the lsb
|
||||
shr CX,1 ; convert size from bytes to words
|
||||
|
||||
add SI,BLK_OVHD ; advance source/destination pointers
|
||||
add DI,BLK_OVHD ; past block header
|
||||
rep movsw ; move contents of source to destination
|
||||
mov CX,DX ; copy fixup (in case odd number of bytes)
|
||||
rep movsb ; copy odd byte, if necessary
|
||||
pop DS ; restore DS
|
||||
|
||||
; return to calling procedure
|
||||
pop BP ; restore caller's BP
|
||||
pop ES ; restore caller's ES
|
||||
ret ; return
|
||||
copy_blk endp
|
||||
|
||||
;;;; Make sure we haven't overflowed C's runtime stack
|
||||
;;; public chk_stk
|
||||
;;;chk_stk proc near
|
||||
;;; mov AX,SP
|
||||
;;; cmp AX,_base
|
||||
;;; ja chk_ret
|
||||
;;; C_call gc_on
|
||||
;;; C_call exit
|
||||
;;;chk_ret: ret
|
||||
;;;chk_stk endp
|
||||
|
||||
;************************************************************************
|
||||
;* C callable Routine to Take car/cdr of a List *
|
||||
;************************************************************************
|
||||
take_arg struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
take_reg dw ? ; argument register address
|
||||
take_arg ends
|
||||
|
||||
public take_car
|
||||
take_car proc near
|
||||
pop DX ;Pop return address
|
||||
pop SI ; load argument register address
|
||||
mov BX,[SI].C_page ; load list's page number
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; it is a list, isn't it?
|
||||
jne take_err ; if not a list, error (jump)
|
||||
mov CX,ES ; save caller's ES
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load list's page's paragraph address
|
||||
mov BX,[SI].C_disp ; load list's offset
|
||||
mov AL,ES:[BX].car_page ; copy car field of list cell
|
||||
mov BX,ES:[BX].car
|
||||
jmp short tkmrg
|
||||
; ***error-- argument register doesn't contain list-- return nil***
|
||||
take_err: mov [SI].C_page,NIL_PAGE*2
|
||||
mov [SI].C_disp,NIL_DISP
|
||||
jmp DX ; return
|
||||
take_car endp
|
||||
|
||||
public take_cdr
|
||||
take_cdr proc near
|
||||
pop DX ;Pop return address
|
||||
pop SI ; load argument register address
|
||||
mov BX,[SI].C_page ; load list's page number
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; it is a list, isn't it?
|
||||
jne take_err ; if not a list, error (jump)
|
||||
mov CX,ES ; save caller's ES
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load list's page's paragraph address
|
||||
mov BX,[SI].C_disp ; load list's offset
|
||||
mov AL,ES:[BX].cdr_page ; Get cdr field of list cell
|
||||
mov BX,ES:[BX].cdr
|
||||
tkmrg: mov byte ptr [SI].C_page,AL ; Copy into argument register
|
||||
mov [SI].C_disp,BX
|
||||
mov ES,CX ; restore caller's ES
|
||||
jmp DX ; return to caller
|
||||
take_cdr endp
|
||||
|
||||
|
||||
IFNDEF PROMEM
|
||||
|
||||
; See PRO2REAL.ASM for protected mode scheme
|
||||
|
||||
public pc_type
|
||||
pc_type proc near
|
||||
push BP
|
||||
call XPCTYPE ; XPCTYPE is located at beginning of this
|
||||
; program in XPROG, it determines PC type
|
||||
pop BP
|
||||
ret
|
||||
pc_type endp
|
||||
|
||||
public pcinit
|
||||
extrn XPCINIT:FAR
|
||||
pcinit proc near
|
||||
push BP
|
||||
call XGROUP:XPCINIT ; XPCINIT is in GRAPHCMD.ASM - in XPROG
|
||||
; it does special initialization per PC type
|
||||
; also, it is called from main()
|
||||
pop BP
|
||||
ret
|
||||
pcinit endp
|
||||
|
||||
; See PRO2REAL.ASM for above definitions
|
||||
|
||||
ENDIF
|
||||
|
||||
;************************************************************************
|
||||
;* Symbol Hashing Routine *
|
||||
;* *
|
||||
;* Calling Seguence: hash_value = hash(symbol, len); *
|
||||
;************************************************************************
|
||||
public hash
|
||||
hash proc near
|
||||
pop DI ; unload return address
|
||||
pop SI ; fetch symbol "string" pointer
|
||||
pop CX ; fetch length
|
||||
xor BX,BX ; zero accumulator
|
||||
xor AH,AH
|
||||
hash_1: lodsb ; fetch next character in symbol name
|
||||
add BX,AX ; sum them up
|
||||
loop hash_1 ; iterate 'til symbol used up
|
||||
mov AX,BX ; copy sum of chars to AX
|
||||
xor DX,DX
|
||||
mov BX,HT_SIZE ; load divisor with hash table size
|
||||
div BX ; divide sum
|
||||
mov AX,DX
|
||||
jmp DI ; return to caller
|
||||
hash endp
|
||||
|
||||
;************************************************************************
|
||||
;* Symbol Equality Routine *
|
||||
;* *
|
||||
;* Calling Sequence: equal? = sym_eq(page, disp, symbol, len); *
|
||||
;************************************************************************
|
||||
public sym_eq
|
||||
sym_eq proc near
|
||||
pop DX ; unload return address
|
||||
pop BX ; fetch page number
|
||||
shl BX,1 ; and adjust for word indexing
|
||||
pop DI ; fetch displacement
|
||||
pop SI ; fetch pointer to symbol name
|
||||
pop CX ; fetch length
|
||||
mov AX,ES ; save value of ES
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; laod symbol page's paragraph address
|
||||
mov BX,ES:[DI].sym_len ; fetch length of symbol
|
||||
sub BX,offset sym_data ; and compute character count
|
||||
cmp CX,BX ; length of symbol match?
|
||||
jne not_eq ; if not same length, jump
|
||||
add DI,offset sym_data ; advance symbol pointer to print name
|
||||
repe cmpsb ; compare symbol to name
|
||||
jne not_eq ; symbols the same? if not, jump
|
||||
mov ES,AX ; restore caller's ES register
|
||||
jmp DX ; return (non-zero value in AX => true)
|
||||
not_eq: mov ES,AX ; restore caller's ES register
|
||||
xor AX,AX ; zero AX (return false value)
|
||||
jmp DX ; return
|
||||
sym_eq endp
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,958 @@
|
|||
; =====> SVARS.ASM
|
||||
;****************************************
|
||||
;* TIPC Scheme '84 Runtime Support *
|
||||
;* Interpreter -- Variable Operations *
|
||||
;* *
|
||||
;* (C) Copyright 1984, 1985, 1988 *
|
||||
;* Texas Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 24 July 1984 *
|
||||
;* Modification History: *
|
||||
;* ?? 10/22/85 - ?? *
|
||||
;* rb 2/ 5/88 - MEMV, ASSV use EQV's *
|
||||
;* definition of number equality *
|
||||
;* (which is "=", *not* "equal"). *
|
||||
;* *
|
||||
;****************************************
|
||||
|
||||
include scheme.equ
|
||||
include sinterp.mac
|
||||
|
||||
include sinterp.arg
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
m_fluid db "LD-FLUID",0
|
||||
m_setfl db "SET-FLUID!",0
|
||||
m_set_gl db "SET!-GLOBAL",0
|
||||
m_fl_p db "FLUID-BOUND?",0
|
||||
m_ve_al db "MAKE-VECTOR",0
|
||||
m_vec_s db "VECTOR-SIZE",0
|
||||
m_vecf db "VECTOR-FILL!",0
|
||||
m_mkvt_a dw m_ve_al ; address of "MAKE-VECTOR"
|
||||
m_one dw 1 ; a constant "one" (1)
|
||||
m_three dw 3 ; a constant "three" (3)
|
||||
m_toobig dw VECTOR_SIZE_LIMIT_ERROR ; numeric error code
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
var_int proc near
|
||||
|
||||
; Entry points defined in "sinterp.asm"
|
||||
extrn next:near ; Top of interpreter
|
||||
extrn next_PC:near ; Reload ES,SI at top of interpreter
|
||||
extrn next_SP:near ; mov SP,BP before next_PC
|
||||
extrn src_err:near ; "source operand error" message display
|
||||
extrn sch_err:near ; Link to Scheme debugger
|
||||
|
||||
;************************************************************************
|
||||
;* Macro support for global/fluid variable lookup *
|
||||
;************************************************************************
|
||||
load macro environ,err_msg,reg_p
|
||||
local x,y
|
||||
lods word ptr ES:[SI] ; load dest reg, constant number
|
||||
save <SI> ; save current location pointer
|
||||
mov BL,AL ; copy destination register number
|
||||
mov DI,BX ; into TIPC register DI
|
||||
mov BL,AH ; isolate constant number
|
||||
IFIDN <reg_p>,<REG>
|
||||
mov SI,reg0_pag+[BX] ; load page number from symbol operand reg
|
||||
mov AX,reg0_dis+[BX] ; likewise for the displacement
|
||||
ELSE
|
||||
mov AX,BX ; BX <- constant number * 3
|
||||
shl AX,1
|
||||
add BX,AX
|
||||
add BX,CB_dis ; add offset for start of code block
|
||||
xor AX,AX
|
||||
mov AL,ES:[BX].cod_cpag ; load symbol's page number
|
||||
mov SI,AX
|
||||
mov AX,ES:[BX].cod_cdis ; load symbol's displacement
|
||||
ENDIF
|
||||
cmp byte ptr ptype+[SI],SYMTYPE*2 ; reg hold a symbol pointer?
|
||||
jne y ; if not, jump to error handler
|
||||
push DI ; save register number
|
||||
mov DX,SI ; copy symbol's page number into DX
|
||||
mov DI,environ&_pag ; load fluid environment pointer
|
||||
mov SI,environ&_dis
|
||||
;;; LoadPage ES,DI
|
||||
;;; mov ES,pagetabl+[DI] ; load paragraph address for env. header
|
||||
mov BX,DI ; BX <= page number
|
||||
call lookup ; search the environment for symbol
|
||||
cmp BX,0 ; symbol found?
|
||||
pop BX ; restore register number
|
||||
je x ; if symbol not found, jump
|
||||
mov AX,ES:[DI].cdr ; load symbol's value pointer
|
||||
mov reg0_dis+[BX],AX ; and store into register
|
||||
mov AL,ES:[DI].cdr_page
|
||||
mov byte ptr reg0_pag+[BX],AL
|
||||
jmp next_PC
|
||||
; symbol not found-- return '***unbound***
|
||||
x: mov CX,offset environ&_reg ; load address of environment reg
|
||||
corrpage DX ; adjust page number for call to C routine
|
||||
add BX,offset reg0 ; compute address of destintatin register
|
||||
pushm <BX,CX,AX,DX> ; push page, displacement, env, dest reg
|
||||
C_call sym_unde,,Load_ES ; call: symbol_undefined(pg,ds,env,dest)
|
||||
;***x: mov reg0_dis+[BX],UN_DISP
|
||||
;*** mov byte ptr reg0_pag+[BX],UN_PAGE*2
|
||||
restore <SI> ; load next instruction's offset and
|
||||
sub SI,3 ; back up PC to retry fluid load
|
||||
jmp sch_err ; Link to Scheme debugger
|
||||
; error-- register doesn't contain a symbol
|
||||
y: lea BX,err_msg
|
||||
jmp src_err ; display error message
|
||||
endm
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Fluid lookup FLUID dest,const *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for fluid variable lookup *
|
||||
;************************************************************************
|
||||
public ld_fluid
|
||||
ld_fluid: load FNV,m_fluid,CONST
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Fluid lookup-register operand FLUID-R dest,sym *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for fluid variable lookup *
|
||||
;************************************************************************
|
||||
public ld_fl_r
|
||||
ld_fl_r: load FNV,m_fluid,REG
|
||||
|
||||
purge load
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* set-fluid! ST-FLUID src,const *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for fluid assignment. *
|
||||
;************************************************************************
|
||||
public st_fluid
|
||||
st_fluid: lods word ptr ES:[SI] ; load source reg and constant number
|
||||
save <SI> ; save current value of location pointer
|
||||
push AX ; save symbol/value register numbers
|
||||
mov BL,AH
|
||||
mov AX,BX ; BX <- constant number * 3
|
||||
shl AX,1
|
||||
add BX,AX
|
||||
add BX,CB_dis ; add in starting offset of code block
|
||||
xor AX,AX
|
||||
mov AL,ES:[BX].cod_cpag ; load pointer to search symbol
|
||||
mov DI,AX
|
||||
cmp byte ptr ptype+[DI],SYMTYPE*2 ; really a symbol?
|
||||
jne setfl_er ; if not, jump
|
||||
mov DX,DI ; copy symbol's page number
|
||||
mov AX,ES:[BX].cod_cdis ; load symbol's displacement
|
||||
mov DI,FNV_pag ; load pointer to fluid environment
|
||||
mov SI,FNV_dis
|
||||
;;; LoadPage ES,DI
|
||||
;;; mov ES,pagetabl+[DI]
|
||||
mov BX,DI ; Page number
|
||||
call lookup ; search fluid environment for symbol
|
||||
cmp BX,0 ; symbol found in fluid environment?
|
||||
je setfl_nf ; if not, error (jump)
|
||||
pop AX ; restore operands
|
||||
mov BL,AL ; copy source register number
|
||||
mov AL,byte ptr reg0_pag+[BX] ; set cdr of fluid var entry
|
||||
mov ES:[DI].cdr_page,AL ; to value in register
|
||||
mov AX,reg0_dis+[BX]
|
||||
mov ES:[DI].cdr,AX
|
||||
jmp next_PC ; return to interpreter
|
||||
; error-- symbol register doesn't contain a symbol pointer
|
||||
setfl_er: mov BX,offset m_setfl ; load error message text
|
||||
jmp src_err ; jump to "source error" routine
|
||||
; error-- symbol not fluidly bound
|
||||
setfl_nf: pop CX ; restore instruction's operands
|
||||
xor CH,CH ; clear high order byte (constant number)
|
||||
add CX,offset reg0 ; compute address of source register
|
||||
corrpage DX ; convert page number to C's notation
|
||||
pushm <CX,AX,DX> ; push arguments for error call
|
||||
C_call not_flui,,Load_ES ; call error routine
|
||||
restore <SI> ; back up location pointer to retry
|
||||
sub SI,3 ; the set-fluid! operation
|
||||
jmp sch_err ; link to Scheme debugger
|
||||
|
||||
; fluid-bound? FLUID? reg
|
||||
public fluid_p
|
||||
fluid_p: lods byte ptr ES:[SI] ; load the register number for test
|
||||
save <SI> ; save the current location pointer
|
||||
mov BX,AX ; copy register number of symbol
|
||||
mov AX,reg0_dis+[BX]
|
||||
mov DX,reg0_pag+[BX]
|
||||
mov DI,DX
|
||||
cmp byte ptr ptype+[DI],SYMTYPE*2 ; symbol pointer?
|
||||
jne fl_p_er ; if not, error (jump)
|
||||
mov DI,FNV_pag
|
||||
mov SI,FNV_dis
|
||||
;;; LoadPage ES,DI
|
||||
;;; mov ES,pagetabl+[DI]
|
||||
push BX
|
||||
mov BX,DI ; Page number
|
||||
call lookup
|
||||
cmp BX,0
|
||||
pop BX
|
||||
je fl_p_nf
|
||||
; symbol is fluidly bound-- return 't
|
||||
mov AL,T_PAGE*2
|
||||
mov byte ptr reg0_pag+[BX],AL
|
||||
mov AX,T_DISP
|
||||
mov reg0_dis+[BX],AX
|
||||
jmp next_PC
|
||||
; symbol not in fluid environment-- return 'nil
|
||||
fl_p_nf: xor AX,AX
|
||||
mov byte ptr reg0_pag+[BX],AL
|
||||
mov reg0_dis+[BX],AX
|
||||
jmp next_PC
|
||||
; error-- operand of (fluid-bound? obj) is not a symbol
|
||||
fl_p_er: lea BX,m_fl_p
|
||||
jmp src_err ; display error message
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* Bind fluid variable BIND-FL const,src *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for binding (creating and defining) *
|
||||
;* fluid variables *
|
||||
;* *
|
||||
;* Note: At entry to this routine, ES is set to point to the beginning *
|
||||
;* of the page containing the current code block. *
|
||||
;************************************************************************
|
||||
public bind_fl
|
||||
bind_fl: lods word ptr ES:[SI] ; load src register, constant number
|
||||
mov BL,AH ; copy the source register number
|
||||
lea DI,reg0+[BX] ; and compute its address
|
||||
; tmp_reg <- symbol
|
||||
mov BL,AL ; BX <- constant number * 3
|
||||
mov AX,BX
|
||||
shl AX,1
|
||||
add BX,AX
|
||||
add BX,CB_dis ; add displacement of current code block
|
||||
xor AX,AX
|
||||
mov AL,ES:[BX].cod_cpag ; copy the symbol pointer into the
|
||||
mov tmp_page,AX ; temporary register
|
||||
mov AX,ES:[BX].cod_cdis
|
||||
mov tmp_disp,AX
|
||||
; cons(tmp_reg, tmp_reg, value)
|
||||
mov AX,offset tmp_reg ; load address of temporary register
|
||||
pushm <DI,AX,AX> ; push arguments to "cons"
|
||||
C_call cons,<SI>,Load_ES ; create (cons symbol value)
|
||||
; cons(FNV, tmp_reg, FNV)
|
||||
mov AX,offset tmp_reg ; load address of temporary register
|
||||
mov BX,offset FNV_reg ; load addr of fluid environment register
|
||||
pushm <BX,AX,BX> ; push arguments to "cons"
|
||||
C_call cons ; create (cons (cons symbol value) FNV)
|
||||
jmp next_SP ; return to interpreter
|
||||
|
||||
;************************************************************************
|
||||
;* Unbind fluid variable UNBIND-FL const *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for unbinding (deleting) fluid *
|
||||
;* variables *
|
||||
;* *
|
||||
;* Description: The fluid environment is maintained as an a-list, so *
|
||||
;* dropping fluids consists of cdr-ing down the list for *
|
||||
;* the required number of elements. *
|
||||
;************************************************************************
|
||||
public unbind_f
|
||||
unbind_f: lods byte ptr ES:[SI] ; load the count of fluids to drop
|
||||
mov DX,ES ; save code block's paragraph address
|
||||
mov CX,AX ; copy the drop count into CX
|
||||
mov BL,byte ptr FNV_pag ; load the fluid environment pointer
|
||||
mov DI,FNV_dis
|
||||
unb_fl: LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load entry's paragraph address
|
||||
mov BL,ES:[DI].cdr_page ; load cdr field of entry
|
||||
mov DI,ES:[DI].cdr
|
||||
loop unb_fl ; continue cdr'ing for desired count
|
||||
mov byte ptr FNV_pag,BL ; re-define the fluid environment
|
||||
mov FNV_dis,DI ; register
|
||||
mov ES,DX ; restore code block paragraph address
|
||||
jmp next ; return to interpreter
|
||||
|
||||
;************************************************************************
|
||||
;* Allocate vector VEC-ALLOCATE dest *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the allocation of vector data *
|
||||
;* objects. *
|
||||
;* *
|
||||
;* Note: Vectors are set to zero after they are allocated to insure *
|
||||
;* that all entries are valid Scheme pointers. Zeroing a *
|
||||
;* vector effectively sets all the entries to nil. *
|
||||
;* If an array were not initialized, the garbage collector *
|
||||
;* would interpret any leftover data as pointers, and *
|
||||
;* might cause the Scheme Virtual Machine to go off the *
|
||||
;* deep end. *
|
||||
;************************************************************************
|
||||
public vec_allo
|
||||
vec_allo: lods byte ptr ES:[SI] ; load destination register number
|
||||
save <SI> ; save the location pointer
|
||||
mov BX,AX ; and copy it to TIPC register BX
|
||||
add BX,offset reg0
|
||||
cmp byte ptr [BX].C_page,SPECFIX*2 ; is size a fixnum?
|
||||
jne ve_al_er ; if not, error (jump)
|
||||
mov AX,[BX].C_disp ; load immediate value from register
|
||||
shl AX,1 ; and sign extend it
|
||||
sar AX,1
|
||||
cmp AX,0 ; value positive?
|
||||
jl ve_al_er ; if not, error (jump)
|
||||
cmp AX,10921 ; check against maximum vector size
|
||||
ja v_toobig ; if too many elements, error (jump)
|
||||
mov CX,AX ; AX <- AX * 3 (multiply number of
|
||||
shl AX,1 ; elements by size of pointer)
|
||||
add AX,CX
|
||||
mov CX,VECTTYPE ; load type of block to allocate
|
||||
pushm <AX,CX,BX> ; push arguments
|
||||
C_call alloc_bl,,Load_ES ; call: alloc_block(®, type, size)
|
||||
pop BX ; recover address of reg holding vector ptr
|
||||
mov AX,[BX].C_page ; fetch page number from destination reg
|
||||
corrpage AX ; correct for C callable routine
|
||||
pushm <[BX].C_disp,AX> ; push page and displacement
|
||||
C_call zero_blk ; call: zero_blk(page, disp)
|
||||
jmp next_SP ; return to interpreter
|
||||
; ***Error-- invalid source operand for vec-alloc***
|
||||
ve_al_er: mov SI,[BX].C_page ; load operand's page number
|
||||
cmp byte ptr ptype+[SI],BIGTYPE*2 ; is it a bignum?
|
||||
je v_toobig ; if so, print "vector too big" message
|
||||
lea BX,m_ve_al ; otherwise, print "source operand"
|
||||
jmp src_err ; error message
|
||||
; ***Error-- vector too large***
|
||||
v_toobig: restore <SI>
|
||||
sub SI,2
|
||||
pushm <SI,m_mkvt_a>
|
||||
C_call disassem,,Load_ES
|
||||
pushm <tmp_adr,m_toobig,m_one>
|
||||
C_call set_nume
|
||||
jmp sch_err
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* Vector size VECTOR-SIZE dest *
|
||||
;* *
|
||||
;* Purpose: Interpreter support for the vector-size function to return *
|
||||
;* the number of elements in a vector data object. *
|
||||
;* *
|
||||
;* Description: The number of elements in a vector data object is *
|
||||
;* determined by dividing the number of bytes (obtained *
|
||||
;* from the block header of the vector data object) by the *
|
||||
;* number of bytes in a pointer (3), and subtracting the *
|
||||
;* overhead of the block header (3 bytes). *
|
||||
;************************************************************************
|
||||
public vec_size
|
||||
vec_size: lods byte ptr ES:[SI] ; load destination register number
|
||||
mov BX,AX ; and copy into TIPC register BX
|
||||
save <SI> ; save the location pointer
|
||||
mov SI,reg0_pag+[BX] ; load page number field of register
|
||||
cmp ptype+[SI],VECTTYPE*2 ; is object a vector?
|
||||
jne vec_s_er ; if not, error (jump)
|
||||
mov DI,reg0_dis+[BX] ; load displacement of vector
|
||||
LoadPage ES,SI
|
||||
;;; mov ES,pagetabl+[SI] ; load vector's page paragraph address
|
||||
mov AX,ES:[DI].vec_len ; load size of object (in bytes),
|
||||
xor DX,DX ; extend to double word,
|
||||
mov CX,3 ; load divisor of three,
|
||||
idiv CX ; divide no. bytes by pointer size
|
||||
dec AX ; subtract off block overhead
|
||||
mov reg0_dis+[BX],AX ; store number of elements
|
||||
mov byte ptr reg0_pag+[BX],SPECFIX*2 ; set tag=fixnum
|
||||
jmp next_PC ; return to interpreter
|
||||
; ***error-- operand doesn't point to a vector data object***
|
||||
vec_s_er: lea BX,m_vec_s
|
||||
jmp src_err ; display error message
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* vector fill vec-fill vect,val*
|
||||
;* *
|
||||
;* Purpose: Scheme intepreter support for the vector-fill operation *
|
||||
;************************************************************************
|
||||
public vec_fill
|
||||
vec_fill: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save location pointer
|
||||
xor BX,BX
|
||||
mov BL,AL ; copy number of register containing vector
|
||||
mov DI,reg0_dis+[BX] ; load vector pointer
|
||||
mov BL,byte ptr reg0_pag+[BX]
|
||||
cmp byte ptr ptype+[BX],VECTTYPE*2 ; is it really a vector?
|
||||
jne vecf_err ; if not, error (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load page address of vector's page
|
||||
mov BL,AH ; copy pointer to fill value
|
||||
mov AX,reg0_dis+[BX] ; load value to fill array
|
||||
mov DL,byte ptr reg0_pag+[BX]
|
||||
mov CX,ES:[DI].vec_len ; load vector length (in bytes) and
|
||||
sub CX,BLK_OVHD ; subtract off overhead for block header
|
||||
jle vecf_fin ; if zero length vector, we're done
|
||||
vecf_lp: mov ES:[DI].vec_page,DL ; store value into current element
|
||||
mov ES:[DI].vec_disp,AX ; of vector
|
||||
add DI,PTRSIZE ; increment pointer into vector
|
||||
sub CX,PTRSIZE ; decrement array size
|
||||
jg vecf_lp ; if more elements to define, loop (jump)
|
||||
vecf_fin: jmp next_PC ; return to Scheme interpreter
|
||||
vecf_err: lea BX,m_vecf
|
||||
jmp src_err
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (memq obj,list) MEMQ dest,src*
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the memq primitive *
|
||||
;************************************************************************
|
||||
; Support for SHIFT-BREAK-- restart operation
|
||||
memq_sb: push m_three ; indicate instruction length = 3
|
||||
C_call restart ; link to Scheme debugger
|
||||
|
||||
public memq
|
||||
memq: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save the current location pointer
|
||||
mov BL,AL ; compute the destination register
|
||||
memq_x: lea DI,reg0+[BX] ; address in TIPC register DI
|
||||
mov AL,byte ptr [DI].C_page ; copy search object pointer
|
||||
mov DX,[DI].C_disp ; into AL,DX (page, disp, respectively)
|
||||
mov BL,AH ; copy pointer to search list
|
||||
mov SI,reg0_dis+[BX] ; load contents of "list" register
|
||||
mov BL,byte ptr reg0_pag+[BX]
|
||||
jmp memq_go
|
||||
memq_nxt: cmp byte ptr s_break,0 ; has shift-break been depressed?
|
||||
jne memq_sb ; if interrupt, jump
|
||||
mov BL,ES:[SI].cdr_page ; load cdr field and continue
|
||||
mov SI,ES:[SI].cdr ; search
|
||||
memq_go: cmp BL,0 ; nil pointer?
|
||||
je memq_f ; if so, return nil (jump)
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; "list" object a list cell?
|
||||
jne memq_f ; if not, return nil (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load paragraph address of list cell
|
||||
cmp DX,ES:[SI].car ; does displacement field of car match obj?
|
||||
jne memq_nxt ; if not, test next element in list (jump)
|
||||
cmp AL,ES:[SI].car_page ; does page field of car match obj?
|
||||
jne memq_nxt ; if not, test next element in list (jump)
|
||||
; match found-- return pointer to current list cell
|
||||
mov byte ptr [DI].C_page,BL ; set destination register to point
|
||||
mov [DI].C_disp,SI ; to current list cell
|
||||
jmp next_PC ; return to interpreter
|
||||
; no match-- return 'nil
|
||||
memq_f: xor AX,AX ; put null value into destination register
|
||||
mov byte ptr [DI].C_page,AL
|
||||
mov [DI].C_disp,AX
|
||||
jmp next_PC ; return to interpreter
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (memv key,list) MEMV dest,src *
|
||||
;* key, list *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the memv primitive *
|
||||
;************************************************************************
|
||||
|
||||
memv_sb: jmp memq_sb ; shift-break support-- link to debugger
|
||||
|
||||
public memv
|
||||
memv: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save the current location pointer
|
||||
mov BL,AL ; compute the destination register
|
||||
mov DI,reg0_pag+[BX] ; load page number of search object
|
||||
; The following 3 lines are sufficient for MEMV if EQV doesn't require
|
||||
; an = test for numbers and only checks types instead. All the remaining
|
||||
; code for MEMV is to handle =.
|
||||
; test attrib+[DI],FLONUMS+BIGNUMS+STRINGS
|
||||
; jz memv_x ; unless one of above types, use "memq"
|
||||
; jmp short memv_y ; otherwise, use full "member" test
|
||||
test attrib[DI],FIXNUMS+FLONUMS+BIGNUMS+STRINGS
|
||||
jz memv_x ; unless one of above types, use "memq"
|
||||
test attrib[DI],FIXNUMS+FLONUMS+BIGNUMS
|
||||
jz memv_y ; for strings do "member" test
|
||||
; key is a number
|
||||
lea DI,reg0[BX] ; DI=address of VM reg containing key
|
||||
mov BL,AH
|
||||
lea SI,reg0[BX] ; SI=address of VM reg containing list
|
||||
push [SI].C_page ; tempsave "list" VM reg
|
||||
push [SI].C_disp
|
||||
jmp short memv_nxt
|
||||
memv_x: jmp memq_x ; these damn short relative jumps!!
|
||||
memv_y: jmp member_x
|
||||
; this list element didn't match, go to the next element
|
||||
memv_more: cmp s_break,0 ; shift-break (IBM: control-break) pressed?
|
||||
jne memv_sb ; yes, do break
|
||||
mov BX,[SI].C_disp ; cdr our way down list
|
||||
mov AL,ES:[BX].cdr_page
|
||||
mov AH,0
|
||||
mov [SI].C_page,AX
|
||||
mov AX,ES:[BX].cdr
|
||||
mov [SI].C_disp,AX
|
||||
; loop over each element in the list
|
||||
memv_nxt: mov BX,[SI].C_page
|
||||
cmp BX,NIL_PAGE ; at end of list?
|
||||
je memv_f ; yes, jump
|
||||
cmp byte ptr ptype[BX],LISTTYPE*2 ; looking at a cons?
|
||||
jne memv_f ; no, jump
|
||||
LoadPage ES,BX ; get cons into memory
|
||||
mov BX,[SI].C_disp ; ES:BX=address of cons cell
|
||||
mov BL,ES:[BX].car_page
|
||||
mov BH,0
|
||||
test attrib[BX],FIXNUMS+FLONUMS+BIGNUMS ; is list elt numeric?
|
||||
jz memv_more ; no, jump
|
||||
; key and list element are both numeric
|
||||
mov tmp_reg.C_page,BX
|
||||
mov BX,[SI].C_disp
|
||||
mov BX,ES:[BX].car
|
||||
mov tmp_reg.C_disp,BX
|
||||
lea BX,tmp_reg
|
||||
; begin comparison of key and list element
|
||||
cmp byte ptr [DI].C_page,SPECFIX*2 ; is key a fixnum?
|
||||
jne memv_float ; no, jump
|
||||
cmp byte ptr [BX].C_page,SPECFIX*2 ; is list elt a fixnum?
|
||||
jne memv_float ; no, jump
|
||||
; both key and list element are fixnums
|
||||
mov AX,[BX] ; AX=list elt
|
||||
mov DX,[DI] ; DX=key
|
||||
shl AX,1
|
||||
shl DX,1
|
||||
cmp AX,DX ; same number?
|
||||
jne memv_more ; no, jump
|
||||
; we have a match, copy list object-pointer to VM register containing key
|
||||
memv_t: mov AX,[SI].C_disp
|
||||
mov [DI].C_disp,AX
|
||||
mov AX,[SI].C_page
|
||||
mov [DI].C_page,AX
|
||||
jmp short memv_f1
|
||||
; we have no match, copy '() to VM register containing key
|
||||
memv_f: xor AX,AX
|
||||
mov [DI].C_page,AX
|
||||
mov [DI].C_disp,AX
|
||||
memv_f1: pop [SI].C_disp ; restore original contents "list" VM reg
|
||||
pop [SI].C_page
|
||||
jmp next_PC ; return to interpreter
|
||||
; key and list element are not both fixnums, do = operation
|
||||
memv_float: mov AX,EQ_OP
|
||||
pushm <ES,DI,SI> ; save our state around C call
|
||||
pushm <BX,DI,AX> ; list elt, key, operation
|
||||
C_call arith2,,Load_ES ; do =
|
||||
popm <SI,SI,SI> ; get C args off stack
|
||||
popm <SI,DI,ES> ; restore our state
|
||||
cmp AX,0 ; AX negative means "error"
|
||||
jge memv_flo2 ; nope
|
||||
jmp sch_err ; yes, go to error handler
|
||||
memv_flo2: jg memv_t ; AX positive means "true"
|
||||
jmp memv_more ; no match, go to next list element
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (member key,list) MEMBER dest,src *
|
||||
;* key, list *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the member primitive *
|
||||
;************************************************************************
|
||||
memb_sb: jmp memq_sb ; shift-break support-- link to debugger
|
||||
public member
|
||||
member: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save the current location pointer
|
||||
mov BL,AL
|
||||
mov DI,reg0_pag+[BX] ; load search object's page number
|
||||
test attrib+[DI],FIXNUMS+SYMBOLS+CONTINU+CLOSURE+PORTS+CODE+CHARS
|
||||
jz member_x ; if not one of these, use "equal?" compare
|
||||
jmp memq_x ; otherwise, use "memq" test
|
||||
member_x: lea DI,reg0+[BX] ; address in TIPC register DI
|
||||
mov CL,byte ptr [DI].C_page ; load pointer to object in CL:DX
|
||||
mov DX,[DI].C_disp
|
||||
mov BL,CL
|
||||
mov CH,byte ptr ptype+[BX] ; load type code of search object
|
||||
mov BL,AH ; copy pointer to search list
|
||||
mov SI,reg0_dis+[BX] ; load contents of "list" register
|
||||
mov BL,byte ptr reg0_pag+[BX]
|
||||
jmp memb_go
|
||||
memb_mor: mov AX,BX
|
||||
mov BL,ES:[SI].car_page
|
||||
cmp CH,byte ptr ptype+[BX]
|
||||
jne memb_nxt
|
||||
pushm <AX,CX,DX,SI> ; save registers across call
|
||||
xor AX,AX
|
||||
mov AL,ES:[SI].car_page
|
||||
mov [BP].temp_reg.C_page,AX ; temp_reg <- (car list)
|
||||
mov AX,ES:[SI].car
|
||||
mov [BP].temp_reg.C_disp,AX
|
||||
lea BX,[BP].temp_reg ; load address of temporary register
|
||||
pushm <BX,DI> ; push arguments
|
||||
C_call sequal_p,,Load_ES ; call: sequal_p(&dest,&src)
|
||||
pop DI ; retrieve destination register address
|
||||
add SP,WORDINCR ; dump other arguments from stack
|
||||
popm <SI,DX,CX,BX> ; restore registers
|
||||
LoadPage ES,BX ; restore page paragraph address
|
||||
cmp AX,0 ; were values equal?
|
||||
jne memb_fnd ; if so, jump
|
||||
memb_nxt: cmp s_break,0 ; has shift-break key been depressed?
|
||||
jne memb_sb ; if interrupt, jump
|
||||
mov BL,ES:[SI].cdr_page ; load cdr field and continue
|
||||
mov SI,ES:[SI].cdr ; search
|
||||
memb_go: cmp BL,0 ; nil pointer?
|
||||
je memb_f ; if so, return nil (jump)
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; "list" object a list cell?
|
||||
jne memb_f ; if not, return nil (jump)
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load paragraph address of list cell
|
||||
cmp DX,ES:[SI].car ; does displacement field of car match obj?
|
||||
jne memb_mor ; if not, test next element in list (jump)
|
||||
cmp CL,ES:[SI].car_page ; does page field of car match obj?
|
||||
jne memb_mor ; if not, test next element in list (jump)
|
||||
; "eq" match found-- return pointer to current list cell
|
||||
memb_fnd: mov byte ptr [DI].C_page,BL ; set destination register to point
|
||||
mov [DI].C_disp,SI ; to current list cell
|
||||
jmp next_PC ; return to interpreter
|
||||
; no match-- return 'nil
|
||||
memb_f: xor AX,AX ; put null value into destination register
|
||||
mov byte ptr [DI].C_page,AL
|
||||
mov [DI].C_disp,AX
|
||||
jmp next_PC ; return to interpreter
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (assq obj,list) ASSQ obj,list*
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the assq primitive *
|
||||
;************************************************************************
|
||||
public assq
|
||||
assq: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save the location pointer
|
||||
assq_go: mov BL,AH ; copy the list register number
|
||||
mov SI,reg0_pag+[BX]
|
||||
cmp ptype+[SI],LISTTYPE*2 ; is second operand a list?
|
||||
jne assq_err ; if not, error(?) (jump)
|
||||
LoadPage ES,SI
|
||||
mov DI,SI ; Save page number
|
||||
;;; mov ES,pagetabl+[SI] ; load list page's paragraph address
|
||||
mov SI,reg0_dis+[BX] ; load pointer to list operand
|
||||
mov BL,AL ; load object register number
|
||||
mov DX,reg0_pag+[BX] ; load pointer to search object
|
||||
mov AX,reg0_dis+[BX]
|
||||
push BX ; save destination register number
|
||||
mov BX,DI ; Pass the page number
|
||||
call lookup ; search list for eq? comparison of obj
|
||||
pop SI ; restore destination register number
|
||||
mov byte ptr reg0_pag+[SI],BL ; store result of search in
|
||||
mov reg0_dis+[SI],DI ; the destination register
|
||||
jmp next_PC ; return to interpreter
|
||||
; ***second operand is not a list-- return nil***
|
||||
assq_err: mov BL,AL ; copy destination register number
|
||||
xor AX,AX
|
||||
mov byte ptr reg0_pag+[BX],AL ; store nil into destination
|
||||
mov reg0_dis+[BX],AX ; register
|
||||
jmp next_PC ; return to interpreter
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (assv key,alist) ASSV key,alist *
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the assv primitive *
|
||||
;************************************************************************
|
||||
|
||||
assv_sb: jmp memq_sb ; shift-break support-- link to debugger
|
||||
|
||||
public assv
|
||||
assv: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save the location pointer
|
||||
mov BL,AL ; get number of VM register containing key
|
||||
mov DI,reg0_pag+[BX] ; load key's page number
|
||||
; The following 3 lines are sufficient for ASSV if EQV doesn't require
|
||||
; an = test for numbers and only checks types instead. All the remaining
|
||||
; code for ASSV is to handle =.
|
||||
; test attrib+[SI],FLONUMS+BIGNUMS+STRINGS ; one of these?
|
||||
; jz assq_go ; if not one of above, use assq (jump)
|
||||
; jmp short assoc_go ; if one of the above, use assoc
|
||||
test attrib[DI],FIXNUMS+FLONUMS+BIGNUMS+STRINGS
|
||||
jz assv_x ; unless one of above types, use "assq"
|
||||
test attrib[DI],FIXNUMS+FLONUMS+BIGNUMS
|
||||
jz assv_y ; for strings do "assoc" test
|
||||
; key is a number
|
||||
lea DI,reg0[BX] ; DI=address of VM reg containing key
|
||||
mov BL,AH
|
||||
lea SI,reg0[BX] ; SI=address of VM reg containing list
|
||||
push [SI].C_page ; tempsave "alist" VM reg
|
||||
push [SI].C_disp
|
||||
jmp short assv_nxt
|
||||
assv_x: jmp assq_go ; these damn short relative jumps!!
|
||||
assv_y: jmp assoc_go
|
||||
; this list element didn't match, go to the next element
|
||||
assv_more: cmp s_break,0 ; shift-break (IBM: control-break) pressed?
|
||||
jne assv_sb ; yes, do break
|
||||
mov BX,[SI].C_page
|
||||
LoadPage ES,BX ; get toplevel cons back into memory
|
||||
mov BX,[SI].C_disp ; ES:BX=address of toplevel cons cell
|
||||
mov AL,ES:[BX].cdr_page ; cdr down the alist
|
||||
mov AH,0
|
||||
mov [SI].C_page,AX
|
||||
mov AX,ES:[BX].cdr
|
||||
mov [SI].C_disp,AX
|
||||
; loop over each element in the list
|
||||
assv_nxt: mov BX,[SI].C_page
|
||||
cmp BX,NIL_PAGE ; at end of list?
|
||||
je assv_f ; yes, jump
|
||||
cmp byte ptr ptype[BX],LISTTYPE*2 ; looking at a cons?
|
||||
jne assv_f ; no, jump
|
||||
LoadPage ES,BX ; get toplevel cons into memory
|
||||
mov BX,[SI].C_disp ; ES:BX=address of toplevel cons cell
|
||||
push BX ; tempsave it
|
||||
mov BL,ES:[BX].car_page
|
||||
mov BH,0
|
||||
cmp byte ptr ptype[BX],LISTTYPE*2 ; is car of toplevel cons also a cons?
|
||||
je assv_down ; yes, jump
|
||||
assv_pop: pop BX ; normalize stack
|
||||
assv_more1: jmp assv_more ; look at next toplevel cons
|
||||
assv_down: mov DX,BX
|
||||
pop BX ; (ES:BX=address of toplevel cons again)
|
||||
mov BX,ES:[BX].car ; DX:BX=object ptr to 2nd level cons
|
||||
LoadPage ES,DX ; ES:BX=address of 2nd level cons cell
|
||||
push BX ; tempsave it
|
||||
mov BL,ES:[BX].car_page
|
||||
mov BH,0
|
||||
test attrib[BX],FIXNUMS+FLONUMS+BIGNUMS ; is its car numeric?
|
||||
jz assv_pop ; no, jump
|
||||
mov tmp_reg.C_page,BX ; yes, move car ptr into tmp_reg
|
||||
pop BX ; (ES:BX=address of 2nd level cons again)
|
||||
mov BX,ES:[BX].car
|
||||
mov tmp_reg.C_disp,BX
|
||||
lea BX,tmp_reg ; BX=address of tmp_reg
|
||||
; begin comparison of key and list element
|
||||
cmp byte ptr [DI].C_page,SPECFIX*2 ; is key a fixnum?
|
||||
jne assv_float ; no, jump
|
||||
cmp byte ptr [BX].C_page,SPECFIX*2 ; is list elt a fixnum?
|
||||
jne assv_float ; no, jump
|
||||
; both key and list element are fixnums
|
||||
mov AX,[BX] ; AX=list elt
|
||||
mov DX,[DI] ; DX=key
|
||||
shl AX,1
|
||||
shl DX,1
|
||||
cmp AX,DX ; same number?
|
||||
jne assv_more1 ; no, jump
|
||||
jmp short assv_t
|
||||
; we have no match, copy '() to VM register containing key
|
||||
assv_f: xor AX,AX
|
||||
mov [DI].C_page,AX
|
||||
mov [DI].C_disp,AX
|
||||
assv_f1: pop [SI].C_disp ; restore original contents "alist" VM reg
|
||||
pop [SI].C_page
|
||||
jmp next_PC ; return to interpreter
|
||||
; we have a match, copy list object-pointer to VM register containing key
|
||||
assv_t: mov BX,[SI].C_page
|
||||
LoadPage ES,BX
|
||||
mov BX,[SI].C_disp ; ES:BX=address of toplevel cons
|
||||
mov AX,ES:[BX].car ; move car of this cons to dest. register
|
||||
mov [DI].C_disp,AX
|
||||
mov AL,ES:[BX].car_page
|
||||
mov AH,0
|
||||
mov [DI].C_page,AX
|
||||
jmp assv_f1 ; return to interpreter
|
||||
; key and list element are not both fixnums, do = operation
|
||||
assv_float: mov AX,EQ_OP
|
||||
pushm <ES,DI,SI> ; save our state around C call
|
||||
pushm <BX,DI,AX> ; list elt, key, operation
|
||||
C_call arith2,,Load_ES ; do =
|
||||
popm <SI,SI,SI> ; get C args off stack
|
||||
popm <SI,DI,ES> ; restore our state
|
||||
cmp AX,0 ; AX negative means "error"
|
||||
jge assv_flo2 ; nope
|
||||
jmp sch_err ; yes, go to error handler
|
||||
assv_flo2: jg assv_t ; AX positive means "true"
|
||||
jmp assv_more ; no match, go to next list element
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* AL AH *
|
||||
;* (assoc obj,list) ASSOC obj,list*
|
||||
;* *
|
||||
;* Purpose: Scheme interpreter support for the assoc primitive *
|
||||
;* *
|
||||
;* Register Usage: DX - address of destination register *
|
||||
;* ES:SI - pointer to current list cell *
|
||||
;************************************************************************
|
||||
public assoc
|
||||
assoc: lods word ptr ES:[SI] ; load operands
|
||||
save <SI> ; save the location pointer
|
||||
mov BL,AL ; copy search object's register number
|
||||
mov SI,reg0_pag+[BX] ; load search object's page number
|
||||
test attrib+[SI],FIXNUMS+SYMBOLS+CONTINU+CLOSURE+PORTS+CODE+CHARS
|
||||
jz assoc_go
|
||||
jmp assq_go ; if one of the above, use assq (jump)
|
||||
assoc_go: mov DX,BX ; copy obj's reg number into TIPC reg DX
|
||||
add DX,offset reg0 ; compute address of search obj register
|
||||
mov BL,AH ; copy list register number
|
||||
mov SI,reg0_dis+[BX] ; load displacement pointer of "list"
|
||||
mov BL,byte ptr reg0_pag+[BX] ; load page number of "list"
|
||||
assoc_lp: cmp BL,0 ; end of list? (nil pointer?)
|
||||
je assoc_nf ; if end of list, jump
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; is list operand a list?
|
||||
jne assoc_er ; if not, error(?) (jump)
|
||||
LoadPage ES,BX
|
||||
mov AX,BX ;****** SAVE PAGE *********
|
||||
;;; mov ES,pagetabl+[BX] ; load list page's paragraph address
|
||||
mov BL,ES:[SI].car_page ; load page number of car
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; does car point to list cell?
|
||||
jne assoc_nl ; if not a list cell, jump
|
||||
mov DI,ES:[SI].car ; load displacement pointer of car field
|
||||
pushm <AX,SI> ;****** REALLY SAVE PAGE****
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
xor AX,AX
|
||||
mov AL,ES:[DI].car_page ; copy car field into tmp_reg
|
||||
mov tmp_page,AX
|
||||
mov AX,ES:[DI].car
|
||||
mov tmp_disp,AX
|
||||
mov AX,offset tmp_reg
|
||||
pushm <DX,AX> ; push arguments to call
|
||||
C_call sequal_p,,Load_ES ; compare equality of the two pointers
|
||||
add SP,WORDINCR ; dump tmp_reg address
|
||||
pop DX ; restore obj/dest register address
|
||||
popm <SI,BX> ; restore ES,SI registers
|
||||
LoadPage ES,BX ;********** Restore Para Address *****
|
||||
cmp AX,0 ; were pointers equal?
|
||||
jne assoc_t ; if equal, jump
|
||||
assoc_nl: xor BX,BX ; clear high order byte of BX
|
||||
mov BL,ES:[SI].cdr_page ; follow cdr field
|
||||
mov SI,ES:[SI].cdr
|
||||
cmp byte ptr s_break,0 ; has the shift-break key been depressed?
|
||||
je assoc_lp ; if no shift-break, loop
|
||||
jmp memq_sb ; if interrupt, jump to debugger support
|
||||
; pointers "equal"-- return pointer to car field of current list cell
|
||||
assoc_t: mov DI,DX ; copy destination register address to DI
|
||||
mov AL,ES:[SI].car_page ; return cdr field of list cell
|
||||
mov byte ptr [DI].C_page,AL
|
||||
mov AX,ES:[SI].car
|
||||
mov [DI].C_disp,AX
|
||||
jmp next_PC ; return to interpreter
|
||||
; end of search, or error detected-- return nil
|
||||
assoc_er:
|
||||
assoc_nf: mov DI,DX ; copy destination register address to DI
|
||||
mov byte ptr [DI].C_page,NIL_PAGE*2 ; store nil pointer into
|
||||
mov [DI].C_disp,NIL_DISP ; destination register
|
||||
jmp next_PC ; return to interpreter
|
||||
|
||||
var_int endp
|
||||
|
||||
;************************************************************************
|
||||
;* Lookup Symbol is Assoc List *
|
||||
;* *
|
||||
;* Purpose: To search a linked list for a given pointer *
|
||||
;* *
|
||||
;* Description: The list to be searched has the following format: *
|
||||
;* *
|
||||
;* +--------+--------+ +--------+-------+ *
|
||||
;* +-->|symbol->|value ->| +-->|symbol->|value->| *
|
||||
;* | +--------+--------+ | +--------+-------+ *
|
||||
;* | | *
|
||||
;* +---+----+--------+ +---+----+--------+ *
|
||||
;* | o | o----+----...----->| o | (nil) | *
|
||||
;* +--------+--------+ +--------+--------+ *
|
||||
;* *
|
||||
;* The symbol portion of the list entries are compared against the *
|
||||
;* search symbol for an identical match. When found, a pointer to *
|
||||
;* the matched symbol's symbol-value entry is returned. If the *
|
||||
;* symbol is not found, a value of nil is returned. *
|
||||
;* *
|
||||
;* Registers upon entry: AX - search symbol's displacement *
|
||||
;* BX - page number of list to search *
|
||||
;* DL - search symbol's page number *
|
||||
;* SI - displacement within page number *
|
||||
;* of list to search *
|
||||
;* *
|
||||
;* Registers on exit: BL - page number of cell whose car is the *
|
||||
;* search symbol, or zero if not found *
|
||||
;* DI - displacement of list cell found, or nil *
|
||||
;* ES:[DI] - points to cell found *
|
||||
;************************************************************************
|
||||
public lookup
|
||||
lookup proc near
|
||||
lookloop:
|
||||
mov CX,BX ; Save Page number
|
||||
LoadPage ES,BX ; Load Paragraph address of page
|
||||
mov BL,ES:[SI].car_page ; load car of next list cell in the list
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; is car a list cell?
|
||||
mov DI,ES:[SI].car
|
||||
jne look_err ; if not a list cell, jump
|
||||
LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX] ; load paragraph address of its page
|
||||
cmp AX,ES:[DI].car ; does car's disp match search symbol's?
|
||||
jne look_nf ; if not, keep searching (jump)
|
||||
cmp DL,ES:[DI].car_page ; does car's page match search symbol's?
|
||||
je look_fnd ; if so, we've got a match (jump)
|
||||
; no match-- continue through linked list
|
||||
look_nf: mov BX,CX ; restore page number
|
||||
LoadPage ES,BX
|
||||
mov BL,ES:[SI].cdr_page ; load the cdr field
|
||||
cmp byte ptr ptype+[BX],LISTTYPE*2 ; is cdr another list cell?
|
||||
jne look_err ; if not, error(?)
|
||||
mov SI,ES:[SI].cdr
|
||||
cmp BX,0 ; is cdr nil?
|
||||
jne lookloop ; if not, branch
|
||||
xor DI,DI ; make BX:DI nil
|
||||
look_fnd: ret ; return pointer to caller
|
||||
;
|
||||
look_err: xor BX,BX ; create a nil pointer to return
|
||||
xor SI,SI
|
||||
ret
|
||||
lookup endp
|
||||
|
||||
;************************************************************************
|
||||
;* C-callable Fluid Variable Lookup *
|
||||
;* *
|
||||
;* Purpose: To retrieve the fluid binding for a variable. *
|
||||
;* *
|
||||
;* Calling Sequence: stat = fluid_lookup(®) *
|
||||
;* where ® - address of the register containing *
|
||||
;* the symbol to be looked up. *
|
||||
;* On exit, "reg" contains the *
|
||||
;* current binding for the symbol, *
|
||||
;* if found. *
|
||||
;* stat - search status: TRUE=symbol found *
|
||||
;* FALSE=symbol not found *
|
||||
;* *
|
||||
;* Note: If the call to "lookup" doesn't find the desired symbol, it *
|
||||
;* will return a nil pointer. It is correct to always *
|
||||
;* return the cdr of the pointer "lookup" returns, since *
|
||||
;* the cdr of nil is itself nil-- a valid value. *
|
||||
;************************************************************************
|
||||
fl_lk_ar struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; caller's ES
|
||||
dw ? ; return address
|
||||
fl_lk_rg dw ? ; register address
|
||||
fl_lk_ar ends
|
||||
|
||||
public fluid_lo
|
||||
fluid_lo proc near
|
||||
push ES ; save caller's ES
|
||||
push BP ; and BP
|
||||
mov BP,SP
|
||||
; load pointer to search symbol in DL:AX
|
||||
mov BX,[BP].fl_lk_rg ; load register address
|
||||
mov AX,[BX].C_disp
|
||||
mov DL,byte ptr [BX].C_page
|
||||
; load pointer to search list (fluid environment) in ES:[SI]
|
||||
mov BX,FNV_pag
|
||||
mov SI,FNV_dis
|
||||
;;; LoadPage ES,BX
|
||||
;;; mov ES,pagetabl+[BX]
|
||||
; search the fluid environment for the symbol
|
||||
call lookup
|
||||
; store "cdr" of returned cell into register
|
||||
mov SI,[BP].fl_lk_rg
|
||||
mov AL,ES:[DI].cdr_page
|
||||
mov byte ptr [SI].C_page,AL
|
||||
mov AX,ES:[DI].cdr
|
||||
mov [SI].C_disp,AX
|
||||
; set return code (BX=0 if symbol not found) and return
|
||||
mov AX,BX
|
||||
pop BP ; restore caller's BP
|
||||
pop ES ; and ES
|
||||
ret ; return to caller
|
||||
fluid_lo endp
|
||||
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
data ends
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
public isw_int,fsw_int,tsw_int,ssw_int
|
||||
|
||||
SWI_ARGS struc
|
||||
OLDBP DW ?
|
||||
RET_ADDR DW ?
|
||||
INT_NUM DW ?
|
||||
AX_ARG DW ?
|
||||
BX_ARG DW ?
|
||||
CX_ARG DW ?
|
||||
DX_ARG DW ?
|
||||
SWI_ARGS ends
|
||||
|
||||
sw_int proc near
|
||||
isw_int:
|
||||
fsw_int:
|
||||
tsw_int:
|
||||
ssw_int:
|
||||
push bp ; Save Base Pointer
|
||||
mov bp,sp ; Update with Stack Pointer
|
||||
|
||||
mov ax,[bp].INT_NUM ; Get interrupt number
|
||||
mov cs:int_no,al ; Move to location in code
|
||||
|
||||
mov ax,[bp].AX_ARG ; Load ax register with 1st arg
|
||||
mov bx,[bp].BX_ARG ; Load bx register with 2nd arg
|
||||
mov cx,[bp].CX_ARG ; Load cx register with 3rd arg
|
||||
mov dx,[bp].DX_ARG ; Load dx register with 4th arg
|
||||
|
||||
db 0CDh ; Byte code for INT instruction
|
||||
int_no db 070h ; Byte code for interrupt number
|
||||
pop bp
|
||||
ret ; and go back to the caller.
|
||||
|
||||
sw_int endp
|
||||
prog ends
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#ifdef REGMEM
|
||||
#define VERSION "\n PC Scheme 3.03 07 June 88"
|
||||
#endif
|
||||
|
||||
#ifdef EXPMEM
|
||||
#define VERSION "\n PC Scheme 3.03 Expanded Memory Version 07 June 88"
|
||||
#endif
|
||||
|
||||
#ifdef EXTMEM
|
||||
#define VERSION "\n PC Scheme 3.03 Extended Memory Version 07 June 88"
|
||||
#endif
|
||||
|
||||
#ifdef PROMEM
|
||||
#define VERSION "\n PC Scheme 4.0 Protected Memory Version 24 June 88"
|
||||
#endif
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
; XLI constants
|
||||
; note: if N_EXE is ever made larger, examine macro "load_index" also
|
||||
XLI_ID equ 4252h ;XLI version number
|
||||
;(PCS 3.0, 3.02 XLI id = 4252)
|
||||
N_EXE equ 10 ;no. of .EXE files allowed
|
||||
N_ARGS equ 16 ;no. of xesc args allowed
|
||||
N_RV equ 4 ;no. of return values
|
||||
;same as for SW-INT: 0-3, with same meaning
|
||||
SWI_TF equ 1 ;SW-INT true/false return value
|
||||
SWI_STR equ 2 ;SW-INT string return value
|
||||
RV_ERR equ 10 ;error return value code
|
||||
PAD_SIZE equ 8 ;max size of 1 elementary data type,
|
||||
;which is size of 1 elt in work_area
|
||||
;(flonum/double)
|
||||
|
||||
; XLI errors
|
||||
XLI_ERR_UNKNOWN_LENGTH equ 1 ;fatal error
|
||||
XLI_ERR_NAME_BAD_TYPE equ 2
|
||||
;XLI_ERR_MISMATCHED_LENGTH equ 3
|
||||
XLI_ERR_ARGN_BAD_TYPE equ 4
|
||||
XLI_ERR_VALUE_BAD_TYPE equ 5
|
||||
XLI_ERR_NO_SUCH_NAME equ 6
|
||||
XLI_ERR_BIG_TO_32_BITS equ 7
|
||||
XLI_ERR_SYNC_ERR equ 8
|
||||
XLI_ERR_RELMEM equ 9
|
||||
XLI_ERR_NO_MEMORY equ 10
|
||||
XLI_ERR_BAD_EXEC equ 11
|
||||
XLI_ERR_NO_AVAILABLE_SLOTS equ 12
|
||||
XLI_ERR_NO_SUCH_FILE equ 13
|
||||
XLI_ERR_BIG_TO_16_BITS equ 14
|
||||
XLI_ERR_BAD_VERSION equ 15
|
||||
XLI_ERR_EXTERNAL_ERROR equ 16
|
||||
|
||||
; DOS function requests
|
||||
FR_TSR equ 3100h ;TSR (keep process)
|
||||
FR_OPEN equ 3D00h ;open file
|
||||
FR_CLOSE equ 3E00h ;close file
|
||||
FR_READ equ 3F00h ;read from file
|
||||
FR_RELMEM equ 4900h ;release memory block
|
||||
FR_EXEC equ 4B00h ;bid (exec) child process
|
||||
FR_FIND1 equ 4E00h ;find match file
|
||||
|
||||
; .EXE states
|
||||
EXE_NONE equ 0 ;this spot is open (haven't EXEC'ed child)
|
||||
EXE_TSR equ 1 ;have EXEC'ed child but not yet TSR'ed it
|
||||
EXE_NORM equ 2 ;child loaded and waiting
|
||||
EXE_TERM equ 3 ;child terminating
|
||||
|
||||
; File block flags
|
||||
FB_NEAR equ 01h ;1=copy to child's space (near data)
|
||||
;0=no copy (far data)
|
||||
FB_INT equ 02h ;1=convert PCS integers to 16-bit int's
|
||||
;0=convert to 32-bit longint's
|
||||
FB_KEEPENV equ 04h ;1=don't release child's env block
|
||||
;0=we do it for child automatically
|
||||
FB_PAD equ 08h ;1=space each arg in dest 8 bytes apart
|
||||
;0=pack args contiguously
|
||||
FB_SYSINT equ 10h ;1=system callable routine
|
||||
;0=normal xli routine
|
||||
|
||||
; Special services
|
||||
SS_SWAP equ 1 ;swap
|
||||
|
||||
; PSP offsets
|
||||
env_ptr equ 02Ch ;env block offset
|
||||
fb_ptr equ 05Ch ;file block offset
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
subttl Macro definitions
|
||||
|
||||
; In segment 'segzero' set $ to the next multiple of 'n'.
|
||||
align macro n,segzero
|
||||
org $ - (($-segzero) MOD n) + n
|
||||
endm
|
||||
|
||||
; Issue a DOS function request (int 21h) after
|
||||
; setting up registers ax,bx,cx,dx,ds,es.
|
||||
; Registers not specified are not affected by the macro,
|
||||
; code to move a reg to itself is skipped, and
|
||||
; moves between DS and ES are handled.
|
||||
dos_fr macro rax,rbx,rcx,rdx,rds,res
|
||||
ifnb <rax> ;;ax
|
||||
ifidn <rax>,<ax>
|
||||
else
|
||||
mov ax,rax
|
||||
endif
|
||||
endif
|
||||
ifnb <rbx> ;;bx
|
||||
ifidn <rbx>,<bx>
|
||||
else
|
||||
mov bx,rbx
|
||||
endif
|
||||
endif
|
||||
ifnb <rcx> ;;cx
|
||||
ifidn <rcx>,<cx>
|
||||
else
|
||||
mov cx,rcx
|
||||
endif
|
||||
endif
|
||||
ifnb <rdx> ;;dx
|
||||
ifidn <rdx>,<dx>
|
||||
else
|
||||
mov dx,rdx
|
||||
endif
|
||||
endif
|
||||
ifnb <res> ;;es
|
||||
ifidn <res>,<ds>
|
||||
push ds
|
||||
pop es
|
||||
else
|
||||
ifidn <res>,<es>
|
||||
else
|
||||
mov es,res
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifnb <rds> ;;ds
|
||||
ifidn <rds>,<es>
|
||||
push es
|
||||
pop ds
|
||||
else
|
||||
ifidn <rds>,<ds>
|
||||
else
|
||||
mov ds,rds
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
int 21h
|
||||
endm
|
||||
|
||||
; Given the value of "active_exe", put into BX the corresponding byte offset
|
||||
; into various tables. If table="itself", just load BX.
|
||||
;
|
||||
; Note: The calculated byte offset must fit into BL because we use BH for
|
||||
; scratch. We don't affect any other register this way. If the
|
||||
; number of entries allowed in the tables is enlarged so that we
|
||||
; could overflow into BH, this macro will need changing. Changing
|
||||
; a table's format will obviously affect this macro too.
|
||||
load_index macro table
|
||||
mov bx,active_exe
|
||||
ifdif <itself>,<table>
|
||||
xor bh,bh
|
||||
endif
|
||||
ifidn <load_table>,<table>
|
||||
shl bx,1 ;; 2 bytes/entry
|
||||
endif
|
||||
ifidn <fb_table>,<table>
|
||||
shl bx,1 ;; 4
|
||||
shl bx,1
|
||||
endif
|
||||
ifidn <pb_table>,<table>
|
||||
shl bx,1 ;; 4
|
||||
shl bx,1
|
||||
endif
|
||||
ifidn <state_table>,<table>
|
||||
mov bh,bl
|
||||
shl bx,1 ;;shift BH and BL simultaneously
|
||||
shl bl,1
|
||||
shl bl,1
|
||||
add bl,bh ;; 10
|
||||
xor bh,bh
|
||||
endif
|
||||
ifidn <status_table>,<table>
|
||||
shl bx,1 ;; 2
|
||||
endif
|
||||
endm
|
||||
|
||||
; *** All registers on entry except CS,IP belong to the child. ***
|
||||
; *** On exit, all registers except CS,IP,DS still belong to the child. ***
|
||||
; This routine captures all the child's registers' values (except CS:IP,
|
||||
; which is located on the stack at the saved SS:SP).
|
||||
; DS is changed to PCS's data segment.
|
||||
save_state macro
|
||||
push ds ;pushes are in child's data segment
|
||||
push ax
|
||||
mov ax,data
|
||||
mov ds,ax ;DS points to PCS's data segment
|
||||
pop ax ;get back ax
|
||||
mov save_ax,ax
|
||||
mov save_bx,bx
|
||||
mov save_cx,cx
|
||||
mov save_dx,dx
|
||||
mov save_si,si
|
||||
mov save_di,di
|
||||
pop ax ;get back ds (stack now same as on entry)
|
||||
mov save_ds,ax
|
||||
mov save_es,es
|
||||
mov save_ss,ss
|
||||
mov save_sp,sp
|
||||
mov save_bp,bp
|
||||
endm
|
||||
|
||||
; Save the parent's (i.e. PCS's) segment and pointer registers.
|
||||
save_parent macro
|
||||
mov pcs_state.st_es,es ;save our state
|
||||
mov pcs_state.st_ss,ss
|
||||
mov pcs_state.st_sp,sp
|
||||
mov pcs_state.st_bp,bp
|
||||
mov pcs_state.st_ds,ds
|
||||
endm
|
||||
|
||||
; Restore the parent's segment and pointer registers.
|
||||
restore_parent macro
|
||||
mov bx,offset pcs_state ;restore parent's state
|
||||
cli
|
||||
mov es,[bx].st_es
|
||||
mov ss,[bx].st_ss
|
||||
mov sp,[bx].st_sp
|
||||
mov bp,[bx].st_bp
|
||||
;; mov ds,[bx].st_ds ;save_state made DS active already
|
||||
sti
|
||||
endm
|
||||
|
||||
; Save off our registers and restore child's, then resume child.
|
||||
call_child macro x
|
||||
save_parent
|
||||
load_index state_table
|
||||
lea bx,state_table[bx]
|
||||
cli ; restore child's state
|
||||
mov es,[bx].st_es
|
||||
mov ss,[bx].st_ss
|
||||
mov sp,[bx].st_sp
|
||||
mov bp,[bx].st_bp
|
||||
mov ds,[bx].st_ds
|
||||
sti
|
||||
xlidbg&x label byte
|
||||
nop ;;this gets replaced with INT 3 for debug
|
||||
nop
|
||||
db 0CBh ;resume child via far return
|
||||
endm
|
||||
|
||||
; Save off child's registers and restore ours, then continue.
|
||||
resume_parent macro
|
||||
save_state ;save child's registers in global area
|
||||
restore_parent
|
||||
load_index state_table
|
||||
lea bx,state_table[bx]
|
||||
mov ax,save_ds ;save child's regs in child-local area
|
||||
mov [bx].st_ds,ax
|
||||
mov ax,save_es
|
||||
mov [bx].st_es,ax
|
||||
mov ax,save_ss
|
||||
mov [bx].st_ss,ax
|
||||
mov ax,save_sp
|
||||
mov [bx].st_sp,ax
|
||||
mov ax,save_bp
|
||||
mov [bx].st_bp,ax
|
||||
endm
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
IFNDEF BLOCK_XFER
|
||||
BLOCK_XFER equ 0EC00h ; Block Transfer
|
||||
ENDIF
|
||||
|
||||
IFNDEF DOS
|
||||
DOS equ 021h ; Dos Function Request
|
||||
ENDIF
|
||||
|
||||
;MOVE_ARGS_TO_BUF
|
||||
; Move the specified arguments to a buffer. If the buffer is not
|
||||
; specified, then ES:DI is assumed to contain the address of the
|
||||
; buffer.
|
||||
;
|
||||
; The specified args are pushed onto the local stack, and the
|
||||
; address noted in DS:SI. The args are then moved to the
|
||||
; specifed buffer.
|
||||
move_args_to_buf macro args,realaddr,autobump,save
|
||||
numbytes = 0
|
||||
irp x,<args>
|
||||
numbytes = numbytes + 2
|
||||
push x
|
||||
endm
|
||||
IFNB <realaddr>
|
||||
les di,dword ptr ss:&realaddr
|
||||
ENDIF
|
||||
mov cx,numbytes
|
||||
mov si,sp
|
||||
move_to_real_buf autobump,save
|
||||
add sp,numbytes
|
||||
endm
|
||||
|
||||
;MOVE_TO_REAL_BUF
|
||||
; Move CX number of bytes from DS:SI to buffer specifed in ES:DI.
|
||||
; Since the destination may be in real mode, use the AIA Dos
|
||||
; extended function Block_Xfer.
|
||||
move_to_real_buf macro autobump,save_offset
|
||||
mov ax,BLOCK_XFER
|
||||
int DOS
|
||||
IFNB <autobump>
|
||||
IFE direction
|
||||
add di,cx
|
||||
ELSE
|
||||
sub di,cx
|
||||
ENDIF
|
||||
ENDIF
|
||||
IFNB <save_offset>
|
||||
mov ss:&real_buf_offset,di
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
;MOVE_BYTE_TO_BUF
|
||||
; Move one byte from the buffer specified in DS:SI to the
|
||||
; destination address in ES:DI.
|
||||
MOVE_BYTE_TO_BUF macro byt,realaddr,autobump
|
||||
IFNB <realaddr>
|
||||
les di,dword ptr ss:&realaddr
|
||||
ENDIF
|
||||
sub sp,2
|
||||
mov si,sp
|
||||
mov byte ptr ss:[si],byt
|
||||
mov cx,1
|
||||
mov ax,BLOCK_XFER
|
||||
int DOS
|
||||
IFNB <autobump>
|
||||
IFE direction
|
||||
inc di
|
||||
ELSE
|
||||
dec di
|
||||
ENDIF
|
||||
ENDIF
|
||||
add sp,2
|
||||
endm
|
||||
|
||||
;MOVE_ARGS_FROM_BUF
|
||||
; Get the specified arguments from a buffer. If the buffer is not
|
||||
; specified, then ES:DI is assumed to contain the address of the
|
||||
; buffer.
|
||||
;
|
||||
; The number of bytes specified by the args is allocated on
|
||||
; the local stack, and the address noted in DS:SI. The args
|
||||
; are then moved from the desired buffer onto the local stack,
|
||||
; and popped into the desired args.
|
||||
move_args_from_buf macro args,realaddr
|
||||
numbytes = 0
|
||||
irp x,<args>
|
||||
numbytes = numbytes + 2
|
||||
endm
|
||||
IFNB <realaddr>
|
||||
les di,dword ptr ss:&realaddr
|
||||
ENDIF
|
||||
mov cx,numbytes
|
||||
sub sp,cx
|
||||
mov si,sp
|
||||
move_from_real_buf
|
||||
irp x,<args>
|
||||
pop x
|
||||
endm
|
||||
endm
|
||||
|
||||
;MOVE_FROM_REAL_BUF
|
||||
; Move CX number of bytes from the buffer specified in ES:DI to
|
||||
; the destination address in DS:SI. Swap the source and
|
||||
; destination registers and perform the AIA Dos extended function
|
||||
; Block_Xfer (in case the source buffer is in real memory).
|
||||
move_from_real_buf macro
|
||||
mov bx,es
|
||||
mov dx,ds
|
||||
mov ds,bx
|
||||
mov es,dx
|
||||
xchg di,si
|
||||
mov ax,BLOCK_XFER
|
||||
int DOS
|
||||
mov ds,dx
|
||||
mov es,bx
|
||||
xchg di,si
|
||||
endm
|
||||
|
||||
;REAL_BYTE_TO REG
|
||||
; Move a byte from the buffer specified by DS:SI to a register.
|
||||
;
|
||||
; ES must equal SS
|
||||
real_byte_to_reg macro reg,autobump
|
||||
push cx
|
||||
mov cx,1
|
||||
sub sp,2
|
||||
mov di,sp
|
||||
mov ax,BLOCK_XFER
|
||||
int DOS
|
||||
mov al,byte ptr es:[di]
|
||||
IFNB <autobump>
|
||||
inc si
|
||||
ENDIF
|
||||
add sp,2
|
||||
pop cx
|
||||
endm
|
||||
|
||||
|
||||
reset_real_buffer_offset macro
|
||||
mov ss:real_buf_offset,0
|
||||
endm
|
||||
|
||||
|
||||
save_real_buffer_offset macro arg
|
||||
IFNB <arg>
|
||||
mov ss:&real_buf_offset,arg
|
||||
ELSE
|
||||
mov ss:&real_buf_offset,di
|
||||
ENDIF
|
||||
endm
|
||||
|
||||
|
||||
direction = 0 ; direction flag for autoincr/autdecr
|
||||
real_buffer_stack = 0 ; treat buffer as stack
|
||||
|
||||
buffer_is_stack macro
|
||||
direction = 1
|
||||
endm
|
||||
|
||||
get_real_buffer_stack macro
|
||||
mov bx,ss:&real_buf_top
|
||||
mov ss:&real_buf_offset,bx
|
||||
direction = 1
|
||||
endm
|
||||
|
||||
get_real_buffer macro
|
||||
les di,dword ptr ss:&real_mode_buffer
|
||||
endm
|
||||
|
||||
buffer_is_buffer macro
|
||||
direction = 0
|
||||
endm
|
||||
|
||||
get_real_buffer_top macro reg
|
||||
mov reg,ss:real_buf_top
|
||||
endm
|
||||
|
||||
get_buffer macro
|
||||
buffer_is_buffer
|
||||
reset_real_buffer_offset
|
||||
get_real_buffer
|
||||
endm
|
||||
|
||||
rls_buffer macro
|
||||
reset_real_buffer_offset
|
||||
endm
|
|
@ -0,0 +1,850 @@
|
|||
; =====> ZIO.ASM
|
||||
;****************************************
|
||||
;* TIPC Scheme Runtime Support *
|
||||
;* File IO - MS-DOS Version 2.1 *
|
||||
;* *
|
||||
;* (C) Copyright 1985 by Texas *
|
||||
;* Instruments Incorporated. *
|
||||
;* All rights reserved. *
|
||||
;* *
|
||||
;* Date Written: 21 January 1985 *
|
||||
;* Last Modification: 26 September 1986 *
|
||||
;****************************************
|
||||
page 60,132
|
||||
include scheme.equ
|
||||
include pcmake.equ
|
||||
|
||||
MSDOS equ 021h
|
||||
TI_CRT equ 049h
|
||||
IBM_CRT equ 010h
|
||||
TI_KEYBD equ 04Ah
|
||||
IBM_KEYB equ 016h
|
||||
|
||||
MAX_COLS equ 80
|
||||
MAX_ROWS equ 25
|
||||
|
||||
CURSMASK equ 10011111b ; The zeros are the bits that disable cursor
|
||||
NOCURSOR equ 00100000b ; byte mask to disable cursor
|
||||
|
||||
DGROUP group data
|
||||
data segment word public 'DATA'
|
||||
assume DS:DGROUP
|
||||
public zapcurs,curs_sav, ega_col, ega_row
|
||||
|
||||
zapcurs dw 0 ; for disabling cursor altogether
|
||||
curs_sav dw 400Ch ; For saving the cursor size when it's
|
||||
; disabled. Default value just in case...
|
||||
|
||||
ega_col db ?
|
||||
ega_row db ?
|
||||
c_row dw ?
|
||||
c_col dw ?
|
||||
c_len dw ?
|
||||
|
||||
banka dw 0a000h
|
||||
|
||||
sav_di dw ?
|
||||
|
||||
extrn vid_mode:word
|
||||
extrn cur_off:byte
|
||||
extrn char_hgt:word
|
||||
|
||||
data ends
|
||||
|
||||
XGROUP group progx
|
||||
progx segment word public 'progx'
|
||||
assume CS:XGROUP
|
||||
extrn z%border:far ; border drawer
|
||||
extrn crt_dsr:far ; use machine appropriate VIDEO interrupt
|
||||
extrn save%scr:far ; save screen
|
||||
extrn rest%scr:far ; restore screen
|
||||
|
||||
extrn ega_curs:far ; display an ega cursor
|
||||
extrn enable:far ; part of the ega cursor routine
|
||||
|
||||
;************************************************************************
|
||||
;* Generate a Bell Character *
|
||||
;* *
|
||||
;* Purpose: To generate a "bell character" (i.e., make a noise) to *
|
||||
;* simulate the effect of outputting a bell character *
|
||||
;* (control-G) in the output stream. *
|
||||
;* *
|
||||
;* Calling Sequence: zbell(); *
|
||||
;* *
|
||||
;* Input Parameters: None. *
|
||||
;* *
|
||||
;* Output Parameters: None. *
|
||||
;* *
|
||||
;************************************************************************
|
||||
public zbell
|
||||
zbell proc far
|
||||
cmp DGROUP:PC_MAKE,TIPC
|
||||
jne zbmbell
|
||||
zbwait: mov AH,1 ; Get speaker status
|
||||
int 48h
|
||||
jnz zbwait ; wait for bell to turn off
|
||||
mov AH,2 ; Set speaker frequency
|
||||
mov CX,1563 ; Value for 1.25MHz/800Hz (system beep)
|
||||
int 48h
|
||||
mov AX,000Ah ; Turn speaker on for AL*25-ms. 0Ah = .25-sec
|
||||
int 48h
|
||||
ret ; return to caller
|
||||
;
|
||||
zbmbell: mov BX,080h ; ****Copied from IBM-PC/XT BIOS listing****
|
||||
in AL,61h
|
||||
push AX ; Save
|
||||
beep_cycle: and AL,0FCh ; Turn off timer gate and speaker data
|
||||
out 61h,AL ; output to control
|
||||
mov CX,48h ; Half cycle time for TONE
|
||||
here: loop here ; speaker off
|
||||
or AL,2 ; Turn speaker on
|
||||
out 61h,AL
|
||||
mov CX,48h
|
||||
here2: loop here2
|
||||
dec BX ; Decrease cycle count
|
||||
jnz beep_cycle
|
||||
pop AX
|
||||
out 61h,AL
|
||||
ret
|
||||
zbell endp
|
||||
|
||||
public zch_rdy
|
||||
zch_rdy proc far
|
||||
|
||||
; IFDEF extmem ; Kludge to fix hanging keyboard
|
||||
; mov AL,0AEh ; Ensure keyboard enabled
|
||||
; out 64h,AL ; Output to 8042 controller
|
||||
; ENDIF
|
||||
|
||||
mov AH,01h ; load "check keyboard status" function code
|
||||
cmp pc_make,TIPC ; TI or IBM flavored PC?
|
||||
jne zch_IBM
|
||||
int TI_KEYBD ; issue TI keyboard DSR service call
|
||||
jz zch_no ; is character buffered? if not, jump
|
||||
zch_yes: xor AH,AH ; clear high order byte of AX
|
||||
cmp AL,0 ; test next character to be read
|
||||
jne zch_ret ; binary zero? if not, jump
|
||||
mov AX,256 ; if character is 0, make it non-zero
|
||||
zch_ret: ret ; return (true)
|
||||
zch_IBM: int IBM_KEYB ; issue IBM keyboard DSR service call
|
||||
jnz zch_yes ; is character buffered? if so, jump
|
||||
zch_no: xor AX,AX ; set result = false
|
||||
ret ; return (false)
|
||||
zch_rdy endp
|
||||
|
||||
zop_args struc
|
||||
dd ? ; far CS and IP
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
zhandle dw ? ; address of handle
|
||||
zpathnam dw ? ; address of string containing file pathname
|
||||
zmode dw ? ; mode: 0=read, 1=write, 2=read/write
|
||||
zhigh dw ? ; address of high word of file size
|
||||
zlow dw ? ; address of low word of file size
|
||||
zop_args ends
|
||||
|
||||
public z%open
|
||||
z%open proc far
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
mov AH,03Dh ; load function request id
|
||||
mov AL,byte ptr [BP].zmode ; load access code (mode)
|
||||
mov DX,[BP].zpathnam ; load pointer to pathname
|
||||
int MSDOS ; issue open request
|
||||
jc zop_ret ; if error, jump
|
||||
mov BX,[BP].zhandle ; load address of handle
|
||||
mov [BX],AX ; and store returned handle value
|
||||
;
|
||||
push AX ; save file handle
|
||||
mov BX,AX ; set bx to file handle
|
||||
xor CX,CX
|
||||
xor DX,DX
|
||||
mov AX,4202h ; poisition file pointer at eof
|
||||
int MSDOS
|
||||
;
|
||||
mov BX,[BP].zhigh ; load address of hsize
|
||||
mov [BX],DX ; and store returned hsize value
|
||||
mov BX,[BP].zlow ; load address of lsize
|
||||
mov [BX],AX ; and store returned lsize value
|
||||
;
|
||||
pop BX ; retrieve file handle
|
||||
xor CX,CX
|
||||
xor DX,DX
|
||||
mov AX,4200h ; reset file pointer to begining of file
|
||||
int MSDOS
|
||||
;
|
||||
xor AX,AX ; set return code for normal return
|
||||
zop_ret: pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
z%open endp
|
||||
|
||||
public z%create
|
||||
z%create proc far
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
mov AH,03Ch ; load function request id
|
||||
mov DX,[BP].zpathnam ; load pointer to pathname
|
||||
mov CX,020h ; create with "archive" attribute
|
||||
int MSDOS ; issue create request
|
||||
jc zcr_ret ; if error, jump
|
||||
mov BX,[BP].zhandle ; load address of handle
|
||||
mov [BX],AX ; and store returned handle value
|
||||
xor AX,AX ; set return code for normal return
|
||||
zcr_ret: pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
z%create endp
|
||||
|
||||
public z%close
|
||||
z%close proc far
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
mov AH,03Eh ; load function request id
|
||||
mov BX,[BP].zhandle ; load handle of file to close
|
||||
int MSDOS ; issue close request
|
||||
jc zcl_ret ; if error, jump
|
||||
xor AX,AX ; set return code for normal return
|
||||
zcl_ret: pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
z%close endp
|
||||
|
||||
zrw_args struc
|
||||
dd ? ; far cs and ip
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
dw ? ; zhandle (use previous equate)
|
||||
zbuffer dw ? ; input/output buffer
|
||||
zlength dw ? ; address of length value
|
||||
zrw_args ends
|
||||
|
||||
public z%read
|
||||
z%read proc far
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
mov AH,03Fh ; load function request id
|
||||
mov DX,[BP].zbuffer ; load address of input buffer
|
||||
mov BX,[BP].zlength ; load address of length value
|
||||
mov CX,[BX] ; then load length for read
|
||||
mov BX,[BP].zhandle ; load file's handle
|
||||
int MSDOS ; issue create request
|
||||
jc zrd_ret ; if error, jump
|
||||
mov BX,[BP].zlength ; load address of length parameter
|
||||
mov [BX],AX ; and store number of characters read
|
||||
xor AX,AX ; set return code for normal return
|
||||
zrd_ret: pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
z%read endp
|
||||
|
||||
public z%write
|
||||
z%write proc far
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
mov AH,040h ; load function request id
|
||||
mov DX,[BP].zbuffer ; load address of input buffer
|
||||
mov BX,[BP].zlength ; load address of length value
|
||||
mov CX,[BX] ; then load length for write
|
||||
mov BX,[BP].zhandle ; load file's handle
|
||||
int MSDOS ; issue write request
|
||||
jc zwr_ret ; if error, jump
|
||||
mov BX,[BP].zlength ; load address of length parameter
|
||||
mov [BX],AX ; and store number of characters written
|
||||
xor AX,AX ; set return code for normal return
|
||||
zwr_ret: pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
z%write endp
|
||||
|
||||
strd struc
|
||||
dd ? ; far cs and ip
|
||||
dw ?,? ;Caller's BP, Return address
|
||||
strdpg dw ? ;Page, displacement of port
|
||||
strdds dw ?
|
||||
strdbuf dw ? ;Buffer address
|
||||
strdlen dw ? ;Length address
|
||||
strd ends
|
||||
public string%rd
|
||||
string%rd proc far
|
||||
push BP
|
||||
mov BP,SP
|
||||
push DS ;Save caller's DS, ES
|
||||
mov AX,ES ; (and make AX nonzero as well)
|
||||
mov BX,[BP].strdlen ;Load CX with number of chars to transfer
|
||||
mov CX,[BX]
|
||||
mov DI,[BP].strdpg ;Get port page
|
||||
mov DX,DI ; and save for later
|
||||
%LoadPage DS,DI ;Get para address
|
||||
mov DI,[BP].strdds ;DS:DI point to port
|
||||
mov SI,word ptr[DI+car].pt_ptr ;Point DS:SI to string
|
||||
mov BL,[DI+car_page].pt_ptr
|
||||
xor BH,BH
|
||||
%LoadPage DS,BX
|
||||
;;; mov DS,ES:pagetabl+[BX]
|
||||
cmp byte ptr[SI],STRTYPE ;Is this a string?
|
||||
jne nostr ;Jump if not (error)
|
||||
mov BX,[SI].str_len ;Else fetch string length
|
||||
cmp BX,0 ;;; check for small string
|
||||
jge strn_01
|
||||
add BX,BLK_OVHD+PTRSIZE
|
||||
strn_01: %LoadPage ES,DX ;Restore ptr to port
|
||||
mov DX,ES:[DI].pt_ullin ;Fetch position within string
|
||||
sub BX,DX ;Set BX to # of chars left
|
||||
jns notpast ;If not negative, skip
|
||||
xor BX,BX ;Set # of chars left to 0
|
||||
notpast: cmp BX,CX ;Set CX to # of chars left or maximum
|
||||
jae max ; called for, whichever is smaller
|
||||
mov CX,BX
|
||||
max: add SI,DX ;Adjust SI into string
|
||||
add DX,CX ;Reset pointer into string
|
||||
mov ES:[DI].pt_ullin,DX
|
||||
mov ES,AX ;Restore C's ES
|
||||
mov DI,[BP].strdbuf ;Point DI to buffer
|
||||
xor AX,AX ;Prepare to return 0 (all's well)
|
||||
jmp short storlen ;Store # of chars
|
||||
nostr: xor CX,CX ;When not a string, move no chars
|
||||
storlen: mov BX,[BP].strdlen ;Set LENGTH to # of chars read
|
||||
mov ES:[BX],CX
|
||||
rep movsb ;Transfer bytes
|
||||
pop DS ;Restore caller's DS
|
||||
pop BP
|
||||
ret
|
||||
string%rd endp
|
||||
|
||||
;************************************************************************
|
||||
;* Buffered Keyboard Input *
|
||||
;* *
|
||||
;* Calling Sequence: ch = getch(); *
|
||||
;* where ch - the character read from the keyboard *
|
||||
;************************************************************************
|
||||
public get%ch
|
||||
get%ch proc far
|
||||
|
||||
; IFDEF extmem ; Kludge to fix hanging keyboard
|
||||
; mov AL,0AEh ; Ensure keyboard enabled
|
||||
; out 64h,AL ; Output to 8042 controller
|
||||
; ENDIF
|
||||
|
||||
mov AH,07h ; function code = Direct Console Input
|
||||
int MSDOS ; do it
|
||||
xor AH,AH ; clear the high order byte
|
||||
ret ; return to caller
|
||||
get%ch endp
|
||||
|
||||
z%ega proc far
|
||||
|
||||
mov AX,banka
|
||||
mov ES,AX ; set ES to the video plane
|
||||
|
||||
mov AX,c_row ; set AX to the row
|
||||
mul char_hgt ; multiply by the character height
|
||||
mov BX,80 ; multiply by 80 bytes per line
|
||||
mul BX
|
||||
add AX,c_col ; add in the starting column
|
||||
mov sav_di,AX ; save the starting value
|
||||
xor BX,BX ; use BX as a counter
|
||||
mov DX,c_len ; number of columns to blank
|
||||
|
||||
zc_03: mov CX,DX ; restore counter
|
||||
mov DI,sav_di ; restore index
|
||||
mov AH,0fh
|
||||
call enable ; enable all banks
|
||||
xor AX,AX ; clear AX
|
||||
cld
|
||||
rep stosb
|
||||
|
||||
add sav_di,80 ; next line
|
||||
inc BX ; increment counter
|
||||
cmp BX,char_hgt ; done with this row?
|
||||
jne zc_03
|
||||
|
||||
xor BX,BX ; clear counter
|
||||
dec [BP].zc_nrows ; decrement row count
|
||||
jg zc_03 ; if more rows, loop (jump)
|
||||
ret
|
||||
z%ega endp
|
||||
|
||||
progx ends
|
||||
|
||||
|
||||
PGROUP group prog
|
||||
prog segment byte public 'PROG'
|
||||
assume CS:PGROUP
|
||||
|
||||
;************************************************************************
|
||||
;* Create a File *
|
||||
;* *
|
||||
;* Calling sequence: stat = zcreate(handle, pathname) *
|
||||
;* where: int *handle - location to store handle *
|
||||
;* returned by open request*
|
||||
;* char *pathname - zero terminated string *
|
||||
;* containing the file's *
|
||||
;* pathname *
|
||||
;* int stat - the completion code *
|
||||
;* 0=no errors *
|
||||
;* 3=path not found *
|
||||
;* 4=too many open files *
|
||||
;* 5=access denied *
|
||||
;************************************************************************
|
||||
public zcreate
|
||||
zcreate proc near
|
||||
call z%create
|
||||
ret ; return
|
||||
zcreate endp
|
||||
|
||||
;************************************************************************
|
||||
;* Open a File *
|
||||
;* *
|
||||
;* Calling sequence: stat = zopen(handle, pathname, access_code) *
|
||||
;* where: int *handle - location to store handle *
|
||||
;* returned by open request*
|
||||
;* char *pathname - zero terminated string *
|
||||
;* containing the file's *
|
||||
;* pathname *
|
||||
;* int access_code - 0=read, 1=write, *
|
||||
;* 2=read and write *
|
||||
;* int stat - the completion code *
|
||||
;* 0=no errors *
|
||||
;* 2=file not found *
|
||||
;* 4=too many open files *
|
||||
;* 5=access denied *
|
||||
;* 12=invalid access *
|
||||
;************************************************************************
|
||||
public zopen
|
||||
zopen proc near
|
||||
call z%open
|
||||
ret ; return
|
||||
zopen endp
|
||||
|
||||
;************************************************************************
|
||||
;* Close a File *
|
||||
;* *
|
||||
;* Calling sequence: stat = zclose(handle) *
|
||||
;* where: int handle - handle returned by open *
|
||||
;* request *
|
||||
;* int stat - the completion code *
|
||||
;* 0=no errors *
|
||||
;* 6=invalid handle *
|
||||
;************************************************************************
|
||||
public zclose
|
||||
zclose proc near
|
||||
call z%close
|
||||
ret ; return
|
||||
zclose endp
|
||||
|
||||
;************************************************************************
|
||||
;* Read From a File *
|
||||
;* *
|
||||
;* Calling sequence: stat = zread(handle, buffer, length) *
|
||||
;* where: int handle - handle returned by open *
|
||||
;* request *
|
||||
;* char *buffer - address of character *
|
||||
;* buffer into which data *
|
||||
;* is to be read *
|
||||
;* int *length - on input, the maximum *
|
||||
;* number of characters *
|
||||
;* which the buffer will *
|
||||
;* hold. On output, the *
|
||||
;* number of characters *
|
||||
;* actually read. Note: *
|
||||
;* a return value of zero *
|
||||
;* characters read *
|
||||
;* indicates end of file. *
|
||||
;* int stat - the completion code *
|
||||
;* 0=no errors *
|
||||
;* 5=access denied *
|
||||
;* 6=invalid handle *
|
||||
;************************************************************************
|
||||
|
||||
public zread
|
||||
zread proc near
|
||||
call z%read
|
||||
ret ; return
|
||||
zread endp
|
||||
|
||||
;************************************************************************
|
||||
;* Write to a File *
|
||||
;* *
|
||||
;* Calling sequence: stat = zwrite(handle, buffer, length) *
|
||||
;* where: int handle - handle returned by open *
|
||||
;* char *buffer - address of character *
|
||||
;* buffer from which data *
|
||||
;* is to be written *
|
||||
;* int *length - on input, the number of *
|
||||
;* characters to write. *
|
||||
;* The actual number of *
|
||||
;* characters which were *
|
||||
;* written is returned in *
|
||||
;* "length" *
|
||||
;* int stat - the completion code *
|
||||
;* 0=no errors *
|
||||
;* 5=access denied *
|
||||
;* 6=invalid handle *
|
||||
;************************************************************************
|
||||
public zwrite
|
||||
zwrite proc near
|
||||
call z%write
|
||||
ret ; return
|
||||
zwrite endp
|
||||
|
||||
;************************************************************************
|
||||
;* Clear a Window *
|
||||
;************************************************************************
|
||||
zc_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
zc_row dw ? ; upper left hand corner row number
|
||||
zc_col dw ? ; upper left hand corner column number
|
||||
zc_nrows dw ? ; number of rows
|
||||
zc_len dw ? ; line length (number of characters)
|
||||
zc_attrib dw ? ; character attributes
|
||||
zc_args ends
|
||||
|
||||
public zclear
|
||||
zclear proc near
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
push ES
|
||||
push DI
|
||||
push AX
|
||||
push BX
|
||||
push CX
|
||||
push DX
|
||||
; Put cursor at beginning of next row
|
||||
zc_loop: mov DL,byte ptr [BP].zc_row ; load current row number
|
||||
mov DH,byte ptr [BP].zc_col ; load starting column number
|
||||
xor BH,BH ; page number (0 if in graphics mode)
|
||||
mov AH,02H ; load "put cursor" code
|
||||
call crt_dsr ; position the cursor
|
||||
; Write line of blanks at current cursor position
|
||||
mov AX,0920h ; load write char/attr code + blank (= 20h)
|
||||
xor BH,BH ; (for IBM-PC BH=display page #)
|
||||
mov BL,byte ptr [BP].zc_attrib ; load attribute flag
|
||||
cmp vid_mode,14 ; IBM EGA modes?
|
||||
jl zc_01
|
||||
cmp BL,87h ; attribute is rv white?
|
||||
jne zc_22
|
||||
mov AX,09dbh ; use the block character not the blank
|
||||
and BL,7fh ; strip off the xor bit
|
||||
zc_01: mov CX,[BP].zc_len ; load number of times to write the blank
|
||||
call crt_dsr ; perform the write
|
||||
; Increment row number, decrement row count, test, loop
|
||||
inc [BP].zc_row ; increment row number
|
||||
dec [BP].zc_nrows ; decrement row count
|
||||
jg zc_loop ; if more rows, loop (jump)
|
||||
; Return to caller
|
||||
zc_end: pop DX
|
||||
pop CX
|
||||
pop BX
|
||||
pop AX
|
||||
pop DI
|
||||
pop ES
|
||||
pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
|
||||
; clear out the line by writing directly to the graphics planes
|
||||
zc_22: mov AX,[BP].zc_row ; set AX to the row
|
||||
mov c_row,AX
|
||||
mov AX,[BP].zc_col ; add in the starting column
|
||||
mov c_col,AX
|
||||
mov AX,[BP].zc_len ; number of columns to blank
|
||||
mov c_len,AX
|
||||
call z%ega ; restore counter
|
||||
|
||||
jmp zc_end ; return
|
||||
|
||||
zclear endp
|
||||
|
||||
;************************************************************************
|
||||
;* Draw Border *
|
||||
;************************************************************************
|
||||
zb_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
zb_line dw ? ; upper left corner line number
|
||||
zb_col dw ? ; upper left corner column number
|
||||
zb_nlines dw ? ; number of lines
|
||||
zb_ncols dw ? ; number of columns
|
||||
zb_battr dw ? ; border attributes
|
||||
zb_label dw ? ; pointer to label text
|
||||
zb_args ends
|
||||
|
||||
public zborder
|
||||
zborder proc near
|
||||
call z%border
|
||||
ret
|
||||
zborder endp
|
||||
|
||||
;************************************************************************
|
||||
;* Link to Save Screen Support *
|
||||
;************************************************************************
|
||||
public save_scr
|
||||
save_scr proc near
|
||||
call save%scr
|
||||
ret
|
||||
save_scr endp
|
||||
|
||||
;************************************************************************
|
||||
;* Link to Restore Screen Support *
|
||||
;************************************************************************
|
||||
public rest_scr
|
||||
rest_scr proc near
|
||||
call rest%scr
|
||||
ret
|
||||
rest_scr endp
|
||||
|
||||
;************************************************************************
|
||||
;* Cursor Off *
|
||||
;************************************************************************
|
||||
public zcuroff
|
||||
zcuroff proc near
|
||||
|
||||
call ega_curs
|
||||
|
||||
mov AH,03
|
||||
xor BH,BH ; IBM page number/must be 0 for graphics mode
|
||||
call crt_dsr ; get the cursor position/mode
|
||||
|
||||
cmp zapcurs,0
|
||||
jne zcoff_01
|
||||
mov curs_sav,CX ; save it for restoration
|
||||
zcoff_01:
|
||||
and CH,CURSMASK ; mask off bits to select cursor type
|
||||
or CH,NOCURSOR ; disables cursor (turns it off)
|
||||
mov AH,01h ; load "set cursor type" code
|
||||
call crt_dsr ; turn the cursor off
|
||||
ret ; return to caller
|
||||
zcuroff endp
|
||||
|
||||
|
||||
;************************************************************************
|
||||
;* Cursor On *
|
||||
;************************************************************************
|
||||
public zcuron
|
||||
zcuron proc near
|
||||
|
||||
cmp zapcurs,0 ; if cursor disabled
|
||||
jne zcon_ret ; then return
|
||||
|
||||
mov CX,curs_sav ; attributes for cursor on
|
||||
mov AH,01h ; load "set cursor type" code
|
||||
call crt_dsr ; turn the cursor on
|
||||
zcon_ret:
|
||||
ret ; return to caller
|
||||
zcuron endp
|
||||
|
||||
;************************************************************************
|
||||
;* Put Cursor *
|
||||
;************************************************************************
|
||||
public zputcur
|
||||
zputcur proc near
|
||||
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
; put cursor in desired location
|
||||
mov DH,byte ptr [BP].zc_col ; load column number
|
||||
mov ega_col,DH
|
||||
mov DL,byte ptr [BP].zc_row ; load row number
|
||||
mov ega_row,DL
|
||||
xor BH,BH ; IBMism: page number (0 if in graphics mode)
|
||||
mov AH,02H ; load "put cursor" code
|
||||
call crt_dsr ; position the cursor (DSR swaps DH/DL)
|
||||
|
||||
call ega_curs ; display cursor for ega mode
|
||||
|
||||
; Return to caller
|
||||
pop BP ; restore caller's BP
|
||||
ret ; return
|
||||
zputcur endp
|
||||
|
||||
;************************************************************************
|
||||
;* Scroll a Window *
|
||||
;************************************************************************
|
||||
zs_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
zs_line dw ? ; upper left hand corner line number
|
||||
zs_col dw ? ; upper left hand corner column number
|
||||
zs_nline dw ? ; number of lines
|
||||
zs_ncols dw ? ; number of columns
|
||||
zs_attr dw ? ; text attributes (used for blanking)
|
||||
zs_args ends
|
||||
|
||||
public zscroll
|
||||
zscroll proc near
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
push AX
|
||||
push BX
|
||||
push CX
|
||||
push DX
|
||||
; scroll window's text up one line
|
||||
mov CL,byte ptr [BP].zs_nline ; load number of lines
|
||||
dec CL ; decrease number of lines by one
|
||||
jz blank1 ; Jump if scrolling 1-line and just blank it
|
||||
mov CH,byte ptr [BP].zs_ncols ; load number of columns
|
||||
mov DL,byte ptr [BP].zs_line ; load upper left line number
|
||||
mov DH,byte ptr [BP].zs_col ; load upper left column number
|
||||
mov AX,0601h ; load "scroll text" code with no blanking
|
||||
cmp DGROUP:PC_MAKE,TIPC
|
||||
je ti_scrl
|
||||
;;;;;;;;; cmp vid_mode,14
|
||||
;;;;;;;;; jge txt_mod ; treat ega modes as text
|
||||
cmp vid_mode,4 ; Are we in graphics mode?
|
||||
jl txt_mod ; If we are then fix blank fill attributes
|
||||
cmp vid_mode,7 ; so that the bar characters don't show up
|
||||
je txt_mod
|
||||
xor BH,BH ; zero attribute for fill blanks
|
||||
jmp short rite_atr
|
||||
txt_mod: mov BH,byte ptr [BP].zs_attr ; Blanked lines' attribute txt mode
|
||||
rite_atr: xchg CX,DX ; CX=Upper left corner
|
||||
xchg CH,CL ; Row,column instead of TI's column,row
|
||||
xchg DH,DL ; ditto
|
||||
add DX,CX ; DX=Lower right corner
|
||||
dec DL ; adjust column count (0 is first column)
|
||||
int IBM_CRT
|
||||
jmp short z_quit ; IFF IBM is in graphics mode weird char's
|
||||
; are used for blanks when scrolling. Do
|
||||
; as TIPC does and "manual" blank 'em.
|
||||
;
|
||||
ti_scrl: mov BX,DX ; copy destination coordinates
|
||||
inc DL ; compute source by incrementing line number
|
||||
int TI_CRT ; perform block move
|
||||
; paint the last line of the window with blank of proper attributes
|
||||
blank1: mov DH,byte ptr [BP].zs_col ; load starting column number
|
||||
mov DL,byte ptr [BP].zs_line ; load upper line number
|
||||
add DL,byte ptr [BP].zs_nline ; add the number of lines and
|
||||
dec DL ; subtract offf one
|
||||
mov AH,02h ; load "put cursor" code
|
||||
xor BH,BH ; IBMism
|
||||
call crt_dsr ; position cursor for write
|
||||
mov AX,0920h ; load "write char/attr" code, write a blank
|
||||
mov BL,byte ptr [BP].zs_attr ; load attribute bit setting
|
||||
|
||||
cmp vid_mode,14 ; ega mode?
|
||||
jl z_scr01
|
||||
mov BH,BL
|
||||
and BH,80h
|
||||
cmp BH,80h ; reverse video?
|
||||
jne z_scr01
|
||||
mov AX,09dbh ; change for block character
|
||||
and BL,7fh ; strip off xor bit
|
||||
z_scr01: xor BH,BH ; IBMism
|
||||
mov CX,[BP].zs_ncols ; load line length
|
||||
call crt_dsr ; write a line of blanks
|
||||
; return to caller
|
||||
z_quit: pop DX ; restore caller's BP
|
||||
pop CX
|
||||
pop BX
|
||||
pop AX
|
||||
pop BP
|
||||
ret
|
||||
zscroll endp
|
||||
|
||||
;************************************************************************
|
||||
;* Output Character To Window *
|
||||
;************************************************************************
|
||||
zp_args struc
|
||||
dw ? ; caller's BP
|
||||
dw ? ; return address
|
||||
zp_line dw ? ; cursor position - line number
|
||||
zp_col dw ? ; cursor position - column number
|
||||
zp_char dw ? ; character to write
|
||||
zp_attr dw ? ; character's attributes
|
||||
zp_args ends
|
||||
|
||||
public zputc
|
||||
zputc proc near
|
||||
push BP ; save caller's BP
|
||||
mov BP,SP
|
||||
push DX
|
||||
push CX
|
||||
push BX
|
||||
push AX
|
||||
; position cursor for write
|
||||
mov DL,byte ptr [BP].zp_line ; load line number
|
||||
mov DH,byte ptr [BP].zp_col ; load column number
|
||||
xor BH,BH ; IBMism
|
||||
mov AH,02h ; load "put cursor" code
|
||||
call crt_dsr ; positio the cursor
|
||||
|
||||
mov BL,byte ptr [BP].zp_attr ; load its attributes
|
||||
cmp vid_mode,14 ; only attribute for EGA modes is a
|
||||
jl zchar_1 ; simulated reverse video
|
||||
|
||||
mov BH,BL ; save the attribute
|
||||
and BH,80h ; reverse video?
|
||||
jz zchar_1 ; zero indicates bit 8 not set
|
||||
|
||||
zchar_2: and BL,7fh ; strip off high bit
|
||||
mov CX,1 ; character count
|
||||
xor BH,BH ; video page number
|
||||
mov AL,0dbh ; block character
|
||||
mov AH,09h
|
||||
call crt_dsr
|
||||
or BL,80h ; set xor bit
|
||||
; write the characters with attributes
|
||||
zchar_1: mov AL,byte ptr [BP].zp_char ; load the character
|
||||
xor BH,BH ; IBMism
|
||||
mov CX,1 ; repeat count = 1
|
||||
mov AH,09h ; load write char/attribute code
|
||||
call crt_dsr
|
||||
; return to caller
|
||||
pop AX
|
||||
pop BX
|
||||
pop CX
|
||||
pop DX
|
||||
pop BP
|
||||
ret
|
||||
zputc endp
|
||||
|
||||
;************************************************************************
|
||||
;* Buffered Keyboard Input *
|
||||
;* *
|
||||
;* Calling Sequence: ch = getch(); *
|
||||
;* where ch - the character read from the keyboard *
|
||||
;************************************************************************
|
||||
public getch
|
||||
getch proc near
|
||||
call get%ch
|
||||
ret ; return to caller
|
||||
getch endp
|
||||
|
||||
;************************************************************************
|
||||
;* Read characters from a string *
|
||||
;* *
|
||||
;* Calling Sequence: stringrd(page, disp, buffer, &length) *
|
||||
;* where page,disp: location of string-fed port *
|
||||
;* buffer and length are as in ZREAD (see above) *
|
||||
;* *
|
||||
;* Note: The passing parameter `page' is page # *
|
||||
;************************************************************************
|
||||
|
||||
public stringrd
|
||||
stringrd proc near
|
||||
call string%rd
|
||||
ret
|
||||
stringrd endp
|
||||
;***************************************************************************
|
||||
;* Link for routines in PROGX *
|
||||
;***************************************************************************
|
||||
extrn shft_brk:near
|
||||
extrn dos_err:near
|
||||
public shft%brk
|
||||
public dos%err
|
||||
shft%brk proc far
|
||||
call shft_brk ;link to SHF BREAK process
|
||||
ret
|
||||
shft%brk endp
|
||||
|
||||
dos%err proc far
|
||||
call dos_err ;link to DOS fatal error process
|
||||
ret
|
||||
dos%err endp
|
||||
;
|
||||
public char_rdy
|
||||
char_rdy proc near ;our equivalent of Lattice C's kbhit fn
|
||||
call zch_rdy
|
||||
ret
|
||||
char_rdy endp
|
||||
|
||||
prog ends
|
||||
|
||||
end
|
||||
|
Loading…
Reference in New Issue