dev86-0.16.17/ar/0000755000000000000000000000000010174732447013173 5ustar rootroot00000000000000dev86-0.16.17/ar/ar.c0000644000000000000000000014607310003513077013737 0ustar rootroot00000000000000/* ar.c - Archive modify and extract. Copyright (C) 1988, 1990 Free Software Foundation, Inc. ar86 changes by Greg Haerr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #ifdef __STDC__ #include #include #include #include #endif #include #include #include #include #include #include "ar.h" #include "rel_aout.h" #if defined(__BCC__) || defined(__HP_cc) #define HAVE_RENAME #undef HAVE_FSYNC #define SHORT_FILENAME #else #define HAVE_FCHMOD #define HAVE_RENAME #undef HAVE_FSYNC #endif #define HAVE_TRAILING_SLASH_IN_NAME #ifdef __GNUC__ # ifndef alloca # define alloca __builtin_alloca # endif #else # if defined(sparc) || defined(HAVE_ALLOCA_H) # include # endif #endif #ifdef USG #define bcopy(source, dest, size) memcpy((dest), (source), (size)) #define bcmp(a, b, size) memcmp((a), (b), (size)) #define bzero(s, size) memset((s), 0, (size)) #endif /* Locking is normally disabled because fcntl hangs on the Sun and it isn't supported properly across NFS anyway. */ /* This structure is used internally to represent the info on a member of an archive. This is to make it easier to change format. */ struct member_desc { /* Name of member. */ char *name; /* The following fields are stored in the member header as decimal or octal numerals, but in this structure they are stored as machine numbers. */ int mode; /* Protection mode from member header. */ long int date; /* Last modify date as stored in member header. */ unsigned int size; /* Bytes of member's data, from member header. */ int uid, gid; /* UID and GID fields copied from member header. */ unsigned int offset;/* Offset in archive of the header of this member. */ unsigned int data_offset;/* Offset of first data byte of the member. */ /* The next field does not describe where the member was in the old archive, but rather where it will be in the modified archive. It is set up by write_archive. */ unsigned int new_offset; /* Offset of this member in new archive */ /* Symdef data for member. Used only for files being inserted. */ struct symdef *symdefs; unsigned int nsymdefs; /* Number of entries of symdef data. */ unsigned int string_size; /* Size of strings needed by symdef data. */ }; /* Each symbol is recorded by something like this. */ struct symdef { union { unsigned long int stringoffset; char *name; } s; unsigned long int offset; }; /* Nonzero means it's the name of an existing member; position new or moved files with respect to this one. */ char *posname; /* How to use `posname': POS_BEFORE means position before that member. POS_AFTER means position after that member. POS_DEFAULT if position by default; then `posname' should also be zero. */ enum { POS_DEFAULT, POS_BEFORE, POS_AFTER } postype; /* Nonzero means describe each action performed. */ int verbose; /* Nonzero means don't warn about creating the archive file if necessary. */ int silent_create; /* Nonzero means don't replace existing members whose dates are more recent than the corresponding files. */ int newer_only; /* Nonzero means preserve dates of members when extracting them. */ int preserve_dates; /* Operation to be performed. */ #define DELETE 1 #define REPLACE 2 #define PRINT_TABLE 3 #define PRINT_FILES 4 #define EXTRACT 5 #define MOVE 6 #define QUICK_APPEND 7 int operation; /* Name of archive file. */ char *archive; /* Descriptor on which we have locked the original archive file, or -1 if this has not been done. */ int lock_indesc; /* Pointer to tail of `argv', at first subfile name argument, or zero if no such were specified. */ char **files; /* Nonzero means write a __.SYMDEF member into the modified archive. */ int symdef_flag; /* Nonzero means __.SYMDEF member exists in old archive. */ int symdef_exists; /* Nonzero means don't update __.SYMDEF unless the flag was given. */ int ignore_symdef; /* Total number of symdef entries we will have. */ unsigned long int nsymdefs; /* Symdef data from old archive (set up only if we need it) */ struct symdef *old_symdefs; /* Number of symdefs in remaining in old_symdefs. */ unsigned int num_old_symdefs; /* Number of symdefs old_symdefs had when it was read in. */ unsigned long int original_num_symdefs; /* String table from old __.SYMDEF member. */ char *old_strings; /* Size of old_strings */ unsigned long int old_strings_size; /* String table to be written into __.SYMDEF member. */ char *new_strings; /* Size of new_strings */ unsigned long int new_strings_size; /* An archive map is a chain of these structures. Each structure describes one member of the archive. The chain is in the same order as the members are. */ struct mapelt { struct member_desc info; struct mapelt *next; }; struct mapelt *maplast; /* If nonzero, this is the map-element for the __.SYMDEF member and we should update the time of that member just before finishing. */ struct mapelt *symdef_mapelt; /* Header that we wrote for the __.SYMDEF member. */ struct ar_hdr symdef_header; /* Name this program was run with. */ char *program_name; #ifndef __STDC__ char *xmalloc (), *xrealloc (); void free (); void add_to_map (), delete_from_map (); int insert_in_map (); void print_descr (); char *concat (); void scan (); void extract_members (); void extract_member (); void print_contents (); void write_symdef_member (); void read_old_symdefs (); void two_operations (); void usage (), fatal (), error (), error3(), error_with_file (); void perror_with_name (), pfatal_with_name (); void write_archive (); void touch_symdef_member (); void update_symdefs (); void delete_members (), move_members (), replace_members (); void quick_append (); char *basename (); void print_modes (); char *make_tempname (); void copy_out_member (); #define const #else /* Grrr. */ extern void error (char * s1, char * s2); extern void error3 (char * s1, char * s2, char * s3); extern void fatal (char * s1, char * s2); extern void extract_members (void (*function) (struct member_desc member, FILE *istream)); extern void scan (void (*function) (struct member_desc member, FILE *istream), int crflag); extern char *basename (char *path); extern char *concat (const char *s1, const char *s2, const char *s3); extern char *make_tempname (char *name); extern char *xmalloc (unsigned int size); extern char *xrealloc (char *ptr, unsigned int size); extern int filter_symbols (struct nlist *syms, unsigned int symcount); extern int insert_in_map (char *name, struct mapelt *map, struct mapelt *after); extern int main (int argc, char **argv); extern int move_in_map (char *name, struct mapelt *map, struct mapelt *after); extern int read_header_info (struct mapelt *mapelt, int desc, long int offset, long int *syms_offset, unsigned int *syms_size, long int *strs_offset, unsigned int *strs_size); extern struct mapelt *find_mapelt (struct mapelt *map, char *name); extern struct mapelt *find_mapelt_noerror (struct mapelt *map, register char *name); extern struct mapelt *last_mapelt (struct mapelt *map); extern struct mapelt *make_map (int nonexistent_ok); extern struct mapelt *prev_mapelt (struct mapelt *map, struct mapelt *elt); extern void add_to_map (struct member_desc member, FILE * istream); extern void close_archive (void); extern void copy_out_member (struct mapelt *mapelt, int archive_indesc, int outdesc, char *outname); extern void delete_from_map (char *name, struct mapelt *map); extern void delete_members (void); extern void error_with_file (char *string, struct mapelt *mapelt); extern void extract_member (struct member_desc member, FILE *istream); extern void header_from_map (struct ar_hdr *header, struct mapelt *mapelt); extern void lock_for_update (void); extern void make_new_symdefs (struct mapelt *mapelt, int archive_indesc); extern void move_members (void); extern void mywrite (int desc, void *buf, int bytes, char *file); extern void perror_with_name (char *name); extern void pfatal_with_name (char *name); extern void print_contents (struct member_desc member, FILE *istream); extern void print_descr (struct member_desc member, FILE * instream); extern void print_modes (int modes); extern void quick_append (void); extern void read_old_symdefs (struct mapelt *map, int archive_indesc); extern void replace_members (void); extern void touch_symdef_member (int outdesc, char *outname); extern void two_operations (void); extern void update_symdefs (struct mapelt *map, int archive_indesc); extern void usage (char *s1, int val); extern void write_archive (struct mapelt *map, int appendflag); extern void write_symdef_member (struct mapelt *mapelt, struct mapelt *map, int outdesc, char *outname); #endif /* Output BYTES of data at BUF to the descriptor DESC. FILE is the name of the file (for error messages). */ void mywrite (desc, pbuf, bytes, file) int desc; void *pbuf; int bytes; char *file; { register int val; register char * buf = pbuf; while (bytes > 0) { val = write (desc, buf, bytes); if (val <= 0) perror_with_name (file); buf += val; bytes -= val; } } int main (argc, argv) int argc; char **argv; { int i; operation = 0; verbose = 0; newer_only = 0; silent_create = 0; posname = 0; postype = POS_DEFAULT; preserve_dates = 0; symdef_flag = 0; symdef_exists = 0; ignore_symdef = 0; symdef_mapelt = 0; files = 0; lock_indesc = -1; program_name = argv[0]; if (argc < 2) usage ("too few command arguments", 0); { char *key = argv[1]; char *p = key; char c; if (*p == '-') p++; while ((c = *p++)) { switch (c) { case 'a': postype = POS_AFTER; break; case 'b': postype = POS_BEFORE; break; case 'c': silent_create = 1; break; case 'd': if (operation) two_operations (); operation = DELETE; break; case 'i': postype = POS_BEFORE; break; case 'l': break; case 'm': if (operation) two_operations (); operation = MOVE; break; case 'o': preserve_dates = 1; break; case 'p': if (operation) two_operations (); operation = PRINT_FILES; break; case 'q': if (operation) two_operations (); operation = QUICK_APPEND; break; case 'r': if (operation) two_operations (); operation = REPLACE; break; case 's': symdef_flag = 1; break; case 't': if (operation) two_operations (); operation = PRINT_TABLE; break; case 'u': operation = REPLACE; newer_only = 1; break; case 'v': verbose = 1; break; case 'x': if (operation) two_operations (); operation = EXTRACT; break; } } } if (operation == 0 && symdef_flag) operation = REPLACE; if (operation == 0) usage ("no operation specified", 0); i = 2; if (postype != POS_DEFAULT) { if (i < argc) posname = argv[i++]; else usage ("no position operand", 0); } if (i >= argc) usage ("no archive specified", 0); archive = argv[i++]; if (i < argc) { files = &argv[i]; while (i < argc) if (!strcmp (argv[i++], "__.SYMDEF")) { ignore_symdef = 1; break; } } switch (operation) { case EXTRACT: extract_members (extract_member); break; case PRINT_TABLE: extract_members (print_descr); break; case PRINT_FILES: extract_members (print_contents); break; case DELETE: if (files != 0) delete_members (); break; case MOVE: if (files != 0) move_members (); break; case REPLACE: if (files != 0 || symdef_flag) replace_members (); break; case QUICK_APPEND: if (files != 0) quick_append (); break; default: usage ("invalid operation %d", operation); } exit (0); } void two_operations () { usage ("two different operation switches specified", 0); } void scan (function, crflag) #ifdef __STDC__ void (*function) (struct member_desc member, FILE *istream); #else void (*function) (); #endif int crflag; { FILE *arcstream = fopen (archive, "r"); if (arcstream == 0 && crflag) /* Creation-warning, if desired, will happen later. */ return; if (arcstream == 0) { perror_with_name (archive); exit (1); } { char buf[SARMAG]; int nread = fread (buf, 1, SARMAG, arcstream); if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG)) fatal ("file %s not a valid archive", archive); } /* Now find the members one by one. */ { int member_offset = SARMAG; while (1) { int nread; struct ar_hdr member_header; struct member_desc member_desc; char name [1 + sizeof member_header.ar_name]; if (fseek (arcstream, member_offset, 0) < 0) perror_with_name (archive); nread = fread (&member_header, 1, sizeof (struct ar_hdr), arcstream); if (nread == 0) /* No data left means end of file; that is OK. */ break; if (nread != sizeof (member_header) || bcmp (member_header.ar_fmag, ARFMAG, 2)) fatal ("file %s not a valid archive", archive); bcopy (member_header.ar_name, name, sizeof member_header.ar_name); { char *p = name + sizeof member_header.ar_name; *p = '\0'; while (p > name && *--p == ' ') *p = '\0'; #if defined(USG) || defined(HAVE_TRAILING_SLASH_IN_NAME) if (*p == '/') /* Since V.2, names are terminated with '/' */ *p = '\0'; #endif } member_desc.name = name; sscanf (member_header.ar_mode, "%o", &member_desc.mode); member_desc.date = atoi (member_header.ar_date); member_desc.size = atoi (member_header.ar_size); member_desc.uid = atoi (member_header.ar_uid); member_desc.gid = atoi (member_header.ar_gid); member_desc.offset = member_offset; member_desc.data_offset = member_offset + sizeof (member_header); member_desc.new_offset = 0; member_desc.symdefs = 0; member_desc.nsymdefs = 0; member_desc.string_size = 0; if (!ignore_symdef && !strcmp (name, "__.SYMDEF")) symdef_exists = 1; function (member_desc, arcstream); member_offset += sizeof (member_header) + member_desc.size; if (member_offset & 1) ++member_offset; } } fclose (arcstream); } void print_descr (member, instream) struct member_desc member; FILE * instream; { char *timestring; if (!verbose) { puts (member.name); return; } print_modes (member.mode); timestring = ctime (&member.date); printf (" %2d/%2d %6d %12.12s %4.4s %s\n", member.uid, member.gid, member.size, timestring + 4, timestring + 20, member.name); } void print_modes (modes) int modes; { putchar (modes & 0400 ? 'r' : '-'); putchar (modes & 0200 ? 'w' : '-'); putchar (modes & 0100 ? 'x' : '-'); putchar (modes & 040 ? 'r' : '-'); putchar (modes & 020 ? 'w' : '-'); putchar (modes & 010 ? 'x' : '-'); putchar (modes & 04 ? 'r' : '-'); putchar (modes & 02 ? 'w' : '-'); putchar (modes & 01 ? 'x' : '-'); } #define BUFSIZE 1024 void extract_member (member, istream) struct member_desc member; FILE *istream; { int ncopied = 0; FILE *ostream; fseek (istream, member.data_offset, 0); ostream = fopen (member.name, "w"); if (!ostream) { perror_with_name (member.name); return; } if (verbose) printf ("x - %s\n", member.name); while (ncopied < member.size) { char buf [BUFSIZE]; int tocopy = member.size - ncopied; int nread; if (tocopy > BUFSIZE) tocopy = BUFSIZE; nread = fread (buf, 1, tocopy, istream); if (nread != tocopy) fatal ("error reading archive %s", archive); fwrite (buf, 1, nread, ostream); ncopied += tocopy; } #ifdef HAVE_FCHMOD fchmod (fileno (ostream), member.mode); #else chmod (member.name, member.mode); #endif if (ferror (ostream) || fclose (ostream) != 0) error ("%s: I/O error", member.name); if (preserve_dates) { #if defined(USG) || defined(__BCC__) long tv[2]; tv[0] = member.date; tv[1] = member.date; utime (member.name, tv); #else struct timeval tv[2]; tv[0].tv_sec = member.date; tv[0].tv_usec = 0; tv[1].tv_sec = member.date; tv[1].tv_usec = 0; utimes (member.name, tv); #endif } } void print_contents (member, istream) struct member_desc member; FILE *istream; { int ncopied = 0; fseek (istream, member.data_offset, 0); if (verbose) printf ("\n\n\n", member.name); while (ncopied < member.size) { char buf [BUFSIZE]; int tocopy = member.size - ncopied; int nread; if (tocopy > BUFSIZE) tocopy = BUFSIZE; nread = fread (buf, 1, tocopy, istream); if (nread != tocopy) fatal ("file %s not a valid archive", archive); fwrite (buf, 1, nread, stdout); ncopied += tocopy; } } /* Make a map of the existing members of the archive: their names, positions and sizes. */ /* If `nonexistent_ok' is nonzero, just return 0 for an archive that does not exist. This will cause the ordinary supersede procedure to create a new archive. */ struct mapelt * make_map (nonexistent_ok) int nonexistent_ok; { struct mapelt mapstart; mapstart.next = 0; maplast = &mapstart; scan (add_to_map, nonexistent_ok); return mapstart.next; } void add_to_map (member, istream) struct member_desc member; FILE * istream; { struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt)); mapelt->info = member; mapelt->info.name = concat (mapelt->info.name, "", ""); maplast->next = mapelt; mapelt->next = 0; maplast = mapelt; } /* Return the last element of the specified map. */ struct mapelt * last_mapelt (map) struct mapelt *map; { struct mapelt *tail = map; while (tail->next) tail = tail->next; return tail; } /* Return the element of the specified map which precedes elt. */ struct mapelt * prev_mapelt (map, elt) struct mapelt *map, *elt; { struct mapelt *tail = map; while (tail->next && tail->next != elt) tail = tail->next; if (tail->next) return tail; return 0; } /* Return the element of the specified map which has the specified name. */ struct mapelt * find_mapelt_noerror (map, name) struct mapelt *map; register char *name; { register struct mapelt *tail; unsigned int len; int dot_o; name = basename (name); len = strlen (name); dot_o = name[len - 2] == '.' && name[len - 1] == 'o'; for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) continue; if (!strncmp (tail->info.name, name, 13)) { unsigned int eltlen = strlen (tail->info.name); if (len <= 13 || eltlen <= 13) return tail; else { char *p = tail->info.name + 13; if (dot_o && p[0] == '.' && p[1] == 'o' && p[2] == '\0') return tail; else if (!strncmp (p, name + 13, (len > eltlen ? len : eltlen) - 13)) return tail; } } } return 0; } struct mapelt * find_mapelt (map, name) struct mapelt *map; char *name; { register struct mapelt *found = find_mapelt_noerror (map, name); if (found == 0) error ("no member named `%s'", name); return found; } /* Before looking at the archive, if we are going to update it based on looking at its current contents, make an exclusive lock on it. The lock is released when `write_archive' is called. */ void lock_for_update () { /* Open the existing archive file; if that fails, create an empty one. */ lock_indesc = open (archive, O_RDWR, 0); if (lock_indesc < 0) { int outdesc; if (!silent_create) printf ("Creating archive file `%s'\n", archive); outdesc = open (archive, O_WRONLY | O_APPEND | O_CREAT, 0666); if (outdesc < 0) pfatal_with_name (archive); mywrite (outdesc, ARMAG, SARMAG, archive); close (outdesc); /* Now we had better be able to open for update! */ lock_indesc = open (archive, O_RDWR, 0); if (lock_indesc < 0) { unlink (archive); pfatal_with_name (archive); } } #ifdef LOCKS /* Lock the old file so that it won't be updated by two programs at once. This uses the fcntl locking facility found on Sun systems which is also in POSIX. (Perhaps it comes from sysV.) Note that merely reading an archive does not require a lock, because we use `rename' to update the whole file atomically. */ { struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; while (1) { int value = fcntl (lock_indesc, F_SETLKW, &lock); if (value >= 0) break; else if (errno == EINTR) continue; else pfatal_with_name ("locking archive"); } } #endif } /* Unlock archive and close the file descriptor. */ void close_archive () { #ifdef LOCKS { struct flock lock; /* Unlock the old archive. */ lock.l_type = F_UNLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; fcntl (lock_indesc, F_SETLK, &lock); } #endif /* Close the archive. If we renamed a new one, the old one disappears. */ close (lock_indesc); } /* Write a new archive file from a given map. */ /* When a map is used as the pattern for a new archive, each element represents one member to put in it, and the order of elements controls the order of writing. Ordinarily, the element describes a member of the old archive, to be copied into the new one. If the `offset' field of the element's info is 0, then the element describes a file to be copied into the new archive. The `name' field is the file's name. If the `name' field of an element is 0, the element is ignored. This makes it easy to specify deletion of archive members. Every operation that will eventually call `write_archive' should call `lock_for_update' before beginning to do any I/O on the archive file. */ void write_archive (map, appendflag) struct mapelt *map; int appendflag; { char *tempname = make_tempname (archive); int indesc = lock_indesc; int outdesc; char *outname; struct mapelt *tail; /* Now open the output. */ if (!appendflag) { /* Updating an existing archive normally. Write output as TEMPNAME and rename at the end. There can never be two invocations trying to do this at once, because of the lock made on the old archive file. */ outdesc = open (tempname, O_WRONLY | O_CREAT, 0666); if (outdesc < 0) pfatal_with_name (tempname); outname = tempname; mywrite (outdesc, ARMAG, SARMAG, outname); } else { /* Fast-append to existing archive. */ outdesc = open (archive, O_WRONLY | O_APPEND, 0); if (outdesc < 0) pfatal_with_name (archive); outname = archive; } /* If archive has or should have a __.SYMDEF member, compute the contents for it. */ if (symdef_flag || symdef_exists) { if (symdef_exists) read_old_symdefs (map, indesc); else { struct mapelt *this = (struct mapelt *) xmalloc (sizeof (struct mapelt)); this->info.name = "__.SYMDEF"; this->info.offset = SARMAG; this->info.data_offset = SARMAG + sizeof (struct ar_hdr); this->info.new_offset = 0; this->info.date = 0; this->info.size = 0; this->info.uid = 0; this->info.gid = 0; this->info.mode = 0666; this->info.symdefs = 0; this->info.nsymdefs = 0; this->info.string_size = 0; this->next = map; map = this; original_num_symdefs = 0; old_strings_size = 0; } update_symdefs (map, indesc); } /* Copy the members into the output, either from the old archive or from specified files. */ for (tail = map; tail != 0; tail = tail->next) { if ((symdef_flag || symdef_exists) && tail->info.name && !strcmp (tail->info.name, "__.SYMDEF") #if 0 && tail->info.date==0 #endif ) write_symdef_member (tail, map, outdesc, outname); else copy_out_member (tail, indesc, outdesc, outname); } if (symdef_mapelt != 0) { /* Check for members whose data offsets weren't known when the symdef member was first written. */ int doneany = 0; for (tail = map; tail != 0; tail = tail->next) if (tail->info.offset == 0) { /* Fix up the symdefs. */ register unsigned int i; for (i = 0; i < tail->info.nsymdefs; ++i) tail->info.symdefs[i].offset = tail->info.new_offset; doneany = 1; } if (doneany) { /* Some files had bad symdefs; rewrite the symdef member. */ lseek (outdesc, symdef_mapelt->info.offset, 0); write_symdef_member (symdef_mapelt, map, outdesc, outname); } } /* Mark the __.SYMDEF member as up to date. */ if (symdef_mapelt != 0) touch_symdef_member (outdesc, outname); /* Install the new output under the intended name. */ #ifdef HAVE_FSYNC fsync (outdesc); #endif close (outdesc); if (!appendflag) if (rename (tempname, archive)) pfatal_with_name (tempname); close_archive (); } void header_from_map (header, mapelt) struct ar_hdr *header; struct mapelt *mapelt; { unsigned int namelen; char *p; /* Zero the header, then store in the data as text. */ bzero ((char *) header, sizeof (*header)); p = basename (mapelt->info.name); strncpy (header->ar_name, p, sizeof (header->ar_name)); namelen = strlen (p); if (namelen >= sizeof (header->ar_name)) { if (mapelt->info.name[namelen - 2] == '.' && mapelt->info.name[namelen - 1] == 'o') { header->ar_name[sizeof (header->ar_name) - 3] = '.'; header->ar_name[sizeof (header->ar_name) - 2] = 'o'; } header->ar_name[sizeof (header->ar_name) - 1] = '\0'; error3 ("member name `%s' truncated to `%s'", mapelt->info.name, header->ar_name); } #if defined(USG) || defined(HAVE_TRAILING_SLASH_IN_NAME) { /* System V tacks a trailing '/' onto the end of the name */ char *p = header->ar_name; char *end = p + sizeof (header->ar_name); while (p < end && *p) p++; *p = '/'; } #endif sprintf (header->ar_date, "%ld", mapelt->info.date); sprintf (header->ar_size, "%d", mapelt->info.size); sprintf (header->ar_uid, "%d", mapelt->info.uid); sprintf (header->ar_gid, "%d", mapelt->info.gid); sprintf (header->ar_mode, "%o", mapelt->info.mode); strncpy (header->ar_fmag, ARFMAG, sizeof (header->ar_fmag)); /* Change all remaining nulls in the header into spaces. */ { char *end = (char *) &header[1]; register char *p; for (p = (char *) header; p < end; ++p) if (*p == '\0') *p = ' '; } } /* gets just the file part of name */ char * basename (path) char *path; { char *save, *start; for (start = save = path; *path; path++) if (*path == '/') save = path + 1; if (save != start) return save; else return start; } /* writes to file open on OUTDESC with name OUTNAME. */ void copy_out_member (mapelt, archive_indesc, outdesc, outname) struct mapelt *mapelt; int archive_indesc; int outdesc; char *outname; { struct ar_hdr header; int indesc; if (mapelt->info.name == 0) /* This element was cancelled. */ return; header_from_map (&header, mapelt); if (mapelt->info.offset != 0) { indesc = archive_indesc; lseek (indesc, mapelt->info.data_offset, 0); } else { indesc = open (mapelt->info.name, 0, 0); if (indesc < 0) { perror_with_name (mapelt->info.name); return; } } mywrite (outdesc, &header, sizeof (header), outname); if (mapelt->info.data_offset == 0) mapelt->info.data_offset = lseek (outdesc, 0L, 1); { char buf[BUFSIZE]; int tocopy = mapelt->info.size; while (tocopy > 0) { int thistime = tocopy; if (thistime > BUFSIZE) thistime = BUFSIZE; read (indesc, buf, thistime); mywrite (outdesc, buf, thistime, outname); tocopy -= thistime; } } if (indesc != archive_indesc) close (indesc); if (mapelt->info.size & 1) mywrite (outdesc, "\n", 1, outname); } /* Update the time of the __.SYMDEF member; done when we updated that member, just before we close the new archive file. It is open on OUTDESC and its name is OUTNAME. */ void touch_symdef_member (outdesc, outname) int outdesc; char *outname; { struct stat statbuf; int i; /* See what mtime the archive file has as a result of our writing it. */ fstat (outdesc, &statbuf); /* Advance member's time to that time. */ bzero (symdef_header.ar_date, sizeof symdef_header.ar_date); sprintf (symdef_header.ar_date, "%ld", statbuf.st_mtime); for (i = 0; i < sizeof symdef_header.ar_date; i++) if (symdef_header.ar_date[i] == 0) symdef_header.ar_date[i] = ' '; /* Write back this member's header with the new time. */ if (lseek (outdesc, symdef_mapelt->info.new_offset, 0) >= 0) mywrite (outdesc, &symdef_header, sizeof symdef_header, outname); } char * make_tempname (name) char *name; { #if defined(USG) || defined(SHORT_FILENAME) /* sigh. 14 character filenames are *wonderful*, just *wonderful*. */ char *p = basename (name); char *q, *r; if (p != name) { q = concat (name, "", ""); /* get a fresh copy */ r = basename (q); /* r points just after last '/' */ *--r = '\0'; return concat (q, "/t_", p); } else if (strlen (name) >= 14) return concat ("t_", name, ""); else #endif return concat (name, "", "_supersede"); } void delete_members () { struct mapelt *map = make_map (0); struct mapelt mapstart; char **p; mapstart.info.name = 0; mapstart.next = map; map = &mapstart; lock_for_update (); if (files) for (p = files; *p; p++) { /* If user says to delete the __.SYMDEF member, don't make a new one to replace it. */ if (!strcmp (*p, "__.SYMDEF")) symdef_exists = 0; delete_from_map (*p, map); } write_archive (map->next, 0); } void delete_from_map (name, map) char *name; struct mapelt *map; { struct mapelt *this = find_mapelt (map, name); if (!this) return; this->info.name = 0; if (verbose) printf ("d - %s\n", name); } void move_members () { struct mapelt *map = make_map (0); char **p; struct mapelt *after_mapelt = 0; struct mapelt mapstart; struct mapelt *change_map; mapstart.info.name = 0; mapstart.next = map; change_map = &mapstart; lock_for_update (); switch (postype) { case POS_DEFAULT: after_mapelt = last_mapelt (change_map); break; case POS_AFTER: after_mapelt = find_mapelt (map, posname); break; case POS_BEFORE: after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname)); } /* Failure to find specified "before" or "after" member is a fatal error; message has already been printed. */ if (!after_mapelt) exit (1); if (files) for (p = files; *p; p++) { if (move_in_map (*p, change_map, after_mapelt)) after_mapelt = after_mapelt->next; } write_archive (map, 0); } int move_in_map (name, map, after) char *name; struct mapelt *map, *after; { struct mapelt *this = find_mapelt (map, name); struct mapelt *prev; if (!this) return 0; prev = prev_mapelt (map, this); prev->next = this->next; this->next = after->next; after->next = this; return 1; } /* Insert files into the archive. */ void replace_members () { struct mapelt *map = make_map (1); struct mapelt mapstart; struct mapelt *after_mapelt = 0; struct mapelt *change_map; char **p; int changed; mapstart.info.name = 0; mapstart.next = map; change_map = &mapstart; lock_for_update (); switch (postype) { case POS_DEFAULT: after_mapelt = last_mapelt (change_map); break; case POS_AFTER: after_mapelt = find_mapelt (map, posname); break; case POS_BEFORE: after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname)); } /* Failure to find specified "before" or "after" member is a fatal error; the message has already been printed. */ if (after_mapelt == 0) exit (1); changed = 0; if (files != 0) for (p = files; *p != 0; ++p) if (insert_in_map (*p, change_map, after_mapelt)) { after_mapelt = after_mapelt->next; changed = 1; } change_map = change_map->next; if (!changed && (!symdef_flag || symdef_exists)) /* Nothing changed. */ close_archive (); else write_archive (change_map, 0); } /* Handle the "quick insert" operation. */ void quick_append () { struct mapelt *map; struct mapelt *after; struct mapelt mapstart; char **p; mapstart.info.name = 0; mapstart.next = 0; map = &mapstart; after = map; lock_for_update (); /* Insert the specified files into the "map", but is a map of the inserted files only, and starts out empty. */ if (files) for (p = files; *p; p++) { if (insert_in_map (*p, map, after)) after = after->next; } /* Append these files to the end of the existing archive file. */ write_archive (map->next, 1); } /* Insert an entry for name NAME into the map MAP after the map entry AFTER. Delete an old entry for NAME. MAP is assumed to start with a dummy entry, which facilitates insertion at the beginning of the list. Return 1 if successful, 0 if did nothing because file NAME doesn't exist or (optionally) is older. */ int insert_in_map (name, map, after) char *name; struct mapelt *map, *after; { struct mapelt *old = find_mapelt_noerror (map, name); struct mapelt *this; struct stat status; if (stat (name, &status)) { perror_with_name (name); return 0; } if (old && newer_only && status.st_mtime <= old->info.date) return 0; if (old) /* Delete the old one. */ old->info.name = 0; this = (struct mapelt *) xmalloc (sizeof (struct mapelt)); this->info.name = name; this->info.offset = 0; this->info.data_offset = 0; this->info.date = status.st_mtime; this->info.size = status.st_size; this->info.uid = status.st_uid; this->info.gid = status.st_gid; this->info.mode = status.st_mode; /* Always place a __.SYMDEF member first in the archive, regardless of any position specifications. */ if (! strcmp (name, "__.SYMDEF")) this->next = map->next, map->next = this; else this->next = after->next, after->next = this; if (verbose) printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name); return 1; } /* Apply a function to each of the specified members. */ void extract_members (function) #ifdef __STDC__ void (*function) (struct member_desc member, FILE *istream); #else void (*function) (); #endif { struct mapelt *map; FILE *arcstream; char **p; if (!files) { /* Handle case where we want to operate on every member. No need to make a map and search it for this. */ scan (function, 0); return; } arcstream = fopen (archive, "r"); if (!arcstream) fatal ("failure opening archive %s for the second time", archive); map = make_map (0); for (p = files; *p; p++) { struct mapelt *this = find_mapelt (map, *p); if (!this) continue; function (this->info, arcstream); } fclose (arcstream); } /* Write the __.SYMDEF member from data in core. OUTDESC and OUTNAME are descriptor and name of file to write to. */ void write_symdef_member (mapelt, map, outdesc, outname) struct mapelt *mapelt; struct mapelt *map; int outdesc; char *outname; { struct ar_hdr header; struct mapelt *mapptr; unsigned long int symdefs_size; if (mapelt->info.name == 0) /* This element was cancelled. */ return; header_from_map (&header, mapelt); bcopy (&header, &symdef_header, sizeof header); mywrite (outdesc, &header, sizeof (header), outname); /* Write the number of symdefs. */ symdefs_size = nsymdefs * sizeof (struct symdef); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_number_to_chars (symdefs_size, sizeof symdefs_size, (unsigned char *) &symdefs_size); #endif mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname); /* Write symdefs surviving from old archive. */ #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_symdefs_to_chars ((struct md_symdef *) old_symdefs, num_old_symdefs, (unsigned char *) old_symdefs); #endif mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef), outname); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_symdefs ((unsigned char *) old_symdefs, (struct md_symdef *) old_symdefs, num_old_symdefs); #endif /* Write symdefs for new members. */ for (mapptr = map; mapptr != 0; mapptr = mapptr->next) if (mapptr->info.nsymdefs != 0) { #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_symdefs_to_chars ((struct md_symdef *) mapptr->info.symdefs, mapptr->info.nsymdefs, (unsigned char *) mapptr->info.symdefs); #endif write (outdesc, mapptr->info.symdefs, mapptr->info.nsymdefs * sizeof (struct symdef)); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_symdefs ((unsigned char *) mapptr->info.symdefs, (struct md_symdef *) mapptr->info.symdefs, mapptr->info.nsymdefs); #endif } /* Write the string table size. */ #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_number_to_chars (new_strings_size, sizeof new_strings_size, (unsigned char *) &new_strings_size); #endif mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname); #ifdef HOST_TARGET_ENDIANESS_DIFFERS new_strings_size = md_chars_to_number ((unsigned char *) &new_strings_size, sizeof new_strings_size); #endif /* Write the string table. */ mywrite (outdesc, new_strings, new_strings_size, outname); if (mapelt->info.size & 1) mywrite (outdesc, "", 1, outname); } void read_old_symdefs (map, archive_indesc) struct mapelt *map; int archive_indesc; { struct mapelt *mapelt; char *data; int val; int symdefs_size; mapelt = find_mapelt_noerror (map, "__.SYMDEF"); if (!mapelt) abort (); /* Only call here if an old one exists */ data = (char *) xmalloc (mapelt->info.size); lseek (archive_indesc, mapelt->info.data_offset, 0); val = read (archive_indesc, data, mapelt->info.size); #ifdef HOST_TARGET_ENDIANESS_DIFFERS symdefs_size = md_chars_to_number ((unsigned char *) data, sizeof symdefs_size); #else symdefs_size = *(unsigned long int *) data; #endif original_num_symdefs = symdefs_size / sizeof (struct symdef); old_symdefs = (struct symdef *) (data + sizeof (symdefs_size)); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_symdefs ((unsigned char *) old_symdefs, (struct md_symdef *) old_symdefs, original_num_symdefs); #endif old_strings = ((char *) (old_symdefs + original_num_symdefs) + sizeof (symdefs_size)); #ifdef HOST_TARGET_ENDIANESS_DIFFERS old_strings_size = md_chars_to_number ((unsigned char *) (old_symdefs + original_num_symdefs), sizeof old_strings_size); #else old_strings_size = *(unsigned long int *) (old_symdefs + original_num_symdefs); #endif } /* Read various information from the header of an object file. Return 0 for failure or 1 for success. */ int read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset, strs_size) struct mapelt *mapelt; int desc; long int offset; long int *syms_offset; unsigned int *syms_size; long int *strs_offset; unsigned int *strs_size; { struct exec hdr; int len; lseek (desc, offset, 0); #ifdef HEADER_SEEK_FD HEADER_SEEK_FD (desc); #endif len = read (desc, (char *) &hdr, sizeof hdr); #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_hdr ((unsigned char *) &hdr, &hdr); #endif if (len == sizeof hdr && !N_BADMAG(hdr)) { *syms_offset = N_SYMOFF (hdr); *syms_size = hdr.a_syms; *strs_offset = N_STROFF (hdr); lseek (desc, N_STROFF (hdr) + offset, 0); if (read (desc, (char *) strs_size, sizeof *strs_size) != sizeof *strs_size) { error_with_file ("failure reading string table size in ", mapelt); return 0; } #ifdef HOST_TARGET_ENDIANESS_DIFFERS *strs_size = md_chars_to_number ((unsigned char *) strs_size, sizeof *strs_size); #endif return 1; } error_with_file ("bad format (not an object file) in ", mapelt); return 0; } /* Create the info.symdefs for a new member by reading the file it is coming from. */ void make_new_symdefs (mapelt, archive_indesc) struct mapelt *mapelt; int archive_indesc; { int indesc; char *name = mapelt->info.name; long int syms_offset, strs_offset; unsigned int syms_size, strs_size; struct nlist *symbols; int symcount; char *strings; register unsigned int i; unsigned long int offset; if (name == 0) /* Deleted member. */ abort (); if (mapelt->info.offset != 0) { indesc = archive_indesc; lseek (indesc, mapelt->info.data_offset, 0); offset = mapelt->info.data_offset; } else { indesc = open (mapelt->info.name, 0, 0); if (indesc < 0) { perror_with_name (mapelt->info.name); return; } offset = 0; } if (!read_header_info (mapelt, indesc, offset, &syms_offset, &syms_size, &strs_offset, &strs_size)) { if (mapelt->info.offset == 0) close (indesc); return; } /* Number of symbol entries in the file. */ symcount = syms_size / sizeof (struct nlist); /* Allocate temporary space for the symbol entries. */ symbols = (struct nlist *) alloca (syms_size); /* Read in the symbols. */ lseek (indesc, syms_offset + offset, 0); if (read (indesc, (char *) symbols, syms_size) != syms_size) { error_with_file ("premature end of file in symbols of ", mapelt); if (mapelt->info.offset == 0) (void) close (indesc); return; } #ifdef HOST_TARGET_ENDIANESS_DIFFERS md_chars_to_nlist ((unsigned char *) symbols, symbols, symcount); #endif /* The string table size includes the size word. */ if (strs_size < sizeof (strs_size)) { error_with_file ("bad string table size in ", mapelt); if (mapelt->info.offset == 0) (void) close (indesc); return; } strs_size -= sizeof (strs_size); /* Allocate permanent space for the string table. */ strings = (char *) xmalloc (strs_size); /* Read in the strings. */ lseek (indesc, offset + strs_offset + sizeof strs_size, 0); if (read (indesc, strings, strs_size) != strs_size) { error_with_file ("premature end of file in strings of ", mapelt); if (mapelt->info.offset == 0) (void) close (indesc); return; } if (indesc != archive_indesc) (void) close (indesc); /* Discard the symbols we don't want to mention; compact the rest down. */ symcount = filter_symbols (symbols, symcount); mapelt->info.symdefs = (struct symdef *) xmalloc (symcount * sizeof (struct symdef)); mapelt->info.nsymdefs = symcount; mapelt->info.string_size = 0; for (i = 0; i < symcount; ++i) { unsigned long int stroff = symbols[i].n_un.n_strx - sizeof (strs_size); char *symname = strings + stroff; if (stroff > strs_size) { char buf[100]; sprintf (buf, "ridiculous string offset %lu in symbol %u of ", stroff + sizeof (strs_size), i); error_with_file (buf, mapelt); return; } mapelt->info.symdefs[i].s.name = symname; mapelt->info.string_size += strlen (symname) + 1; } } /* Choose which symbol entries to mention in __.SYMDEF; compact them downward to get rid of the rest. Return the number of symbols left. */ int filter_symbols (syms, symcount) struct nlist *syms; unsigned int symcount; { struct nlist *from, *to; struct nlist *end = syms + symcount; for (to = from = syms; from < end; ++from) if ((from->n_type & N_EXT) && (from->n_type != N_EXT || from->n_value != 0)) *to++ = *from; return to - syms; } /* Update the __.SYMDEF data before writing a new archive. */ void update_symdefs (map, archive_indesc) struct mapelt *map; int archive_indesc; { struct mapelt *tail; int pos; register unsigned int i; unsigned int len; struct symdef *s; unsigned long int deleted_strings_size = 0; nsymdefs = original_num_symdefs; num_old_symdefs = original_num_symdefs; new_strings_size = old_strings_size; if (nsymdefs != 0) { /* We already had a __.SYMDEF member, so just update it. */ /* Mark as canceled any old symdefs for members being deleted. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) { /* Old member being deleted. Delete its symdef entries too. */ for (i = 0; i < original_num_symdefs; i++) if (old_symdefs[i].offset == tail->info.offset) { old_symdefs[i].offset = 0; --nsymdefs; deleted_strings_size += strlen (old_strings + old_symdefs[i].s.stringoffset) + 1; } } } /* Compactify old symdefs. */ { register unsigned int j = 0; for (i = 0; i < num_old_symdefs; ++i) { if (j != i) old_symdefs[j] = old_symdefs[i]; if (old_symdefs[i].offset != 0) ++j; } num_old_symdefs -= i - j; } /* Create symdef data for any new members. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.offset != 0 || tail->info.name == 0 || !strcmp (tail->info.name, "__.SYMDEF")) continue; make_new_symdefs (tail, archive_indesc); nsymdefs += tail->info.nsymdefs; new_strings_size += tail->info.string_size; } } else { /* Create symdef data for all existing members. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0 || !strcmp (tail->info.name, "__.SYMDEF")) continue; make_new_symdefs (tail, archive_indesc); nsymdefs += tail->info.nsymdefs; new_strings_size += tail->info.string_size; } } new_strings_size -= deleted_strings_size; old_strings_size -= deleted_strings_size; /* Now we know the size of __.SYMDEF, so assign the positions of all the members. */ tail = find_mapelt_noerror (map, "__.SYMDEF"); tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef)) + sizeof (new_strings_size) + new_strings_size); symdef_mapelt = tail; pos = SARMAG; for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) /* Ignore deleted members. */ continue; tail->info.new_offset = pos; pos += sizeof (struct ar_hdr) + tail->info.size; if (tail->info.size & 1) ++pos; } /* Now update the offsets in the symdef data to be the new offsets rather than the old ones. */ for (tail = map; tail != 0; tail = tail->next) { if (tail->info.name == 0) continue; if (tail->info.symdefs == 0) /* Member without new symdef data. Check the old symdef data; it may be included there. */ for (i = 0; i < num_old_symdefs; i++) { if (old_symdefs[i].offset == tail->info.offset) old_symdefs[i].offset = tail->info.new_offset; } else for (i = 0; i < tail->info.nsymdefs; i++) tail->info.symdefs[i].offset = tail->info.new_offset; } /* Generate new, combined string table and put each string's offset into the symdef that refers to it. Note that old symdefs ref their strings by offsets into old_strings but new symdefs contain addresses of strings. */ new_strings = (char *) xmalloc (new_strings_size); pos = 0; /* Write the strings of the old symdefs and update the structures to contain indices into the string table instead of strings. */ for (i = 0; i < num_old_symdefs; i++) { strcpy (new_strings + pos, old_strings + old_symdefs[i].s.stringoffset); old_symdefs[i].s.stringoffset = pos; pos += strlen (new_strings + pos) + 1; } if (pos < old_strings_size) { unsigned int d = old_strings_size - pos; /* Correct the string table size. */ new_strings_size -= d; /* Correct the size of the `__.SYMDEF' member, since it contains the string table. */ symdef_mapelt->info.size -= d; } else if (pos > old_strings_size) fatal ("Old archive's string size was %u too small.", (void*)(pos - old_strings_size)); for (tail = map; tail != 0; tail = tail->next) if (tail->info.symdefs) { len = tail->info.nsymdefs; s = tail->info.symdefs; for (i = 0; i < len; i++) { strcpy (new_strings + pos, s[i].s.name); s[i].s.stringoffset = pos; pos += strlen (new_strings + pos) + 1; } } if (pos != new_strings_size) fatal ("internal error: inconsistency in new_strings_size", 0); } /* Print error message and usage message, and exit. */ void usage (s1, val) char *s1; int val; { char vbuf[16]; sprintf(vbuf, "%d", val); error (s1, vbuf); fprintf (stderr, "\ Usage: %s [d|m|p|q|r|t|x [[abi [position-name] [cilouv]] archive file...\n", program_name); exit (1); } /* Print error message and exit. */ void fatal (s1, s2) char *s1, *s2; { error (s1, s2); exit (1); } /* Print error message. `s1' is printf control string, the rest are args. */ void error (s1, s2) char *s1, *s2; { fprintf (stderr, "%s: ", program_name); fprintf (stderr, s1, s2); fprintf (stderr, "\n"); } void error3 (s1, s2, s3) char *s1, *s2, *s3; { fprintf (stderr, "%s: ", program_name); fprintf (stderr, s1, s2, s3); fprintf (stderr, "\n"); } void error_with_file (string, mapelt) char *string; struct mapelt *mapelt; { fprintf (stderr, "%s: ", program_name); fprintf (stderr, string); if (mapelt->info.offset != 0) fprintf (stderr, "%s(%s)", archive, mapelt->info.name); else fprintf (stderr, "%s", mapelt->info.name); fprintf (stderr, "\n"); } void perror_with_name (name) char *name; { error (concat ("", strerror(errno), " for %s"), name); } void pfatal_with_name (name) char *name; { fatal (concat ("", strerror(errno), " for %s"), name); } /* Return a newly-allocated string whose contents concatenate those of S1, S2, and S3. */ char * concat (s1, s2, s3) const char *s1, *s2, *s3; { int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); char *result = (char *) xmalloc (len1 + len2 + len3 + 1); strcpy (result, s1); strcpy (result + len1, s2); strcpy (result + len1 + len2, s3); *(result + len1 + len2 + len3) = 0; return result; } /* Like malloc but get fatal error if memory is exhausted. */ char * xmalloc (size) unsigned int size; { #ifdef MALLOC_0_RETURNS_NULL char *result = malloc (size ? size : 1); #else char *result = malloc (size); #endif if (result == 0) fatal ("virtual memory exhausted", 0); return result; } char * xrealloc (ptr, size) char *ptr; unsigned int size; { char *result = realloc (ptr, size); if (result == 0) fatal ("virtual memory exhausted", 0); return result; } #ifndef HAVE_RENAME int rename (from, to) char *from, *to; { (void)unlink (to); if (link (from, to) < 0 || unlink (from) < 0) return -1; else return 0; } #else #ifdef ATT int Error; #endif #endif dev86-0.16.17/ar/Makefile0000644000000000000000000000131707724367760014646 0ustar rootroot00000000000000# Copyright (c) 1999 Greg Haerr # This file is part of the Linux-8086 Development environment and is # distributed under the GNU General Public License. LIBDIR =/usr/bin CFLAGS =-O LDFLAGS = DEFS = OBJS= ar.o alloca.o all: ar86 ar86: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o $@ install: ar86 install -d $(LIBDIR) install -m 755 ar86 $(LIBDIR) clean realclean clobber: rm -f *.o ar86 ar ar.h rel_aout.h $(OBJS): ar.h rel_aout.h ar.h: test -f ar.h || \ { rm -f ar.h ; ln -s ../libc/include/ar.h . ; } || \ ln ../libc/include/ar.h . rel_aout.h: test -f rel_aout.h || \ { rm -f rel_aout.h ; ln -s ../ld/rel_aout.h . ; } || \ ln ../ld/rel_aout.h . .c.o: $(CC) $(CFLAGS) $(DEFS) -c $< -o $@ dev86-0.16.17/ar/alloca.c0000644000000000000000000000253307740630227014573 0ustar rootroot00000000000000 #ifdef __STDC__ #include #else #include #include #endif #if defined(__TINYC__) || defined(__HP_cc) typedef union mem_cell { union mem_cell *next; /* A pointer to the next mem */ unsigned int size; /* An int >= sizeof pointer */ char *depth; /* For the alloca hack */ } mem; #define m_size(p) ((p) [0].size) /* For malloc */ #define m_next(p) ((p) [1].next) /* For malloc and alloca */ #define m_deep(p) ((p) [0].depth) /* For alloca */ static mem *alloca_stack = 0; void * alloca(size) size_t size; { auto char probe; /* Probes stack depth: */ register mem *hp; /* * Reclaim garbage, defined as all alloca'd storage that was allocated * from deeper in the stack than currently. */ for (hp = alloca_stack; hp != 0;) if (m_deep(hp) < &probe) { register mem *np = m_next(hp); free((void *) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ alloca_stack = hp; /* -> last valid storage. */ if (size == 0) return 0; /* No allocation required. */ hp = (mem *) malloc(sizeof(mem)*2 + size); if (hp == 0) return hp; m_next(hp) = alloca_stack; m_deep(hp) = &probe; alloca_stack = hp; /* User storage begins just after header. */ return (void *) (hp + 2); } #endif dev86-0.16.17/as/0000755000000000000000000000000010174732447013174 5ustar rootroot00000000000000dev86-0.16.17/as/align.h0000644000000000000000000000063206327740417014441 0ustar rootroot00000000000000/* align.h - memory alignment requirements for linker */ /* Copyright (C) 1994 Bruce Evans */ #ifndef S_ALIGNMENT # define align(x) #else #if defined(__STDC__) && defined(_POSIX_SOURCE) # define align(x) ((x)=(void *) \ (((ssize_t)(x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) #else # define align(x) ((x)=(void *) \ ((char *)(x) + ((S_ALIGNMENT-(char)(x)) & (S_ALIGNMENT-1)))) #endif #endif dev86-0.16.17/as/file.h0000644000000000000000000000126106172131774014263 0ustar rootroot00000000000000/* file.h - global variables involving files for assembler */ EXTERN char *filnamptr; /* file name pointer */ EXTERN char *truefilename; /* in case actual source name is a tmpname */ EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */ /* Output fds */ EXTERN unsigned char outfd; /* output fd for writer fns */ EXTERN fd_t binfil; /* binary output file (0 = memory) */ EXTERN fd_t lstfil; /* list output file (0 = standard) */ EXTERN fd_t objfil; /* object output file */ EXTERN fd_t symfil; /* symbol table output file */ /* readsrc internals */ EXTERN unsigned infil0; /* Number of first input area */ EXTERN unsigned infiln; /* Number of current input area */ dev86-0.16.17/as/type.h0000644000000000000000000000607207315172641014330 0ustar rootroot00000000000000/* type.h - types for assembler */ typedef unsigned short u2_t; typedef unsigned u2_pt; typedef unsigned long u4_t; typedef unsigned long u4_pt; /* redefine foo_t's because their use has become non-portable */ #define bool_t bool_T #define count_t count_T #define fd_t fd_T #define indcount_t indcount_T #define offset_t offset_T #define opcode_t opcode_T #define opsize_t opsize_T #define scale_t scale_T #define sem_t sem_T #define smallcount_t smallcount_T #define soffset_t soffset_T typedef unsigned char bool_t; typedef int bool_pt; typedef unsigned count_t; typedef int fd_t; typedef unsigned char indcount_t; #ifdef I80386 typedef unsigned long offset_t; typedef long soffset_t; # define SIZEOF_OFFSET_T 4 /* non-portable */ #endif #ifdef MC6809 typedef unsigned offset_t; typedef int soffset_t; # define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */ #endif typedef int opcode_pt; typedef unsigned char opcode_t; typedef int opsize_pt; typedef unsigned char opsize_t; typedef unsigned reg_pt; typedef unsigned char scale_t; typedef unsigned char smallcount_t; typedef /* signed */ char sem_t; typedef unsigned u16_pt; typedef unsigned short u16_T; typedef unsigned long u32_T; /* symbol table entry */ struct sym_s { struct sym_s *next; /* next symbol in hash chain (NUL_PTR if none) */ /* zero offset because it is accessed most */ unsigned char type; unsigned char data; /* flags valid for expressions as well as syms*/ union { offset_t value; /* value, if sym is a label */ unsigned char reg; /* register code, if sym is a register */ struct { unsigned char routine; /* routine number */ opcode_t opcode; /* opcode, if sym is a hardware op */ } op; /* if sym is pseudo-op or hardware op */ } value_reg_or_op; unsigned char length; /* length of symbol string */ char name[1]; /* string of variable length */ }; /* address */ struct address_s { offset_t offset; unsigned char data; struct sym_s *sym; }; #ifdef I80386 /* effective address */ struct ea_s { indcount_t indcount; opsize_t size; reg_pt base; reg_pt index; scale_t scale; struct address_s displ; }; #endif /* flags */ struct flags_s { bool_t global; bool_t current; int semaphore; }; /* location counter */ struct lc_s { unsigned char data; offset_t lc; }; /* string chain */ struct schain_s { struct schain_s *next; char string[2]; /* variable length */ }; /* block stack */ struct block_s { unsigned char data; unsigned char dp; offset_t lc; }; /* if stack */ struct if_s { bool_t ifflag; bool_t elseflag; }; /* macro stack */ struct macro_s { char *text; struct schain_s *parameters; }; /* symbol listing format */ struct sym_listing_s { char name[SYMLIS_NAMELEN]; char zname[2]; char segm[1]; char pad1[1]; char value[4]; char pad2[1]; char ar[1]; char pad3[1]; char cein[1]; char pad4[1]; char nullterm; }; #if __STDC__ typedef void (*pfv)(void); #else typedef void (*pfv)(); #endif #include "proto.h" dev86-0.16.17/as/assemble.c0000644000000000000000000001503507315312211015121 0ustar rootroot00000000000000/* assemble.c - main loop for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "globvar.h" #include "opcode.h" #include "scan.h" PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */ PRIVATE void (*routine) P((void)); PRIVATE pfv rout_table[] = { pelse, pelseif, pelsifc, pendif, pif, pifc, /* start of non-conditionals */ palign, pasciz, pblkw, pblock, pbss, pcomm, pcomm1, pdata, pendb, penter, pentry, pequ, peven, pexport, pfail, pfcb, pfcc, pfdb, #if SIZEOF_OFFSET_T > 2 pfqb, #endif pget, pglobl, pident, pimport, plcomm, plcomm1, plist, ploc, pmaclist, pmacro, pmap, porg, pproceof, prmb, psect, pset, psetdp, ptext, #ifdef I80386 puse16, puse32, #endif pwarn, /* end of pseudo-ops */ #ifdef I80386 mbcc, mbswap, mcall, mcalli, mdivmul, menter, mEwGw, mExGx, mf_inher, mf_m, mf_m2, mf_m2_ax, mf_m2_m4, mf_m2_m4_m8, mf_m4_m8_optst, mf_m4_m8_st, mf_m4_m8_stst, mf_m4_m8_m10_st, mf_m10, mf_optst, mf_st, mf_stst, mf_w_inher, mf_w_m, mf_w_m2, mf_w_m2_ax, mgroup1, mgroup2, mgroup6, mgroup7, mgroup8, mGvEv, mGvMa, mGvMp, mimul, min, mincdec, minher, minher16, minher32, minhera, mint, mjcc, mjcxz, mlea, mmov, mmovx, mnegnot, mout, mpushpop, mret, mseg, msetcc, mshdouble, mtest, mxchg, #endif /* I80386 */ #ifdef MC6809 mall, /* all address modes allowed, like LDA */ malter, /* all but immediate, like STA */ mimmed, /* immediate only (ANDCC, ORCC) */ mindex, /* indexed (LEA's) */ minher, /* inherent, like CLC or CLRA */ mlong, /* long branches */ mshort, /* short branches */ msstak, /* S-stack (PSHS, PULS) */ mswap, /* TFR, EXG */ mustak, /* U-stack (PSHU,PULU) */ #endif /* MC6809 */ }; FORWARD void asline P((void)); /* This uses registers as follows: A is for work and is not preserved by the subroutines.B holds the last symbol code, X usually points to data about the last symbol, U usually holds the value of last expression or symbol, and Y points to the current char. The value in Y is needed by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U. If the expression starts with an identifier, X must point to its string. LOOKUP needs a string pointer in X and length in A. It returns a table pointer in X (unless not assembling and not found), symbol type in A and overflow in CC. */ PUBLIC void assemble() { while (TRUE) { asline(); if (label != NUL_PTR) /* must be confirmed if still set */ { /* it is nulled by EQU, COMM and SET */ #ifndef MC6809 #define NEEDENDLABEL ILLAB if (nocolonlabel) error(NEEDENDLABEL); #endif if(pass && label->value_reg_or_op.value != oldlabel) { dirty_pass = TRUE; if( pass == last_pass ) error(UNSTABLE_LABEL); } label->type |= LABIT; /* confirm, perhaps redundant */ if (label->type & REDBIT) { /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */ label->type |= EXPBIT; label->type &= ~REDBIT; } if ((mcount | popflags) == 0) /* unaccompanied label, display adr like EQU and SET */ showlabel(); label = NUL_PTR; /* reset for next line */ } skipline(); listline(); genbin(); genobj(); binmbuf = lc += lcjump #ifdef I80386 + immcount #endif ; } } PRIVATE void asline() { register struct sym_s *symptr; postb = popflags = pcrflag = #ifdef I80386 sprefix = oprefix = aprefix = #endif immcount = lastexp.data = lcjump = 0; #ifdef I80386 sib = NO_SIB; #endif #if SIZEOF_OFFSET_T > 2 fqflag = #endif fdflag = fcflag = FALSE; cpuwarn(); readline(); getsym(); if (sym != IDENT) /* expect label, mnemonic or macro */ { /* Warn if not a comment marker or a hash (for /lib/cpp) */ if( sym != EOLSYM && sym != IMMEDIATE ) list_force = TRUE; return; /* anything else is a comment */ } symptr = gsymptr; if (!ifflag) /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */ { if (symptr == NUL_PTR || !(symptr->type & MNREGBIT) || symptr->data & REGBIT || symptr->value_reg_or_op.op.routine >= MIN_NONCOND) return; } else if (!(symptr->type & (MACBIT | MNREGBIT))) /* not macro, op, pseudo-op or register, expect label */ { oldlabel = symptr->value_reg_or_op.value; if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */ { sym = COLON; ++lineptr; } if (symptr->type & (LABIT | VARBIT)) { if (symptr->type & REDBIT) labelerror(RELAB); label = symptr; if (pass && !(symptr->type & VARBIT) /*&& last_pass>1*/) { label->data = (label->data & FORBIT) | lcdata; label->value_reg_or_op.value = lc; } } else if (checksegrel(symptr)) { symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */ #ifdef MC6809 #if 0 if (sym == COLON) symptr->type |= EXPBIT; #endif #endif /* remember if forward referenced */ symptr->data = (symptr->data & FORBIT) | lcdata; symptr->value_reg_or_op.value = lc; /* unless changed by EQU,COMM or SET */ label = symptr; } getsym(); if (sym != IDENT) { if (sym == EQOP) { getsym(); pequ(); } return; /* anything but ident is comment */ } symptr = gsymptr; } if (symptr->type & MACBIT) { entermac(symptr); return; } if (!(symptr->type & MNREGBIT)) { error(OPEXP); return; } if (symptr->data & REGBIT) { error(REGUID); return; } mnsize = 0; if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0) { #ifdef MNSIZE if (page == (PAGE1 | PAGE2)) { mnsize = 1; page = 0; } else #endif { #ifdef PAGE2_OPCODE if (page == PAGE2) page = PAGE2_OPCODE; else #endif page = PAGE1_OPCODE; mcount = 1; } } opcode = symptr->value_reg_or_op.op.opcode; #ifdef I80386 needcpu((page==0 && ((opcode&0xF0) == 0x60||(opcode&0xF6)==0xC0))?1:0); #endif routine = rout_table[symptr->value_reg_or_op.op.routine]; getsym(); (*routine)(); if (sym != EOLSYM) error(JUNK_AFTER_OPERANDS); #ifdef I80386 needcpu(page==PAGE1_OPCODE?2:0); if (aprefix != 0) ++mcount; if (oprefix != 0) ++mcount; if (sprefix != 0) ++mcount; #endif } dev86-0.16.17/as/opcode.h0000644000000000000000000000503607315312126014611 0ustar rootroot00000000000000/* opcode.h - routine numbers and special opcodes for assembler */ enum { /* Pseudo-op routine numbers. * Conditionals are first - this is used to test if op is a conditional. */ ELSEOP, ELSEIFOP, ELSEIFCOP, ENDIFOP, IFOP, IFCOP, #define MIN_NONCOND ALIGNOP ALIGNOP, ASCIZOP, BLKWOP, BLOCKOP, BSSOP, COMMOP, COMMOP1, DATAOP, ENDBOP, ENTEROP, ENTRYOP, EQUOP, EVENOP, EXPORTOP, FAILOP, FCBOP, FCCOP, FDBOP, #if SIZEOF_OFFSET_T > 2 FQBOP, #endif GETOP, GLOBLOP, IDENTOP, IMPORTOP, LCOMMOP, LCOMMOP1, LISTOP, LOCOP, MACLISTOP, MACROOP, MAPOP, ORGOP, PROCEOFOP, RMBOP, SECTOP, SETOP, SETDPOP, TEXTOP, #ifdef I80386 USE16OP, USE32OP, #endif WARNOP, /* Machine-op routine numbers. */ #ifdef I80386 BCC, BSWAP, CALL, CALLI, DIVMUL, ENTER, EwGw, ExGx, F_INHER, F_M, F_M2, F_M2_AX, F_M2_M4, F_M2_M4_M8, F_M4_M8_OPTST, F_M4_M8_ST, F_M4_M8_STST, F_M4_M8_M10_ST, F_M10, F_OPTST, F_ST, F_STST, F_W_INHER, F_W_M, F_W_M2, F_W_M2_AX, GROUP1, GROUP2, GROUP6, GROUP7, GROUP8, GvEv, GvMa, GvMp, IMUL, IN, INCDEC, INHER, INHER16, INHER32, INHER_A, INT, JCC, JCXZ, LEA, MOV, MOVX, NEGNOT, OUT, PUSHPOP, RET, SEG, SETCC, SH_DOUBLE, TEST, XCHG #endif /* I80386 */ #ifdef MC6809 ALL, /* all address modes allowed, like LDA */ ALTER, /* all but immediate, like STA */ IMMED, /* immediate only (ANDCC, ORCC) */ INDEXD, /* indexed (LEA's) */ INHER, /* inherent, like CLC or CLRA */ LONG, /* long branches */ SHORT, /* short branches */ SSTAK, /* S-stack (PSHS, PULS) */ SWAP, /* TFR, EXG */ USTAK /* U-stack (PSHU,PULU) */ #endif /* MC6809 */ }; /* Special opcodes. */ #ifdef I80386 # define CMP_OPCODE_BASE 0x38 # define CMPSB_OPCODE 0xA6 # define CMPSW_OPCODE 0xA7 # define ESCAPE_OPCODE_BASE 0xD8 # define FST_ENCODED 0x12 # define FSTP_ENCODED 0x13 # define JMP_OPCODE 0xE9 # define JMP_SHORT_OPCODE 0xEB # define JSR_OPCODE 0xE8 # define MOVSB_OPCODE 0xA4 # define MOVSW_OPCODE 0xA5 # define PAGE1_OPCODE 0x0F # define POP_OPCODE 0x8F # define PUSH_OPCODE 0xFF # define WAIT_OPCODE 0x9B #endif #ifdef MC6809 # define JMP_OPCODE 0x7E # define JSR_OPCODE 0xBD # define PAGE1_OPCODE 0x10 # define PAGE2_OPCODE 0x11 #endif dev86-0.16.17/as/express.c0000644000000000000000000002041107315311064015016 0ustar rootroot00000000000000/* express.c - expression handler for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "globvar.h" #include "scan.h" #include "source.h" FORWARD void experror P((char * err_str)); FORWARD void expundefined P((void)); FORWARD void simple2 P((void)); FORWARD void simple P((void)); FORWARD void term P((void)); FORWARD void factor2 P((void)); PUBLIC void absexpres() { expres(); chkabs(); } /* check lastexp.data is abs */ PUBLIC void chkabs() { if (lastexp.data & RELBIT) { if (pass == last_pass) error(ABSREQ); expundefined(); } } PRIVATE void experror(err_str) char * err_str; { error(err_str); expundefined(); } PRIVATE void expundefined() { if( last_pass == 1 ) lastexp.data = FORBIT | UNDBIT; else lastexp.data = UNDBIT; } PUBLIC void nonimpexpres() { expres(); if (lastexp.data & IMPBIT) experror(NONIMPREQ); } /* generate relocation error if pass 2, make lastexp.data forward&undefined */ PUBLIC void showrelbad() { if (pass == last_pass) error(RELBAD); expundefined(); } PUBLIC void symabsexpres() { getsym(); absexpres(); } PUBLIC void symexpres() { getsym(); expres(); } /* expres() parses expression = simple expression [op simple expression], where op is =, < or >. Parameters: sym, number in number, identifier from symname to lineptr - 1. Returns value in lastexp. */ PUBLIC void expres() { offset_t leftoffset; simple(); leftoffset = lastexp.offset; if (sym == EQOP) { simple2(); if (leftoffset == lastexp.offset) lastexp.offset = -1; else lastexp.offset = 0; } else if (sym == LESSTHAN) { /* context-sensitive, LESSTHAN really means less than here */ simple2(); if (leftoffset < lastexp.offset) lastexp.offset = -1; else lastexp.offset = 0; } else if (sym == GREATERTHAN) { /* context-sensitive, GREATERTHAN really means greater than here */ simple2(); if (leftoffset > lastexp.offset) lastexp.offset = -1; else lastexp.offset = 0; } } /* get symbol and 2nd simple expression, check both rel or both abs */ PRIVATE void simple2() { unsigned char leftdata; leftdata = lastexp.data; getsym(); simple(); if ((leftdata | lastexp.data) & IMPBIT || (leftdata ^ lastexp.data) & (RELBIT | SEGM)) showrelbad(); else lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM); } /* simple() parses simple expression = [+-] term {op term}, where op is +, -, or \ (OR). */ PRIVATE void simple() { offset_t leftoffset; unsigned char leftdata; if (sym == ADDOP || sym == SUBOP) lastexp.data = lastexp.offset = 0; else term(); while (TRUE) { leftoffset = lastexp.offset; leftdata = lastexp.data; if (sym == ADDOP) { getsym(); term(); if (leftdata & lastexp.data & RELBIT) showrelbad(); /* rel + rel no good */ else lastexp.data |= leftdata; lastexp.offset += leftoffset; } else if (sym == SUBOP) { getsym(); term(); /* check not abs - rel or rel - rel with mismatch */ if (lastexp.data & RELBIT && (!(leftdata & RELBIT) || (leftdata | lastexp.data) & IMPBIT || (leftdata ^ lastexp.data) & (RELBIT | SEGM))) showrelbad(); else lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM)) | ((leftdata ^ lastexp.data) & (RELBIT | SEGM)); lastexp.offset = leftoffset - lastexp.offset; } else if (sym == OROP) { getsym(); term(); lastexp.data |= leftdata; chkabs(); /* both must be absolute */ lastexp.offset |= leftoffset; } else return; } } /* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */ PRIVATE void term() { offset_t leftoffset; factor(); while (TRUE) { leftoffset = lastexp.offset; if (sym == STAR) { /* context-sensitive, STAR means multiplication here */ factor2(); lastexp.offset *= leftoffset; } else if (sym == SLASH) { /* context-sensitive, SLASH means division here */ factor2(); lastexp.offset = leftoffset / lastexp.offset; } else if (sym == ANDOP) { factor2(); lastexp.offset &= leftoffset; } else if (sym == SLOP) { factor2(); lastexp.offset = leftoffset << lastexp.offset; } else if (sym == SROP) { factor2(); lastexp.offset = leftoffset >> lastexp.offset; } else return; } } /* get symbol and 2nd or later factor, check both abs */ PRIVATE void factor2() { unsigned char leftdata; leftdata = lastexp.data; getsym(); factor(); lastexp.data |= leftdata; chkabs(); } /* factor() parses factor = number | identifier | * | (expression) | ! factor, ! is complementation. Returns value in lastexp.offset, possible flags IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT. If the factor is an identifier, LOOKUP is used to get its value (so the ident is installed in the symbol table if necessary, with default flags inidata). If the identifier is not a label, (could be imported, or later in the program), its FORBIT is set. The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then taken from the identifier. */ PUBLIC void factor() { switch (sym) { case SLASH: /* context-sensitive, SLASH means a hex number here */ context_hexconst(); case INTCONST: lastexp.data = 0; /* absolute & not forward or undefined */ lastexp.offset = number; getsym(); return; case IDENT: { register struct sym_s *symptr; symptr = gsymptr; if (symptr->type & (MNREGBIT | MACBIT)) experror(symptr->type & MACBIT ? MACUID : symptr->data & REGBIT ? REGUID : MNUID); else { if (!(symptr->type & (LABIT | VARBIT))) { if( last_pass == 1 ) symptr->data |= FORBIT; lastexp.sym = symptr; } if (pass != last_pass) { if( last_pass == 1 ) lastexp.data = symptr->data & (FORBIT | RELBIT | UNDBIT | SEGM); else lastexp.data = symptr->data & (RELBIT | UNDBIT | SEGM); /* possible flags for pass 1 */ lastexp.offset = symptr->value_reg_or_op.value; } else { if ((lastexp.data = symptr->data) & IMPBIT) lastexp.offset = 0; /* value != 0 for commons */ /* OK even if UNDBIT */ else { lastexp.offset = symptr->value_reg_or_op.value; if (lastexp.data & UNDBIT) experror(UNBLAB); } } } getsym(); return; } #ifndef MC6809 case LBRACKET: if (!asld_compatible) break; /* error, LPAREN is the grouping symbol */ getsym(); expres(); if (sym != RBRACKET) error(RBEXP); else getsym(); return; #endif case LPAREN: #ifndef MC6809 if (asld_compatible) break; /* error, LBRACKET is the grouping symbol */ #endif getsym(); expres(); if (sym != RPAREN) error(RPEXP); else getsym(); return; case NOTOP: getsym(); factor(); chkabs(); lastexp.offset = ~lastexp.offset; return; case ADDOP: getsym(); factor(); return; case SUBOP: getsym(); factor(); chkabs(); lastexp.offset = -lastexp.offset; return; case STAR: /* context-sensitive, STAR means location counter here */ lastexp.offset = lc; if ((lastexp.data = lcdata) & UNDBIT && pass == last_pass) experror(UNBLAB); getsym(); return; } experror(FACEXP); } /* string compare for IFC/ELSEIFC expects (,) returns logical value in lastexp */ PUBLIC void scompare() { /* prepare flags for OK, lastexp.offset for error */ lastexp.data = lastexp.offset = 0; if (sym != LPAREN) experror(LPEXP); else { register char *string1; register char *string2; for (string2 = string1 = lineptr; *string2 != ','; ++string2) if (*string2 == 0 || *string2 == ')') { symname = string2; experror(COMEXP); return; } string2++; while (*string1++ == *string2++) ; if (string2[-1] == ')') { if (string1[-1] == ',') lastexp.offset = TRUE; /* else leave FALSE */ lineptr = string2; } else /* FALSE, keep reading to verify syntax */ { for (; *string2 != ')'; ++string2) if (*string2 == 0 || *string2 == ',') { symname = string2; experror(RPEXP); } lineptr = ++string2; } getsym(); } } dev86-0.16.17/as/chk0000755000000000000000000000045707775363557013714 0ustar rootroot00000000000000 compile() { # /lib/elksemu ./as86 -3 -k "$@" ./as86 -3 -k "$@" } for i in `ls asm/*.asm` do j=`basename $i .asm` compile asm/$j.asm -b $j.bin -o $j.obj > /dev/null cmp $j.obj obj1/$j.obj # compile asm/$j.asm -b $j.bin > /dev/null # cmp $j.bin bin/$j.bin rm -f $j.bin $j.obj $j.asm done dev86-0.16.17/as/source.h0000644000000000000000000000026204465701360014641 0ustar rootroot00000000000000/* source.h - global variables for source handlers for assembler */ EXTERN unsigned linum; /* line # */ EXTERN bool_t listpre; /* flag to show line has already been listed */ dev86-0.16.17/as/6809/0000755000000000000000000000000005727442400013575 5ustar rootroot00000000000000dev86-0.16.17/as/6809/const.h0000644000000000000000000002626104777257703015121 0ustar rootroot00000000000000#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */ #define LOW_BYTE 0 /* must be changed for big-endian */ /* const.h - constants for assembler */ /* major switches */ #undef I80386 /* generate 80386 code */ #define MC6809 /* generate 6809 code */ #define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ #undef SOS_EDOS /* source OS is EDOS */ /* defaults */ #define DIRCHAR '/' /* character separating filename from dir */ #define INBUFSIZE 8192 #define SOS_EOLSTR "\012" /* defaults modified by switches */ #ifdef SOS_EDOS # undef INBUFSIZE # define INBUFSIZE 512 # undef SOS_EOLSTR # define SOS_EOLSTR "\015\012" # define STAKSIZ 256 /* table grows up to stack less this */ #endif /* booleans */ #define FALSE 0 #define TRUE 1 /* ASCII constants */ #define ETB 23 /* C tricks */ #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC #define NULL 0 /* O/S constants */ #define CREAT_PERMS 0666 #define EOF (-1) #define STDIN 0 #define STDOUT 1 /* register codes (internal to assembler) */ #ifdef I80386 /* index regs must be first */ #define BPREG 0 #define BXREG 1 #define DIREG 2 #define SIREG 3 #define MAX16BITINDREG 3 #define EAXREG 4 #define EBPREG 5 #define EBXREG 6 #define ECXREG 7 #define EDIREG 8 #define EDXREG 9 #define ESIREG 10 #define ESPREG 11 #define MAXINDREG 11 #define AXREG 12 #define CXREG 13 #define DXREG 14 #define SPREG 15 #define AHREG 16 #define ALREG 17 #define BHREG 18 #define BLREG 19 #define CHREG 20 #define CLREG 21 #define DHREG 22 #define DLREG 23 #define CSREG 24 #define DSREG 25 #define ESREG 26 #define FSREG 27 #define GSREG 28 #define SSREG 29 #define CR0REG 30 #define CR2REG 31 #define CR3REG 32 #define DR0REG 33 #define DR1REG 34 #define DR2REG 35 #define DR3REG 36 #define DR6REG 37 #define DR7REG 38 #define TR6REG 39 #define TR7REG 40 #define NOREG 41 #endif /* I80386 */ #ifdef MC6809 /* index regs must be first, then PC, then other regs */ #define AREG 5 #define BREG 6 #define CCREG 7 #define DPREG 8 #define DREG 9 #define MAXINDREG 3 #define NOREG 10 #define PCREG 4 #define SREG 0 #define UREG 1 #define XREG 2 #define YREG 3 #endif #ifdef I80386 /* type and size keywords */ #define BYTEOP 0 #define DWORDOP 1 #define FWORDOP 2 #define FAROP 3 #define PTROP 4 #define PWORDOP 5 #define QWORDOP 6 #define TBYTEOP 7 #define WORDOP 8 #endif /* special chars */ #define EOL 0 #define MACROCHAR '?' /* symbol codes */ /* the first 2 must be from chars in identifiers */ #define IDENT 0 #define INTCONST 1 /* the next few are best for other possibly-multi-char tokens */ #define ADDOP 2 /* also ++ */ #define BINCONST 3 #define CHARCONST 4 #define GREATERTHAN 5 /* also >> and context-sensitive */ #define HEXCONST 6 #define LESSTHAN 7 /* also << and context-sensitive */ #define SUBOP 8 /* also -- */ #define WHITESPACE 9 #define ANDOP 10 #define COMMA 11 #define EOLSYM 12 #define EQOP 13 #define IMMEDIATE 14 #define INDIRECT 15 #define LBRACKET 16 #define LPAREN 17 #define MACROARG 18 #define NOTOP 19 #define OROP 20 #define OTHERSYM 21 #define POSTINCOP 22 #define PREDECOP 23 #define RBRACKET 24 #define RPAREN 25 #define SLASH 26 /* context-sensitive */ #define SLOP 27 #define SROP 28 #define STAR 29 /* context-sensitive */ #define STRINGCONST 30 #define COLON 31 /* these are from assembler errors module */ /* syntax errors */ #define COMEXP 0 #define DELEXP 1 #define FACEXP 2 #define IREGEXP 3 #define LABEXP 4 #define LPEXP 5 #define OPEXP 6 #define RBEXP 7 #define REGEXP 8 #define RPEXP 9 #define SPEXP 10 /* expression errors */ #define ABSREQ 11 #define NONIMPREQ 12 #define RELBAD 13 /* label errors */ #define ILLAB 14 #define MACUID 15 #define MISLAB 16 #define MNUID 17 #define REGUID 18 #define RELAB 19 #define UNBLAB 20 #define UNLAB 21 #define VARLAB 22 /* addressing errors */ #define ABOUNDS 23 #define DBOUNDS 24 #define ILLMOD 25 #define ILLREG 26 /* control structure errors */ #define ELSEBAD 27 #define ELSEIFBAD 27 #define ENDBBAD 28 #define ENDIFBAD 27 #define EOFBLOCK 29 #define EOFIF 30 #define EOFLC 31 #define EOFMAC 32 #define FAILERR 33 /* overflow errors */ #define BLOCKOV 34 #define BWRAP 35 #define COUNTOV 36 #define COUNTUN 37 #define GETOV 38 #define IFOV 39 #define LINLONG 40 #define MACOV 41 #define OBJSYMOV 42 #define OWRITE 43 #define PAROV 44 #define SYMOV 45 #define SYMOUTOV 46 /* i/o errors */ #define OBJOUT 47 /* miscellaneous errors */ #define CTLINS 48 #define FURTHER 49 #define NOIMPORT 50 #define NOTIMPLEMENTED 51 #define REENTER 52 #define SEGREL 53 /* warnings */ #define MINWARN 54 #define ALREADY 54 #define SHORTB 55 /* symbol table entry */ /* type entry contains following flags */ #define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */ #define COMMBIT (1<<1) /* common */ #define LABIT (1<<2) /* label (a PC location or defined by EQU) */ #define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ #define MACBIT (1<<4) /* macro */ #define REDBIT (1<<5) /* redefined */ #define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ #define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ /* data entry contains following flags, valid */ /* for expressions as well as syms */ #define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */ #define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */ #define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */ #define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */ #define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */ #define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ #define FORBIT (1<<5) /* forward referenced */ #define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ #define UNDBIT (1<<7) /* undefined */ /* pseudo-op routine numbers */ /* conditionals are first, this is used to test if op is a conditional */ #define ELSEOP 0 #define ELSEIFOP 1 #define ELSEIFCOP 2 #define ENDIFOP 3 #define IFOP 4 #define IFCOP 5 #define MAXCOND 6 /* limit of conditionals */ #define BLOCKOP 6 #define COMMOP 7 #define ENDOP 8 #define ENDBOP 9 #define ENTEROP 10 #define ENTRYOP 11 #define EQUOP 12 #define EXPORTOP 13 #define FAILOP 14 #define FCBOP 15 #define FCCOP 16 #define FDBOP 17 #define GETOP 18 #define IDENTOP 19 #define IMPORTOP 20 #define _LISTOP 21 #define LOCOP 22 #define _MACLISTOP 23 #define MACROOP 24 #define _MAPOP 25 #define ORGOP 26 #define RMBOP 27 #define SETOP 28 #define SETDPOP 29 #define _WARNOP 30 #ifdef I80386 /* further pseudo-ops */ #define BSSOP 31 #define COMMOP1 32 #define DATAOP 33 #define TEXTOP 34 #define USE16OP 35 #define USE32OP 36 /* machine-op routine numbers */ #define ARPL 37 #define BCC 38 #define BOUND 39 #define CALL 40 #define DIVMUL 41 #define ENTER 42 #define GROUP1 43 #define GROUP2 44 #define GROUP6 45 #define GROUP7 46 #define GROUP8 47 #define GvEv 48 #define IMUL 49 #define IN 50 #define INCDEC 51 #define INHER 52 #define INHER16 53 #define INHER32 54 #define INHER_A 55 #define INT 56 #define JCC 57 #define JCXZ 58 #define LEA 59 #define LOAD_FULL_POINTER 60 #define MOV 61 #define MOVX 62 #define NEGNOT 63 #define OUT 64 #define PUSHPOP 65 #define RET 66 #define RETF 67 #define SEG 68 #define SETCC 69 #define SH_DOUBLE 70 #define TEST 71 #define XCHG 72 /* further pseudo-ops */ #define BLKWOP 73 #define EVENOP 74 #define FQBOP 75 #define ALIGNOP 76 /* further machine-ops */ #define CALLI 77 /* yet further pseudo-ops */ #define LCOMMOP 78 #define LCOMMOP1 79 #endif /* I80386 */ #ifdef MC6809 /* machine-op routine numbers */ #define ALL 31 /* all address modes allowed, like LDA */ #define ALTER 32 /* all but immediate, like STA */ #define IMMED 33 /* immediate only (ANDCC, ORCC) */ #define INDEXD 34 /* indexed (LEA's) */ #define INHER 35 /* inherent, like CLC or CLRA */ #define LONG 36 /* long branches */ #define SHORT 37 /* short branches */ #define SSTAK 38 /* S-stack (PSHS, PULS) */ #define SWAP 39 /* TFR, EXG */ #define USTAK 40 /* U-stack (PSHU,PULU) */ /* yet further pseudo-ops */ #define LCOMMOP 41 #endif /* object code format (Introl) */ #define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ #define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ #define OBJ_ABS 0x40 /* absolute code command */ #define OBJ_OFFSET_REL 0x80 /* offset relocation command */ #define OBJ_SET_SEG 0x20 /* set segment command */ #define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ #define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ #define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ #define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ #define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ #if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ oops - RELBIT misplaced #endif #define OBJ_E_MASK 0x80 /* exported bit (symbols) */ #if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ oops - EXPBIT misplaced #endif #define OBJ_I_MASK 0x40 /* imported bit (symbols) */ #if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ oops - IMPBIT misplaced #endif #define OBJ_N_MASK 0x01 /* entry bit (symbols) */ #if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ oops - ENTBIT misplaced #endif #define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ #define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ #define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ #define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ #define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ #define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ #define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ #define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ #define SYMLIS_NAMELEN 26 #define SYMLIS_LEN (sizeof (struct sym_listing_s)) #define FILNAMLEN 64 /* max length of a file name */ #define LINLEN 256 /* max length of input line */ #define LINUM_LEN 5 /* length of formatted line number */ #define SPTSIZ 1024 /* number of symbol ptrs */ /* pseudo-op flags */ #define POPHI 1 /* set to print hi byte of adr */ #define POPLO 2 /* to print lo byte of ADR */ #define POPLC 4 /* to print LC */ #define POPLONG 8 /* to print high word of ADR */ #define MAXBLOCK 8 /* max nesting level of BLOCK stack */ #define MAXGET 8 /* max nesting level of GET stack */ #define MAXIF 8 /* max nesting level of IF stack */ #define MACPSIZ (128/sizeof (struct schain_s)) /* size of macro param buffer */ #define MAXMAC 8 /* max nesting level of macro stack */ #define NLOC 16 /* number of location counters */ #ifdef I80386 #define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ #endif /* special segments */ #define BSSLOC 3 #define DATALOC 3 #define DPLOC 2 #define STRLOC 1 #define TEXTLOC 0 dev86-0.16.17/as/byteord.h0000644000000000000000000000076106324142215015007 0ustar rootroot00000000000000/* byteord.h - byte order dependencies for C compiler, assembler, linker */ /* These are for the targets of everything and for linker source too. */ #ifdef I8086 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ #endif #ifdef I80386 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 #endif #ifdef MC6809 # define INT_BIG_ENDIAN 1 /* byte order in words is high-low */ # define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ #endif dev86-0.16.17/as/as86_encap.sh0000644000000000000000000000553506504601163015457 0ustar rootroot00000000000000#!/bin/sh - # # This file is simply an example of what can be done using the new binary # and symbol table output functions. As shown it can be used to produce # a C file containing the encapsulated binary of the assembly, plus any # public symbols in the source are accessable to the C program. # # Use it in a makefile: # # .s.v: # as86_encap $*.s $*.v $*_ $(AS86FLAGS) # [ $# -lt 2 ] && { echo "Usage: `basename $0` infile outfile prefix [as86 opts]" 1>&2 exit 1 } trap "rm -f _$$.* ; exit 99" 1 2 3 15 LIBDIR='%%LIBDIR%%' # Set by make install BINDIR='%%BINDIR%%' # Set by make install # If the one set by install fails then try a couple of others. [ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`" [ -x "$LIBDIR/as86" ] || LIBDIR="$BINDIR" [ -x "$LIBDIR/as86" ] || LIBDIR="`dirname $0`/../lib" [ -x "$LIBDIR/as86" ] || LIBDIR=/usr/bin IFILE="$1" OFILE="$2" PREFIX="`basename $IFILE .s`_" shift ; shift if [ $# -ge 1 ] then case "$1" in -* ) ;; [A-Za-z_]* ) PREFIX="$1" shift ;; esac fi RV=0 $LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$? echo '#ifndef __ASSEMBLY__' > _$$.0 echo >> _$$.0 echo '#else' > _$$.3 echo >> _$$.3 echo '#endif' > _$$.5 [ "$RV" = 0 ] && { ( sort _$$.sym echo %%%% od -v -t uC _$$.bin ) | \ awk -v prefix=$PREFIX -v ofile=_$$ ' BEGIN{ sname = prefix "start"; sn_file= ofile ".1"; bn_file= ofile ".2"; as_file= ofile ".4"; } /^%%%%$/ { flg++; if( flg == 1 ) { if( !started ) { printf "#define %s 0\n", sname > sn_file; printf "%s = 0\n", sname > as_file; } printf "static char %sdata[] = {\n", prefix >bn_file; bincount=0; } next; } flg==0 { if(NF == 0) next; if( substr($2,1,4) == "0000" ) $2=substr($2,5); if( $1 == "+" && $4 == "$start" ) { printf "#define %s 0x%s\n", sname, $2 > sn_file; printf "%s = $%s\n", sname, $2 > as_file; started = 1; } else if( substr($3, 1, 1) == "E" && $4 != "start" && $4 != "size" && $4 != "data" ) { printf "#define %s%s 0x%s\n", prefix, $4, $2 > sn_file; printf "%s%s = $%s\n", prefix, $4, $2 > as_file; } next; } flg==1 { if(NF == 0) next; printf " " > bn_file; for(i=2;i<=NF;i++) { if( $i >= 32 && $i < 127 && $i != 39 && $i != 92 ) printf("\047%c\047,", $i) > bn_file; else printf("%3d,", $i) > bn_file; bincount++; } printf "\n" > bn_file; } END { printf "};\n\n" > bn_file; printf "#define %ssize %d\n\n", prefix, bincount > sn_file; printf "%ssize = $%04x\n\n", prefix, bincount > as_file; } ' RV=$? } [ "$RV" = 0 ] && { if [ "X$OFILE" = "X-" ] then cat _$$.[0-9] else cat _$$.[0-9] > "$OFILE" || RV=$? fi } rm -f _$$.* exit $RV dev86-0.16.17/as/as86_to_data0000644000000000000000000000375206352300646015375 0ustar rootroot00000000000000#!/bin/sh - # # This file is simply an example of what can be done using the new binary # and symbol table output functions. It produces a byte array with the # symbols in the object as array references within it. # # The output is a Linux OMAGIC binary created by ld86 -N, this means the # object can be linked directly to C-functions created by the same GCC that # compiled ld86. # # Use it in a makefile: # # .s86.o: # as86_to_data $*.s86 $*.o $(AS86FLAGS) # [ $# -lt 2 ] && { echo "Usage: `basename $0` infile outfile [as86 opts]" 1>&2 exit 1 } trap "rm -f _$$.* ; exit 99" 1 2 3 15 LIBDIR='%%LIBDIR%%' # Set by make install [ -d "$LIBDIR" ] || LIBDIR='%%BINDIR%%' [ -d "$LIBDIR" ] || LIBDIR=/usr/bin IFILE="$1" OFILE="$2" shift ; shift RV=0 $LIBDIR/as86 "$@" "$IFILE" -b _$$.bin -s _$$.sym || RV=$? [ "$RV" = 0 ] && { ( cat _$$.sym echo %%%% od -v -t uC _$$.bin echo %%%% ) | \ awk > _$$.v ' BEGIN{ startaddr=""; printf ".text\n.data\n"; } /^%%%%$/ { flg++; next; } flg==0 { if(NF == 0) next; if( substr($2,1,4) == "0000" ) $2=substr($2,5); if( $1 == "+" && $4 == "$start" ) { if( $2 != "0000" ) startaddr=" - $" $2; } else if( substr($3, 1, 1) == "E" && $4 != "start" && $4 != "size" && $4 != "data" ) { printf "export _%s\n", $4 printf "_%s = * + $%s%s\n\n", $4, $2, startaddr; } next; } flg==1 { if(NF <= 1) next; printf " .byte "; for(i=2;i tmp @mv -f tmp $@ chmod +x $@ install: all install -d $(LIBDIR) install -m 755 as86 $(LIBDIR) install -d $(BINDIR) install -m 755 as86_encap $(BINDIR)/as86_encap -@rm -f tmp clean realclean clobber: rm -f *.o as86 as86_encap .c.o: $(CC) $(CFLAGS) -c $< $(OBJS): const.h errors.h as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h assemble.o: const.h type.h address.h globvar.h opcode.h scan.h error.o: const.h type.h express.o: const.h type.h address.h globvar.h scan.h source.h genbin.o: const.h type.h address.h file.h globvar.h genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \ source.h genobj.o: const.h type.h address.h file.h globvar.h gensym.o: const.h type.h flag.h file.h globvar.h keywords.o: const.h type.h globvar.h opcode.h macro.o: const.h type.h globvar.h scan.h macro.h mops.o: const.h type.h globvar.h opcode.h scan.h address.h pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h scan.o: const.h type.h globvar.h scan.h table.o: const.h type.h globvar.h opcode.h scan.h dev86-0.16.17/as/genbin.c0000644000000000000000000001300607573467450014612 0ustar rootroot00000000000000/* genbin.c - binary code generation routines for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "file.h" #include "globvar.h" #ifdef USE_FIXED_HEAP PRIVATE char *asmbeg; /* beginning of assembler code */ /* for overwrite check */ /* bss-init to zero = NULL and not changed */ #endif /* Sneaky stuff, the start of a binary file can be _negative_ for the I80386 assembler. The -ve addresses are ones over 2GB (or "org -32") */ #ifdef I80386 PRIVATE soffset_t binfbuf; /* binary code buffer for file (counter) */ PRIVATE soffset_t binmax; /* maximum value of binmbuf for pass 1 */ PRIVATE soffset_t binmin; /* minimum value of binmbuf for pass 1 */ #define PT soffset_t #else PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */ PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */ PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */ #define PT offset_t #endif FORWARD void putbinoffset P((offset_t offset, count_t size)); /* write header to binary file */ PUBLIC void binheader() { #ifdef BINSYM if ((outfd = binfil) != 0x0 && binmbuf_set && binmax >= binmin) { writec(0x0); /* binary header byte */ #ifdef LONG_BINHEADER writeoff(binmax - binmin); /* program length */ writeoff(binfbuf = binmin); /* program start */ #else writew((unsigned) (binmax - binmin)); /* program length */ writew((unsigned) (binfbuf = binmin)); /* program start */ #endif } #else if ( ( outfd = symfil ) && binmbuf_set && binmax >= binmin) { int sft; writec('+'); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(binmin>>sft) & 0xF]); writesn(" ----- $start"); writec('+'); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(binmax>>sft) & 0xF]); writesn(" ----- $end"); binfbuf = binmin; /* program start */ } #endif } /* write trailer to binary file */ PUBLIC void bintrailer() { #ifdef BINSYM if ((outfd = binfil) != 0x0 && (pedata & UNDBIT) != UNDBIT && binmbuf_set) { writec(0xFF); /* binary trailer byte */ writew(0x0); /* further trailer bytes */ #ifdef LONG_BINHEADER writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */ #else writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent); #endif } #endif } /* generate binary code for current line */ PUBLIC void genbin() { struct address_s *adrptr; char *bufptr; unsigned char remaining; if (binaryg && mcount != 0x0) { if (popflags) { if (fcflag) { bufptr = databuf.fcbuf; remaining = mcount; do putbin(*bufptr++); while (--remaining != 0x0); } if (fdflag) { adrptr = databuf.fdbuf; remaining = mcount; do { putbinoffset(adrptr->offset, 0x2); ++adrptr; } while ((remaining -= 0x2) != 0x0); } #if SIZEOF_OFFSET_T > 0x2 if (fqflag) { adrptr = databuf.fqbuf; remaining = mcount; do { putbinoffset(adrptr->offset, 0x4); ++adrptr; } while ((remaining -= 0x4) != 0x0); } #endif } else { remaining = mcount - 0x1; /* count opcode immediately */ #ifdef I80386 if (aprefix != 0x0) { putbin(aprefix); --remaining; } if (oprefix != 0x0) { putbin(oprefix); --remaining; } if (sprefix != 0x0) { putbin(sprefix); --remaining; } #endif if (page != 0x0) { putbin(page); --remaining; } putbin(opcode); if (remaining != 0x0) { if (postb != 0x0) { putbin(postb); --remaining; } #ifdef I80386 if (sib != NO_SIB) { putbin(sib); --remaining; } #endif if (remaining != 0x0) putbinoffset(lastexp.offset, remaining); } #ifdef I80386 if (immcount != 0x0) putbinoffset(immadr.offset, immcount); #endif } /* else no code for this instruction, or already generated */ } } /* initialise private variables */ PUBLIC void initbin() { #ifdef I80386 binmin = ((offset_t)-1 >>1); /* greater than anything */ #else binmin = -1; /* greater than anything */ #endif } /* write char to binary file or directly to memory */ PUBLIC void putbin(ch) opcode_pt ch; { if (binfil != 0x0) { if (!binaryc) /* pass 1, just record limits */ { if ((PT)binmbuf < binmin) binmin = binmbuf; binmbuf++; if ((PT)binmbuf > binmax) binmax = binmbuf; } else { #if 0 if (binfbuf > (PT)binmbuf) { error(BWRAP); /* file buffer ahead of memory buffer */ } else #endif { #ifdef MSDOS static PT zapptr = 0; #endif outfd = binfil; #ifdef MSDOS while (binfbuf < (PT)binmbuf && binfbuf >= zapptr+binmin) { writec(0); ++binfbuf; ++zapptr; } #endif if( binfbuf != (PT)binmbuf) if( lseek(binfil, (long)((PT)binmbuf-binfbuf), 1) < 0 ) error(BWRAP); binfbuf = binmbuf; writec(ch); binmbuf = ++binfbuf; } } } #ifdef USE_FIXED_HEAP else if (binaryc && !(lcdata & UNDBIT)) /* memory output, and enabled */ { register char *bufptr; if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < temp_buf()) error(OWRITE); else *bufptr = ch; ++binmbuf; } #endif } /* write sized offset to binary file or directly to memory */ PRIVATE void putbinoffset(offset, size) offset_t offset; count_t size; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 0x2 u4cn(buf, offset, size); #else u2cn(buf, offset, size); #endif putbin(buf[0]); if (size > 0x1) putbin(buf[1]); if (size > 0x2) { putbin(buf[2]); putbin(buf[3]); } } dev86-0.16.17/as/obj1/0000755000000000000000000000000006235766000014022 5ustar rootroot00000000000000dev86-0.16.17/as/obj1/xchg.obj0000644000000000000000000000041005060271421015433 0ustar rootroot00000000000000£†*"àUUUUàxchg @ff“f‘f’f”f•f–f—ff“f‘f’f”f•f–f—“‘’”•–—“‘’”•–—†À†à†Ø†ø†Ë†ë†Ó†ó@g†g†'g†g†?g†g†/g†g†7g†g†'g†g†?g†g†/g†g†7gf‡gf‡gf‡gf‡@gf‡'gf‡/gf‡7gf‡?gf‡gf‡gf‡gf‡gf‡'gf‡/gf‡7gf‡?g‡g‡g‡g‡g‡'g`‡/g‡7g‡?f‡f‡f‡ f‡f‡#f‡+f‡3f‡;dev86-0.16.17/as/obj1/ea.obj0000644000000000000000000000073005060271412015074 0ustar rootroot00000000000000£†* ¯UUUU¯ea @gf‹gf‹gf‹gf‹gf‹gf‹gf¡4gf‹gf‹@gf‹Agf‹Bgf‹Cgf‹Dgf‹Eg@f‹Fgf‹Ggf‹€4gf‹4gf‹‚4gf‹ƒ4gf‹„4gf‹…4gf‹†4gf‹‡4ˆÀˆàˆØˆ@øˆÈˆèˆÐˆðf‰Àf‰Èf‰Ðf‰Øf‰àf‰èf‰ðf‰øf‹f‹f‹f‹f¡xV4f‹f‹f‹@f‹A@f‹Bf‹Cf‹Ef‹Ff‹Gf‹€xV4f‹xV4f‹‚xV4f‹ƒxV4f‹…xV4f‹†xV4f@‹‡xV4‰À‰È‰Ð‰Ø‰à‰è‰ð‰øf‹pf‹qf‹rf‹sf‹tf‹uxV4f‹vf‹wf‹Dpf@‹Dqf‹Drf‹Dsf‹Dtf‹D$f‹Duf‹Dvf‹Dwf‹„pxV4f‹„qxV4f‹„rxV4fo‹„sxV4f‹„txV4f‹„$xV4f‹„uxV4f‹„vxV4f‹„wxV4dev86-0.16.17/as/obj1/group7.obj0000644000000000000000000000012205060271414015727 0ustar rootroot00000000000000£†*$+UUUU+group7 kgggg?gF ðg70ãdev86-0.16.17/as/obj1/each.obj0000644000000000000000000000131305061123311015400 0ustar rootroot00000000000000£†*7‡UUUU‡@Ï €;eachmanyalot @7Õ Ô ?fµfµf#µcµfbµf¼µf½µ@Ëf£µf»µf³µf«µÿµf˜˜øüúõf;µ¦f§@§f§µf™™'/ÿ µ÷4µÈô÷<µ÷,µä ÿµlfmmÍ Î@<µfÏÏuÿ$µŸfµfµÉµµfŵ@fĵf´µfµµf²µµ4µð¬f­­âfµ@µf‹µf‹µ"À¤f¥¥f¾µf¶µ÷$µ÷µ@÷µf µæ nfooµfaafÿ4µf``fœœÑµÑµ@ÑµÑ µóóóòòÃËžÑ$µÑ<µÑ$µÑ,µfµ®f¯¯@•µµ µf¤µf¬µµ$µùýûªf@«« µf+µf…µ$µ,µ› fÁµf‡µ×fG3µdev86-0.16.17/as/obj1/farcall.obj0000644000000000000000000000010705060271413016112 0ustar rootroot00000000000000£†*%UUUUfarcall _šgÿgÿêÿ.gÿ.dev86-0.16.17/as/obj1/f.obj0000644000000000000000000000031705060271413014736 0ustar rootroot00000000000000£†*«UUUU«f @ÜØØÁÜÁÜ3Ø3ØñÞÁß#ß3ØÜØÑØÑÝÁÝáÝáÞÚßÛß+ÙÝÛ+ÙÁÙ+Ù;Ù#Ý3Ù3Ý#@Ý;ßàÙÝÝÑ›Ù;›Ý;›ßà›Ý3›Ù3ÙÐÙàÙáÙäÙåÙèÙéÙêÙëÙìÙíÙîÙðÙñÙòÙóÙôÙõÙöÙk÷ÙøÙùÙúÙûÙüÙýÙþÙÿÚé›ÛàÛà›ÛáÛá›ÛâÛâ›ÛãÛãÛäÞÙdev86-0.16.17/as/obj1/shdouble.obj0000644000000000000000000000015205060271420016311 0ustar rootroot00000000000000£†*43UUUU3 @shdoubleILLEGALS sf¤Øf¤Ë¤òf¥Ù¤Ögf¤g¤gf¥g¥f¬Ëf­Ùdev86-0.16.17/as/obj1/pushpop.obj0000644000000000000000000000023705060271417016214 0ustar rootroot00000000000000£†*%vUUUUvpushpop @jgÿ7fjÿfPfSfQfRfTfUfVfWffff f¨fh4fh4gfÿ7PSQRTUVWhxV4vhxV4gÿ7gfXf[fYfZf\f]f^f_fff¡f©fgfX[YZ\]^_gdev86-0.16.17/as/obj1/fadd.obj0000644000000000000000000000205505060271413015410 0ustar rootroot00000000000000£†*ÊSUUUUS@K €™€Æ)@ø1€!;€:D€EQ€)[@P`@µp€\{@º‰@æ@™™€ ž@°ª€Ä¶€u¿Å€¿Ð@.Ù€Oß@(è€Ëñ@®ú@¿€ €!faddSWAPSUBTRACT_BIGSHIFTTO_UNDERFLOWROUNDUPUNDERFLOWOVERFLOWADD_BIGSHIFTLOVERFLOWXBIGTO_ADD_BIGSHIFTNORMLITTLETO_NORMLITTLEROUNDNORMALIZEDONETO_SUBTRACTTO_OVERFLOWSUBTRACT_faddTO_ANSWER0faddfxfy_faccfsubfxfyfmulfxfyTO_DONE1NORMALIZE2DONE1ANSWER0 [fUf‰åg‹Fg‹Vg‹^ g‹N裀OB‰€S@f]Ãñ€UWV‰Ï‰Öæÿÿÿçÿÿÿ9þw r9Øs‡Ê‡þ“æÿÿçÿÿÎÏ@ÁéÁê‰Íf)Ñf÷Ùfƒù7s2f1Õfåu*€ù s*­Ý­ûÓïØþ)Ûf‰Ñfáÿ÷Æ@ té{ëbéÀé‹é¬÷½ÿtòfƒïf÷ßfQf‰ù¥Æ¥è¥ÝÓãfYf)ùr@;ý€w r…Ûu¨tƒÀƒÖ)í)Û÷Æ ufâf ÊÁâæÿÿ ò^_]Ã)Ò‰Ð@^_]ÃÑîÑØÑÝÑÛfAfùu¬ºàÿ)À^_]Àé ­Ý­ûÓïøƒÖ‡Ýé=ÿÿÿ¤Æ¤è@¤ÝÁã€ér±éJÿÿÿ)í€ù s­Ý­ûÓï÷ÝØþ)Ûf‰Ñfáÿé&ÿÿÿ€é ­Ý­ûÓï÷@Û÷݃ÛøƒÞ‡Ýf‰Ñfáÿéÿÿÿé]ÿÿÿëþéVÿÿÿUWV‰Ö‰ÏÁêÁéf‰Õf1Ífåf@âÿtÕfáÿtÎfÑférËfùÿwÂæÿÿçÿÿÎÏfQfU‰Á÷ã‰Õ“n÷æPR‰ð÷ç‰Ö‘÷çÅXЃÖZÕȃÖfZfYfƒÁ épþÿÿdev86-0.16.17/as/obj1/imul.obj0000644000000000000000000000022305060271414015454 0ustar rootroot00000000000000£†*"mUUUUmimul @öëö.f÷ëf÷.÷ë÷.f¯Ãf¯¯Ã¯fkÃfkkÃkgf¯g¯fkÀkÀfimÃ,fi,iÃà“ià“gf¯,¯à“fiÀ,iÀà“dev86-0.16.17/as/obj1/incdec.obj0000644000000000000000000000022205060271416015734 0ustar rootroot00000000000000£†*$jUUUUjincdec @þÀþÄþÃþÇþÁþÅþÂþÆgÿgþf@fCfAfBfDfEfFfGgfÿ@CABDEFGgÿþÈþÌþËþÏþÉþjÍþÊþÎgÿgþfHfKfIfJfLfMfNfOgfÿHKIJLMNOgÿdev86-0.16.17/as/obj1/calljmp.obj0000644000000000000000000000031005061127502016124 0ustar rootroot00000000000000£†*;ˆUUUUˆ@ˆ@ˆcalljmpREL16REL32 @š è|fÿÐfÿÓfÿÑfÿÒfÿÔfÿÕfÿÖfÿ×gÿgÿgfÿèUfÿÐfÿÓfÿÑfÿÒf@ÿÔfÿÕfÿÖfÿ×fÿê ë3ÿàÿãÿáÿâÿäÿåÿæÿçÿ'ÿ'ÿ'ëfÿàfÿãfÿáfÿâfÿäfÿåfHÿæfÿçfÿ'dev86-0.16.17/as/obj1/shift.obj0000644000000000000000000000046405060271420015627 0ustar rootroot00000000000000£†*# UUUU shift @ÒÐÒÔÒÓÒ×ÒÑÒÕÒÒÒÖgÓgÒfÓÐfÓÓfÓÑfÓÒfÓÔfÓÕfÓÖfÓ×gfÓÓÐÓÓÓÑÓÒÓÔÓÕÓÖ@Ó×gÓÐÐÐÔÐÓÐ×ÐÑÐÕÐÒÐÖgÑgÐfÑÐfÑÓfÑÑfÑÒfÑÔfÑÕfÑÖfÑ×gfÑÑÐÑÓÑÑÑÒÑ@ÔÑÕÑÖÑ×gÑÀÐÀÔÀÓÀ×ÀÑÀÕÀÒÀÖgÁgÀÀÐfÁÐfÁÓfÁÑfÁÒfÁÔ@fÁÕfÁÖfÁ×gfÁÁÐÁÓÁÑÁÒÁÔÁÕÁÖÁ×gÁfÁØfÁÀfÁÈfÁàfÁJøfÁàfÁèdev86-0.16.17/as/obj1/group1.obj0000644000000000000000000000022105060271413015720 0ustar rootroot00000000000000£†*$iUUUUigroup1 @f4xV4€ÃfÃ4ÃxV4g€g€Gg€gf4gxV4g€gfƒýgƒýiÙfÙÙggfgggfgÙ Ù8ÙÙ(ÙÙ0Ùdev86-0.16.17/as/obj1/movspec.obj0000644000000000000000000000132205060271416016165 0ustar rootroot00000000000000£†*% UUUU movspec @ À Ð Ø!À!È!Ð!Ø!ð!ø$Ø$à$è$ð$ø"À"Ð"Ø#À#È#Ð#Ø@#ð#ø&Ø&à&è&ð&ø Ã Ó Û!Ã!Ë!Ó!Û!ó!û$Û$ã$ë$ó$û"@Ã"Ó"Û#Ã#Ë#Ó#Û#ó#û&Û&ã&ë&ó&û Á Ñ Ù!Á!É!Ñ!Ù!ñ@!ù$Ù$á$é$ñ$ù"Á"Ñ"Ù#Á#É#Ñ#Ù#ñ#ù&Ù&á&é&ñ&ù Â@ Ò Ú!Â!Ê!Ò!Ú!ò!ú$Ú$â$ê$ò$ú"Â"Ò"Ú#Â#Ê#Ò#Ú#ò#@ú&Ú&â&ê&ò&ú Æ Ö Þ!Æ!Î!Ö!Þ!ö!þ$Þ$æ$î$ö$þ"Æ"Ö@"Þ#Æ#Î#Ö#Þ#ö#þ&Þ&æ&î&ö&þ Ç × ß!Ç!Ï!×!ß!÷!ÿ@$ß$ç$ï$÷$ÿ"Ç"×"ß#Ç#Ï#×#ß#÷#ÿ&ß&ç&ï&÷&ÿ Ä Ô @Ü!Ä!Ì!Ô!Ü!ô!ü$Ü$ä$ì$ô$ü"Ä"Ô"Ü#Ä#Ì#Ô#Ü#ô#ü&Ü@&ä&ì&ô&ü Å Õ Ý!Å!Í!Õ!Ý!õ!ý$Ý$å$í$õ$ý"Å"Õ"Ý`#Å#Í#Õ#Ý#õ#ý&Ý&å&í&õ&ýdev86-0.16.17/as/obj1/inher.obj0000644000000000000000000000023605060271416015621 0ustar rootroot00000000000000£†*#wUUUUwinher @7?øüúõ¦'/ôÎlŸÉð¬¤nóóòž®ùýûª›˜™f˜f™§f§mfmÏfÏ­f­¥f¥ofoafaf`f`wœfœ¯f¯««××f˜f™˜™f§§fmmfÏÏf­­f¥¥foofaaff``fœœf¯¯f«f«××dev86-0.16.17/as/obj1/seg.obj0000644000000000000000000000005205060271417015267 0ustar rootroot00000000000000£†*!UUUUseg F.>&de6dev86-0.16.17/as/obj1/inout.obj0000644000000000000000000000012205060271416015644 0ustar rootroot00000000000000£†*#,UUUU,inout líììfífííä äfå fåå åïîîfïfïïæ æfç fçeç çdev86-0.16.17/as/obj1/group6.obj0000644000000000000000000000010305060271413015724 0ustar rootroot00000000000000£†*$UUUUgroup6 \ÐgÛgF ág,dev86-0.16.17/as/genobj.c0000644000000000000000000003424007615574767014626 0ustar rootroot00000000000000/* genobj.c - object code generation routines for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "file.h" #include "globvar.h" #define OBJBUFSIZE 512 /* size of object code output buffer */ #define isge2byteoffset(offset) ((offset) >= 0x100) #define isge4byteoffset(offset) ((offset) >= 0x10000L) PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */ PRIVATE char *absbuf; /* start */ PRIVATE char *absbufend; /* last location + 1 */ PRIVATE char *absbufptr; /* current location */ PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */ PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */ PRIVATE unsigned numext; /* number of external symbols */ PRIVATE char *objbuf; /* start */ PRIVATE char *objbufend; /* last location + 1 */ PRIVATE char *objbufptr; /* current location */ PRIVATE unsigned char relsize; /* current relocation size, 0 init */ /* local to genobjadr, but here */ /* because of static re-init bug */ PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */ FORWARD void flushabs P((void)); FORWARD void flushrmb P((void)); FORWARD void genobjadr P((struct address_s *adrptr, int size)); FORWARD void putobj1 P((opcode_pt ch)); FORWARD void putobj4 P((u32_T offset)); FORWARD void putobjoffset P((offset_t offset, count_t size)); FORWARD void putobjword P((unsigned word)); FORWARD void writeobj P((char *buf, unsigned count)); /* accumulate RMB requests into 1 (so + and - requests cancel) */ PUBLIC void accumulate_rmb(offset) offset_t offset; { if (objectc) { flushabs(); rmbcount += offset; } } /* flush absolute object code buffer to object code buffer if necessary */ PRIVATE void flushabs() { if (absbufptr > absbuf) { putobj1((absbufptr - absbuf) | OBJ_ABS); { register char *bufptr; bufptr = absbuf; do putobj1(*bufptr); while (++bufptr < absbufptr); absbufptr = absbuf; } } } /* flush object code buffer if necessary */ PUBLIC void flushobj() { int ntowrite; if ((ntowrite = objbufptr - objbuf) > 0) { if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite) { error(OBJOUT); listline(); finishup(); } objbufptr = objbuf; } } /* flush RMB count if necessary */ PRIVATE void flushrmb() { count_t size; if (rmbcount != 0) { #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(rmbcount)) { putobj1(OBJ_SKIP_4); size = 4; } else #endif if (isge2byteoffset(rmbcount)) { putobj1(OBJ_SKIP_2); size = 2; } else { putobj1(OBJ_SKIP_1); size = 1; } putobjoffset(rmbcount, size); rmbcount = 0; } } /* generate object code for current line */ /* any address parameter is (regrettably) in lastexp any immediate parameter is (corectly) in immadr */ PUBLIC void genobj() { struct address_s *adrptr; char *bufptr; unsigned char remaining; if (objectc && mcount != 0) { if (popflags) { if (fcflag) { bufptr = databuf.fcbuf; remaining = mcount; do putabs(*bufptr++); while (--remaining != 0); } if (fdflag) { adrptr = databuf.fdbuf; remaining = mcount; do genobjadr(adrptr++, 2); while ((remaining -= 2) != 0); } #if SIZEOF_OFFSET_T > 2 if (fqflag) { adrptr = databuf.fqbuf; remaining = mcount; do genobjadr(adrptr++, 4); while ((remaining -= 4) != 0); } #endif } else { remaining = mcount - 1; /* count opcode immediately */ #ifdef I80386 if (aprefix != 0) { putabs(aprefix); --remaining; } if (oprefix != 0) { putabs(oprefix); --remaining; } if (sprefix != 0) { putabs(sprefix); --remaining; } #endif if (page != 0) { putabs(page); --remaining; } putabs(opcode); if (remaining != 0) { if (postb != 0) { putabs(postb); --remaining; } #ifdef I80386 if (sib != NO_SIB) { putabs(sib); --remaining; } #endif if (remaining != 0) genobjadr(&lastexp, remaining); } } #ifdef I80386 if (immcount != 0) genobjadr(&immadr, immcount); #endif } } /* generate object code for current address */ PRIVATE void genobjadr(adrptr, size) struct address_s *adrptr; smallcount_t size; { unsigned char byte; unsigned symnum; if (!(adrptr->data & RELBIT)) { /* absolute address */ char buf[sizeof(offset_t)]; #if SIZEOF_OFFSET_T > 2 u4cn(buf, adrptr->offset, size); #else u2cn(buf, adrptr->offset, size); #endif putabs(buf[0]); if (size > 1) putabs(buf[1]); if (size > 2) { putabs(buf[2]); putabs(buf[3]); } } else { /* relocatable address */ if (size != relsize) /* set reloc size index |00|0000xx| */ putobj((relsize = size) == 4 ? 0x03 : relsize); if (!(adrptr->data & IMPBIT)) { /* offset relocation (known offset) */ putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag); putobjoffset(adrptr->offset, size); } else { /* symbol relocation (imported symbol + offset) */ { register struct sym_s **copyptr; for (copyptr = arrext, symnum = 0; symnum < numext && *copyptr++ != adrptr->sym; ++symnum) ; } byte = OBJ_SYMBOL_REL; if (isge2byteoffset(symnum)) byte = OBJ_SYMBOL_REL | OBJ_S_MASK; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(adrptr->offset)) { byte |= 0x03; /* 4 byte offset */ size = 4; } else #endif if (isge2byteoffset(adrptr->offset)) { byte |= 0x02; /* 2 byte offset */ size = 2; } else if (adrptr->offset != 0) { byte |= 0x01; /* 1 byte offset */ size = 1; } else size = 0; putobj(byte | pcrflag); if (isge2byteoffset(symnum)) putobjword(symnum); else putobj1((opcode_pt) symnum); if (adrptr->offset != 0) putobjoffset(adrptr->offset, size); } } } /* initialise private variables */ PUBLIC void initobj() { absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf; objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf; } /* write header to object file also build array of imported/exported symbols */ PUBLIC void objheader() { static char module_header[] = { #ifdef I80386 0xA3, 0x86, 1, 0, (char) (0xA3 + 0x86 + 1 + 0), #endif #ifdef MC6809 'S', '1', /* 2 byte magic number */ 0, 1, /* 2 byte number of modules in file */ 'S' + '1' + 0 + 1, /* 1 byte checksum */ #endif }; static char seg_max_sizes[] = { 0x55, /* all segments have maximum size 2^16 */ 0x55, /* this is encoded by 0b01 4 times per byte */ 0x55, /* other codes are 0b00 = max size 2^8 */ 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */ }; unsigned char byte; register struct sym_s **copyptr; struct sym_s **copytop; struct sym_s **hashptr; struct lc_s *lcp; char module_name[FILNAMLEN + 1]; char *nameptr; unsigned offset; unsigned segsizebytes; unsigned size; unsigned char sizebits; unsigned strsiz; /* size of object string table */ unsigned symosiz; /* size of object symbol table */ register struct sym_s *symptr; u32_T textlength; int symcount = 0; if ((objectc = objectg) == 0) return; writeobj(module_header, sizeof module_header); /* calculate number of imported/exported symbols */ /* and lengths of symbol and string tables */ /* build array of imported/exported symbols */ symosiz = 0; if (truefilename == NUL_PTR) truefilename = filnamptr; nameptr = strrchr(truefilename, DIRCHAR); strcpy(module_name, nameptr != NUL_PTR ? nameptr + 1 : truefilename); if ((nameptr = strrchr(module_name, '.')) != NUL_PTR) *nameptr = 0; strsiz = strlen(module_name) + 1; for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do { if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || (!globals_only_in_obj && symptr->name[0] != '.' && !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))) { symcount ++; } } while ((symptr = symptr->next) != NUL_PTR); arrext = copyptr = asalloc( sizeof(struct sym_s *) * symcount); for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do { if ((symptr->type & EXPBIT || symptr->data & IMPBIT) || (!globals_only_in_obj && symptr->name[0] != '.' && !(symptr->type & (MNREGBIT | MACBIT | VARBIT)))) { *copyptr++ = symptr; strsiz += symptr->length + 1; if (textseg>=0 && (symptr->data & SEGM) == textseg) strsiz+=2; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(symptr->value_reg_or_op.value)) size = 4 + 4; /* 4 is size of offset into string table and flags */ /* 2nd 4 is for 4 byte offset */ else #endif if (isge2byteoffset(symptr->value_reg_or_op.value)) size = 4 + 2; else if (symptr->value_reg_or_op.value != 0) size = 4 + 1; else size = 4; symosiz += size; ++numext; } } while ((symptr = symptr->next) != NUL_PTR); copytop = copyptr; /* calculate length of text, and number of seg size bytes in header */ textlength = segsizebytes = 0; lcp = lctab; do if (lcp->lc != 0) { textlength += lcp->lc; /* assuming text starts at 0 */ #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(lcp->lc)) segsizebytes += 4; else #endif segsizebytes += 2; /* use 2 byte size if possible */ } while (++lcp < lctabtop); /* offset to text = length of header since only 1 module header consists of: module header sizeof module_header offset to start of text 4 length of text 4 length of string area 2 class 1 revision 1 seg max sizes sizeof seg_max_sizes seg size descriptors 4 seg sizes segsizebytes symbol count 2 symbol offsets and types symosiz strings strsiz */ /* offset to start of text */ putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 + sizeof seg_max_sizes + 4 + segsizebytes + 2 + symosiz) + strsiz); /* length of text */ putobj4((u32_T) textlength); /* length of string area */ putobjword(strsiz); /* class and revision */ putobj1(0); putobj1(0); /* segment max sizes (constant) */ writeobj(seg_max_sizes, sizeof seg_max_sizes); /* segment size descriptors */ /* produce only 0 and 2 byte sizes */ lcp = lctabtop; byte = 0; sizebits = OBJ_SEGSZ_TWO << 6; do { --lcp; if (lcp->lc != 0) { byte |= sizebits; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(lcp->lc)) byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */ #endif } if ((sizebits >>= 2) == 0) { putobj1(byte); byte = 0; sizebits = OBJ_SEGSZ_TWO << 6; } } while (lcp > lctab); /* segment sizes */ do /* lcp starts at lctab */ if (lcp->lc != 0) { #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(lcp->lc)) putobj4(lcp->lc); else #endif putobjword((unsigned) lcp->lc); } while (++lcp < lctabtop); /* symbol count */ putobjword(numext); /* symbol offsets and types */ offset = strlen(module_name) + 1; /* 1st symbol begins after name */ for (copyptr = arrext; copyptr < copytop;) { putobjword(offset); symptr = *copyptr++; byte = symptr->type & OBJ_N_MASK; #if SIZEOF_OFFSET_T > 2 if (isge4byteoffset(symptr->value_reg_or_op.value)) { byte |= OBJ_SZ_FOUR; size = 4; } else #endif if (isge2byteoffset(symptr->value_reg_or_op.value)) { byte |= OBJ_SZ_TWO; size = 2; } else if (symptr->value_reg_or_op.value != 0) { byte |= OBJ_SZ_ONE; size = 1; } else size = 0; if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) { byte |= OBJ_SA_MASK; symptr->data &= ~OBJ_I_MASK; } putobjword((unsigned) (byte << 0x8) | (symptr->type & OBJ_E_MASK) | /* |E|0000000| */ ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^ /* |0|I|0|A|SEGM| */ RELBIT)); /* RELBIT by negative logic */ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT)) symptr->data |= OBJ_I_MASK; if (size != 0) putobjoffset(symptr->value_reg_or_op.value, size); offset += symptr->length + 1; if (textseg>=0 && (symptr->data & SEGM) == textseg) offset+=2; } /* strings */ writeobj(module_name, strlen(module_name)); putobj1(0); for (copyptr = arrext; copyptr < copytop;) { symptr = *copyptr++; writeobj(symptr->name, symptr->length); if (textseg>=0 && (symptr->data & SEGM) == textseg) { putobj1('.'); putobj1(hexdigit[textseg]); } putobj1(0); } putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */ } /* write trailer to object file */ PUBLIC void objtrailer() { if (objectc) { putobj(0); /* end of object file */ flushobj(); } } /* write char to absolute object code buffer, flush if necessary */ PUBLIC void putabs(ch) opcode_pt ch; { if (objectc) { if (rmbcount != 0) flushrmb(); if (absbufptr >= absbufend) flushabs(); *absbufptr++ = ch; } } /* write char to object code buffer, flush if necessary */ PUBLIC void putobj(ch) opcode_pt ch; { if (objectc) { flushabs(); flushrmb(); putobj1(ch); } } /* write char to object code buffer assuming nothing in absolute & rmb bufs */ PRIVATE void putobj1(ch) opcode_pt ch; { if (objbufptr >= objbufend) flushobj(); *objbufptr++ = ch; } /* write 32 bit offset to object code buffer assuming ... */ PRIVATE void putobj4(offset) u32_T offset; { char buf[sizeof offset]; u4c4(buf, offset); writeobj(buf, 4); } /* write sized offset to object code buffer assuming ... */ PRIVATE void putobjoffset(offset, size) offset_t offset; count_t size; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 2 u4cn(buf, offset, size); #else u2cn(buf, offset, size); #endif putobj1(buf[0]); if (size > 1) putobj1(buf[1]); if (size > 2) { putobj1(buf[2]); putobj1(buf[3]); } } /* write word to object code buffer assuming ... */ PRIVATE void putobjword(word) unsigned word; { char buf[sizeof word]; u2c2(buf, word); putobj1(buf[0]); putobj1(buf[1]); } /* write several bytes to object code buffer assuming ... */ PRIVATE void writeobj(buf, count) char *buf; unsigned count; { do putobj1(*buf++); while (--count); } dev86-0.16.17/as/keywords.c0000644000000000000000000006512607606510133015211 0ustar rootroot00000000000000/* keywords.c - keyword tables for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "opcode.h" /* --- start of keywords --- */ /* registers */ /* the register code (internal to assembler) is given in 1 byte */ /* the "opcode" field is not used */ PUBLIC char regs[] = { #ifdef I80386 2, 'B', 'P', BPREG, 0, 2, 'B', 'X', BXREG, 0, 2, 'D', 'I', DIREG, 0, 2, 'S', 'I', SIREG, 0, 3, 'E', 'A', 'X', EAXREG, 0, 3, 'E', 'B', 'P', EBPREG, 0, 3, 'E', 'B', 'X', EBXREG, 0, 3, 'E', 'C', 'X', ECXREG, 0, 3, 'E', 'D', 'I', EDIREG, 0, 3, 'E', 'D', 'X', EDXREG, 0, 3, 'E', 'S', 'I', ESIREG, 0, 3, 'E', 'S', 'P', ESPREG, 0, 2, 'A', 'X', AXREG, 0, 2, 'C', 'X', CXREG, 0, 2, 'D', 'X', DXREG, 0, 2, 'S', 'P', SPREG, 0, 2, 'A', 'H', AHREG, 0, 2, 'A', 'L', ALREG, 0, 2, 'B', 'H', BHREG, 0, 2, 'B', 'L', BLREG, 0, 2, 'C', 'H', CHREG, 0, 2, 'C', 'L', CLREG, 0, 2, 'D', 'H', DHREG, 0, 2, 'D', 'L', DLREG, 0, 2, 'C', 'S', CSREG, 0, 2, 'D', 'S', DSREG, 0, 2, 'E', 'S', ESREG, 0, 2, 'F', 'S', FSREG, 0, 2, 'G', 'S', GSREG, 0, 2, 'S', 'S', SSREG, 0, 3, 'C', 'R', '0', CR0REG, 0, 3, 'C', 'R', '2', CR2REG, 0, 3, 'C', 'R', '3', CR3REG, 0, 3, 'D', 'R', '0', DR0REG, 0, 3, 'D', 'R', '1', DR1REG, 0, 3, 'D', 'R', '2', DR2REG, 0, 3, 'D', 'R', '3', DR3REG, 0, 3, 'D', 'R', '6', DR6REG, 0, 3, 'D', 'R', '7', DR7REG, 0, 3, 'T', 'R', '3', TR3REG, 0, 3, 'T', 'R', '4', TR4REG, 0, 3, 'T', 'R', '5', TR5REG, 0, 3, 'T', 'R', '6', TR6REG, 0, 3, 'T', 'R', '7', TR7REG, 0, 2, 'S', 'T', ST0REG, 0, #endif /* I80386 */ #ifdef MC6809 1, 'A', AREG, 0, 1, 'B', BREG, 0, 2, 'C', 'C', CCREG, 0, 1, 'D', DREG, 0, 2, 'D', 'P', DPREG, 0, 2, 'P', 'C', PCREG, 0, 3, 'P', 'C', 'R', PCREG, 0, 1, 'S', SREG, 0, 1, 'U', UREG, 0, 1, 'X', XREG, 0, 1, 'Y', YREG, 0, #endif 0 /* end of register list */ }; #ifdef I80386 /* type sizes */ /* the "opcode" field gives the type size */ PUBLIC char typesizes[] = { 4, 'B', 'Y', 'T', 'E', BYTEOP, 1, 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4, 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6, 3, 'F', 'A', 'R', FAROP, 0, 4, 'N', 'E', 'A', 'R', WORDOP, 2, 3, 'P', 'T', 'R', PTROP, 0, 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6, 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8, 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10, 4, 'W', 'O', 'R', 'D', WORDOP, 2, 0 /* end of typesize list */ }; #endif /* ops */ /* the routine number is given in 1 byte */ /* the opcode is given in 1 byte (it is not used for pseudo-ops) */ PUBLIC char ops[] = { /* pseudo-ops. The "opcode" field is unused and padded with a null byte */ /* conditionals - must be first */ 4, 'E', 'L', 'S', 'E', ELSEOP, 0, 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0, 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0, 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0, 2, 'I', 'F', IFOP, 0, 3, 'I', 'F', 'C', IFCOP, 0, /* unconditionals */ 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0, 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0, 6, '.', 'A', 'S', 'C', 'I', 'Z', ASCIZOP, 0, 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0, 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0, 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0, 4, '.', 'B', 'S', 'S', BSSOP, 0, 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0, 4, 'C', 'O', 'M', 'M', COMMOP, 0, 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0, 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0, 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0, 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0, #if SIZEOF_OFFSET_T > 2 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0, #endif 2, 'D', 'B', FCBOP, 0, #if SIZEOF_OFFSET_T > 2 2, 'D', 'D', FQBOP, 0, #endif 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0, 2, 'D', 'W', FDBOP, 0, 3, 'E', 'N', 'D', PROCEOFOP, 0, 4, 'E', 'N', 'D', 'B', ENDBOP, 0, 6, '.', 'E', 'N', 'T', 'E', 'R', ENTEROP, 0, 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0, 3, 'E', 'Q', 'U', EQUOP, 0, 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0, 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0, 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0, 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0, 4, 'F', 'A', 'I', 'L', FAILOP, 0, 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0, 3, 'F', 'C', 'B', FCBOP, 0, 3, 'F', 'C', 'C', FCCOP, 0, 3, 'F', 'D', 'B', FDBOP, 0, 3, 'G', 'E', 'T', GETOP, 0, 7, '.', 'G', 'L', 'O', 'B', 'A', 'L', GLOBLOP, 0, 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0, 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0, 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0, 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0, 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0, 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0, 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0, 3, 'L', 'O', 'C', LOCOP, 0, #if SIZEOF_OFFSET_T > 2 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0, #endif 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0, 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0, 4, '.', 'M', 'A', 'P', MAPOP, 0, 3, 'O', 'R', 'G', ORGOP, 0, 4, '.', 'O', 'R', 'G', ORGOP, 0, 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0, 3, 'R', 'M', 'B', RMBOP, 0, 4, '.', 'R', 'O', 'M', DATAOP, 0, 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0, 3, 'S', 'E', 'T', SETOP, 0, 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0, 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0, 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0, 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0, #ifndef MC6809 5, 'U', 'S', 'E', '1', '6', USE16OP, 0, 5, 'U', 'S', 'E', '3', '2', USE32OP, 0, #endif 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0, 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0, 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0, /* hardware ops. The opcode field is now used */ #ifdef I80386 3, 'A', 'A', 'A', INHER, 0x37, 3, 'A', 'A', 'D', INHER_A, 0xD5, 3, 'A', 'A', 'M', INHER_A, 0xD4, 3, 'A', 'A', 'S', INHER, 0x3F, 3, 'A', 'D', 'C', GROUP1, 0x10, 3, 'A', 'D', 'D', GROUP1, 0x00, 3, 'A', 'N', 'D', GROUP1, 0x20, 4, 'A', 'R', 'P', 'L', EwGw, 0x63, 3, 'B', 'C', 'C', BCC, 0x73, 3, 'B', 'C', 'S', BCC, 0x72, 3, 'B', 'E', 'Q', BCC, 0x74, 3, 'B', 'G', 'E', BCC, 0x7D, 3, 'B', 'G', 'T', BCC, 0x7F, 3, 'B', 'H', 'I', BCC, 0x77, 4, 'B', 'H', 'I', 'S', BCC, 0x73, 3, 'B', 'L', 'E', BCC, 0x7E, 3, 'B', 'L', 'O', BCC, 0x72, 4, 'B', 'L', 'O', 'S', BCC, 0x76, 3, 'B', 'L', 'T', BCC, 0x7C, 3, 'B', 'M', 'I', BCC, 0x78, 3, 'B', 'N', 'E', BCC, 0x75, 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62, 3, 'B', 'P', 'C', BCC, 0x7B, 3, 'B', 'P', 'L', BCC, 0x79, 3, 'B', 'P', 'S', BCC, 0x7A, 2, 'B', 'R', CALL, JMP_OPCODE, 3, 'B', 'V', 'C', BCC, 0x71, 3, 'B', 'V', 'S', BCC, 0x70, 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE, 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A, 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A, 3, 'C', 'B', 'W', INHER16, 0x98, 3, 'C', 'L', 'C', INHER, 0xF8, 3, 'C', 'L', 'D', INHER, 0xFC, 3, 'C', 'L', 'I', INHER, 0xFA, 3, 'C', 'M', 'C', INHER, 0xF5, 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE, 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE, 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE, 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE, 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE, 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE, 4, 'C', 'S', 'E', 'G', INHER, 0x2E, 3, 'C', 'W', 'D', INHER16, 0x99, 4, 'C', 'W', 'D', 'E', INHER32, 0x98, 3, 'C', 'D', 'Q', INHER32, 0x99, 3, 'D', 'A', 'A', INHER, 0x27, 3, 'D', 'A', 'S', INHER, 0x2F, 4, 'D', 'S', 'E', 'G', INHER, 0x3E, 3, 'D', 'E', 'C', INCDEC, 0x08, 3, 'D', 'I', 'V', DIVMUL, 0x30, 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8, 4, 'E', 'S', 'E', 'G', INHER, 0x26, 4, 'F', 'S', 'E', 'G', INHER, 0x64, 4, 'G', 'S', 'E', 'G', INHER, 0x65, 3, 'H', 'L', 'T', INHER, 0xF4, 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38, 4, 'I', 'M', 'U', 'L', IMUL, 0x28, 2, 'I', 'N', IN, 0xEC, 3, 'I', 'N', 'C', INCDEC, 0x00, 3, 'I', 'N', 'S', INHER, 0x6D, 4, 'I', 'N', 'S', 'B', INHER, 0x6C, 4, 'I', 'N', 'S', 'D', INHER32, 0x6D, 4, 'I', 'N', 'S', 'W', INHER16, 0x6D, 3, 'I', 'N', 'T', INT, 0xCD, 4, 'I', 'N', 'T', 'O', INHER, 0xCE, 3, 'I', 'N', 'W', IN, 0xED, 4, 'I', 'R', 'E', 'T', INHER16, 0xCF, 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF, 1, 'J', CALL, JMP_SHORT_OPCODE, 2, 'J', 'A', JCC, 0x77, 3, 'J', 'A', 'E', JCC, 0x73, 2, 'J', 'B', JCC, 0x72, 3, 'J', 'B', 'E', JCC, 0x76, 2, 'J', 'C', JCC, 0x72, 4, 'J', 'C', 'X', 'E', JCXZ, 0x2, 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2, 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4, 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4, 2, 'J', 'E', JCC, 0x74, 2, 'J', 'G', JCC, 0x7F, 3, 'J', 'G', 'E', JCC, 0x7D, 2, 'J', 'L', JCC, 0x7C, 3, 'J', 'L', 'E', JCC, 0x7E, 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE, 4, 'J', 'M', 'P', 'F', CALLI, 0xEA, 4, 'J', 'M', 'P', 'I', CALLI, 0xEA, 3, 'J', 'N', 'A', JCC, 0x76, 4, 'J', 'N', 'A', 'E', JCC, 0x72, 3, 'J', 'N', 'B', JCC, 0x73, 4, 'J', 'N', 'B', 'E', JCC, 0x77, 3, 'J', 'N', 'C', JCC, 0x73, 3, 'J', 'N', 'E', JCC, 0x75, 3, 'J', 'N', 'G', JCC, 0x7E, 4, 'J', 'N', 'G', 'E', JCC, 0x7C, 3, 'J', 'N', 'L', JCC, 0x7D, 4, 'J', 'N', 'L', 'E', JCC, 0x7F, 3, 'J', 'N', 'O', JCC, 0x71, 3, 'J', 'N', 'P', JCC, 0x7B, 3, 'J', 'N', 'S', JCC, 0x79, 3, 'J', 'N', 'Z', JCC, 0x75, 2, 'J', 'O', JCC, 0x70, 2, 'J', 'P', JCC, 0x7A, 3, 'J', 'P', 'E', JCC, 0x7A, 3, 'J', 'P', 'O', JCC, 0x7B, 2, 'J', 'S', JCC, 0x78, 2, 'J', 'Z', JCC, 0x74, 4, 'L', 'A', 'H', 'F', INHER, 0x9F, 3, 'L', 'D', 'S', GvMp, 0xC5, 3, 'L', 'E', 'A', LEA, 0x8D, 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9, 3, 'L', 'E', 'S', GvMp, 0xC4, 4, 'L', 'O', 'C', 'K', INHER, 0xF0, 4, 'L', 'O', 'D', 'B', INHER, 0xAC, 4, 'L', 'O', 'D', 'S', INHER, 0xAD, 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC, 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD, 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD, 4, 'L', 'O', 'D', 'W', INHER16, 0xAD, 4, 'L', 'O', 'O', 'P', JCC, 0xE2, 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1, 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0, 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0, 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1, 3, 'M', 'O', 'V', MOV, 0x88, 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE, 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE, 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE, 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE, 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE, 3, 'M', 'U', 'L', DIVMUL, 0x20, 3, 'N', 'E', 'G', NEGNOT, 0x18, 3, 'N', 'O', 'P', INHER, 0x90, 3, 'N', 'O', 'T', NEGNOT, 0x10, 2, 'O', 'R', GROUP1, 0x08, 3, 'O', 'U', 'T', OUT, 0xEE, 4, 'O', 'U', 'T', 'S', INHER, 0x6F, 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E, 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F, 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F, 4, 'O', 'U', 'T', 'W', OUT, 0xEF, 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE, 4, 'P', 'O', 'P', 'A', INHER16, 0x61, 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61, 4, 'P', 'O', 'P', 'F', INHER16, 0x9D, 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D, 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE, 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60, 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60, 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C, 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C, 3, 'R', 'C', 'L', GROUP2, 0x10, 3, 'R', 'C', 'R', GROUP2, 0x18, 3, 'R', 'O', 'L', GROUP2, 0x00, 3, 'R', 'O', 'R', GROUP2, 0x08, 3, 'R', 'E', 'P', INHER, 0xF3, 4, 'R', 'E', 'P', 'E', INHER, 0xF3, 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2, 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2, 4, 'R', 'E', 'P', 'Z', INHER, 0xF3, 3, 'R', 'E', 'T', RET, 0xC3, 4, 'R', 'E', 'T', 'F', RET, 0xCB, 4, 'R', 'E', 'T', 'I', RET, 0xCB, 4, 'S', 'A', 'H', 'F', INHER, 0x9E, 3, 'S', 'A', 'L', GROUP2, 0x20, 3, 'S', 'A', 'R', GROUP2, 0x38, 3, 'S', 'B', 'B', GROUP1, 0x18, 4, 'S', 'C', 'A', 'B', INHER, 0xAE, 4, 'S', 'C', 'A', 'S', INHER, 0xAF, 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE, 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF, 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF, 4, 'S', 'C', 'A', 'W', INHER16, 0xAF, 3, 'S', 'E', 'G', SEG, 0x06, 3, 'S', 'H', 'L', GROUP2, 0x20, 3, 'S', 'H', 'R', GROUP2, 0x28, 4, 'S', 'S', 'E', 'G', INHER, 0x36, 3, 'S', 'T', 'C', INHER, 0xF9, 3, 'S', 'T', 'D', INHER, 0xFD, 3, 'S', 'T', 'I', INHER, 0xFB, 4, 'S', 'T', 'O', 'B', INHER, 0xAA, 4, 'S', 'T', 'O', 'S', INHER, 0xAB, 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA, 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB, 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB, 4, 'S', 'T', 'O', 'W', INHER16, 0xAB, 3, 'S', 'U', 'B', GROUP1, 0x28, 4, 'T', 'E', 'S', 'T', TEST, 0x84, 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, 4, 'X', 'C', 'H', 'G', XCHG, 0x86, 4, 'X', 'L', 'A', 'T', INHER, 0xD7, 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7, 3, 'X', 'O', 'R', GROUP1, 0x30, /* floating point */ 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70, 4, 'F', 'A', 'B', 'S', F_INHER, 0x61, 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00, 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60, 4, 'F', 'B', 'L', 'D', F_M10, 0x74, 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76, 4, 'F', 'C', 'H', 'S', F_INHER, 0x60, 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2, 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02, 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03, 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19, 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F, 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76, 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1, 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06, 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67, 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07, 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66, 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0, 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50, 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20, 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22, 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23, 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26, 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27, 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30, 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21, 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77, 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3, 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32, 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33, 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24, 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25, 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10, 4, 'F', 'L', 'D', '1', F_INHER, 0x68, 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A, 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69, 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15, 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14, 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C, 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D, 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B, 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E, 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01, 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61, 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2, 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1, 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0, 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3, 4, 'F', 'N', 'O', 'P', F_INHER, 0x50, 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56, 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17, 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16, 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57, 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73, 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78, 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75, 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72, 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C, 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54, 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56, 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D, 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4, 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E, 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B, 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A, 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED, 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17, 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16, 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED, 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57, 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04, 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65, 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05, 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64, 4, 'F', 'T', 'S', 'T', F_INHER, 0x64, 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54, 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55, 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9, 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE, 4, 'F', 'X', 'A', 'M', F_INHER, 0x65, 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11, 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74, 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71, 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79, #endif /* I80386 */ #ifdef MC6809 3, 'A', 'B', 'X', INHER, 0x3A, 4, 'A', 'D', 'C', 'A', ALL, 0x89, 4, 'A', 'D', 'C', 'B', ALL, 0xC9, 4, 'A', 'D', 'D', 'A', ALL, 0x8B, 4, 'A', 'D', 'D', 'B', ALL, 0xCB, 4, 'A', 'D', 'D', 'D', ALL, 0xC3, 4, 'A', 'N', 'D', 'A', ALL, 0x84, 4, 'A', 'N', 'D', 'B', ALL, 0xC4, 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C, 3, 'A', 'S', 'L', ALTER, 0x08, 4, 'A', 'S', 'L', 'A', INHER, 0x48, 4, 'A', 'S', 'L', 'B', INHER, 0x58, 3, 'A', 'S', 'R', ALTER, 0x07, 4, 'A', 'S', 'R', 'A', INHER, 0x47, 4, 'A', 'S', 'R', 'B', INHER, 0x57, 3, 'B', 'C', 'C', SHORT, 0x24, 3, 'B', 'C', 'S', SHORT, 0x25, 3, 'B', 'E', 'Q', SHORT, 0x27, 3, 'B', 'G', 'E', SHORT, 0x2C, 3, 'B', 'G', 'T', SHORT, 0x2E, 3, 'B', 'H', 'I', SHORT, 0x22, 3, 'B', 'H', 'S', SHORT, 0x24, 4, 'B', 'I', 'T', 'A', ALL, 0X85, 4, 'B', 'I', 'T', 'B', ALL, 0XC5, 3, 'B', 'L', 'E', SHORT, 0x2F, 3, 'B', 'L', 'O', SHORT, 0x25, 3, 'B', 'L', 'S', SHORT, 0x23, 3, 'B', 'L', 'T', SHORT, 0x2D, 3, 'B', 'M', 'I', SHORT, 0x2B, 3, 'B', 'N', 'E', SHORT, 0x26, 3, 'B', 'P', 'L', SHORT, 0x2A, 3, 'B', 'R', 'A', SHORT, 0x20, 4, 'L', 'B', 'R', 'A', LONG, 0x16, 3, 'B', 'R', 'N', SHORT, 0x21, 3, 'B', 'S', 'R', SHORT, 0x8D, 4, 'L', 'B', 'S', 'R', LONG, 0x17, 3, 'B', 'V', 'C', SHORT, 0x28, 3, 'B', 'V', 'S', SHORT, 0x29, 3, 'C', 'L', 'R', ALTER, 0x0F, 4, 'C', 'L', 'R', 'A', INHER, 0x4F, 4, 'C', 'L', 'R', 'B', INHER, 0x5F, 4, 'C', 'M', 'P', 'A', ALL, 0x81, 4, 'C', 'M', 'P', 'B', ALL, 0xC1, 4, 'C', 'M', 'P', 'X', ALL, 0x8C, 3, 'C', 'O', 'M', ALTER, 0x03, 4, 'C', 'O', 'M', 'A', INHER, 0x43, 4, 'C', 'O', 'M', 'B', INHER, 0x53, 4, 'C', 'W', 'A', 'I', IMMED, 0x3C, 3, 'D', 'A', 'A', INHER, 0x19, 3, 'D', 'E', 'C', ALTER, 0x0A, 4, 'D', 'E', 'C', 'A', INHER, 0x4A, 4, 'D', 'E', 'C', 'B', INHER, 0x5A, 4, 'E', 'O', 'R', 'A', ALL, 0x88, 4, 'E', 'O', 'R', 'B', ALL, 0xC8, 3, 'E', 'X', 'G', SWAP, 0x1E, 3, 'I', 'N', 'C', ALTER, 0x0C, 4, 'I', 'N', 'C', 'A', INHER, 0x4C, 4, 'I', 'N', 'C', 'B', INHER, 0x5C, 3, 'J', 'M', 'P', ALTER, 0x0E, 3, 'J', 'S', 'R', ALTER, 0x8D, 3, 'L', 'D', 'A', ALL, 0x86, 3, 'L', 'D', 'B', ALL, 0xC6, 3, 'L', 'D', 'D', ALL, 0xCC, 3, 'L', 'D', 'U', ALL, 0xCE, 3, 'L', 'D', 'X', ALL, 0x8E, 4, 'L', 'E', 'A', 'S', INDEXD, 0x32, 4, 'L', 'E', 'A', 'U', INDEXD, 0x33, 4, 'L', 'E', 'A', 'X', INDEXD, 0x30, 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31, 3, 'L', 'S', 'L', ALTER, 0x08, 4, 'L', 'S', 'L', 'A', INHER, 0x48, 4, 'L', 'S', 'L', 'B', INHER, 0x58, 3, 'L', 'S', 'R', ALTER, 0x04, 4, 'L', 'S', 'R', 'A', INHER, 0x44, 4, 'L', 'S', 'R', 'B', INHER, 0x54, 3, 'M', 'U', 'L', INHER, 0x3D, 3, 'N', 'E', 'G', ALTER, 0x00, 4, 'N', 'E', 'G', 'A', INHER, 0x40, 4, 'N', 'E', 'G', 'B', INHER, 0x50, 3, 'N', 'O', 'P', INHER, 0x12, 3, 'O', 'R', 'A', ALL, 0x8A, 3, 'O', 'R', 'B', ALL, 0xCA, 4, 'O', 'R', 'C', 'C', IMMED, 0x1A, 4, 'P', 'S', 'H', 'S', SSTAK, 0x34, 4, 'P', 'S', 'H', 'U', USTAK, 0x36, 4, 'P', 'U', 'L', 'S', SSTAK, 0x35, 4, 'P', 'U', 'L', 'U', USTAK, 0x37, 3, 'R', 'O', 'L', ALTER, 0x09, 4, 'R', 'O', 'L', 'A', INHER, 0x49, 4, 'R', 'O', 'L', 'B', INHER, 0x59, 3, 'R', 'O', 'R', ALTER, 0x06, 4, 'R', 'O', 'R', 'A', INHER, 0x46, 4, 'R', 'O', 'R', 'B', INHER, 0x56, 3, 'R', 'T', 'I', INHER, 0x3B, 3, 'R', 'T', 'S', INHER, 0x39, 4, 'S', 'B', 'C', 'A', ALL, 0x82, 4, 'S', 'B', 'C', 'B', ALL, 0xC2, 3, 'S', 'E', 'X', INHER, 0x1D, 3, 'S', 'T', 'A', ALTER, 0x87, 3, 'S', 'T', 'B', ALTER, 0xC7, 3, 'S', 'T', 'D', ALTER, 0xCD, 3, 'S', 'T', 'U', ALTER, 0xCF, 3, 'S', 'T', 'X', ALTER, 0x8F, 4, 'S', 'U', 'B', 'A', ALL, 0x80, 4, 'S', 'U', 'B', 'B', ALL, 0xC0, 4, 'S', 'U', 'B', 'D', ALL, 0x83, 3, 'S', 'W', 'I', INHER, 0x3F, 4, 'S', 'Y', 'N', 'C', INHER, 0x13, 3, 'T', 'F', 'R', SWAP, 0x1F, 3, 'T', 'S', 'T', ALTER, 0x0D, 4, 'T', 'S', 'T', 'A', INHER, 0x4D, 4, 'T', 'S', 'T', 'B', INHER, 0x5D, #endif /* MC6809 */ 0 /* end of ops */ }; PUBLIC char page1ops[] = { #ifdef I80386 3, 'B', 'S', 'F', GvEv, 0xBC, 3, 'B', 'S', 'R', GvEv, 0xBD, 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8, 2, 'B', 'T', GROUP8, 0x20, 3, 'B', 'T', 'C', GROUP8, 0x38, 3, 'B', 'T', 'R', GROUP8, 0x30, 3, 'B', 'T', 'S', GROUP8, 0x28, 4, 'C', 'L', 'T', 'S', INHER, 0x06, 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6, 4, 'I', 'N', 'V', 'D', INHER, 0x08, 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38, 3, 'L', 'A', 'R', GvEv, 0x02, 3, 'L', 'F', 'S', GvMp, 0xB4, 4, 'L', 'G', 'D', 'T', GROUP7, 0x10, 3, 'L', 'G', 'S', GvMp, 0xB5, 4, 'L', 'I', 'D', 'T', GROUP7, 0x18, 4, 'L', 'L', 'D', 'T', GROUP6, 0x10, 4, 'L', 'M', 'S', 'W', GROUP7, 0x30, 3, 'L', 'S', 'L', GvEv, 0x03, 3, 'L', 'S', 'S', GvMp, 0xB2, 3, 'L', 'T', 'R', GROUP6, 0x18, 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE, 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6, 5, 'R', 'D', 'M', 'S', 'R', INHER, 0x32, 4, 'S', 'E', 'T', 'A', SETCC, 0x97, 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93, 4, 'S', 'E', 'T', 'B', SETCC, 0x92, 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96, 4, 'S', 'E', 'T', 'C', SETCC, 0x92, 4, 'S', 'E', 'T', 'E', SETCC, 0x94, 4, 'S', 'E', 'T', 'G', SETCC, 0x9F, 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D, 4, 'S', 'E', 'T', 'L', SETCC, 0x9C, 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E, 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96, 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92, 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93, 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97, 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93, 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95, 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E, 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C, 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D, 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F, 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91, 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B, 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99, 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95, 4, 'S', 'E', 'T', 'O', SETCC, 0x90, 4, 'S', 'E', 'T', 'P', SETCC, 0x9A, 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A, 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B, 4, 'S', 'E', 'T', 'S', SETCC, 0x98, 4, 'S', 'E', 'T', 'Z', SETCC, 0x94, 4, 'S', 'G', 'D', 'T', GROUP7, 0x00, 4, 'S', 'I', 'D', 'T', GROUP7, 0x08, 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4, 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC, 4, 'S', 'L', 'D', 'T', GROUP6, 0x00, 4, 'S', 'M', 'S', 'W', GROUP7, 0x20, 3, 'S', 'T', 'R', GROUP6, 0x08, 4, 'V', 'E', 'R', 'R', GROUP6, 0x20, 4, 'V', 'E', 'R', 'W', GROUP6, 0x28, 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09, 5, 'W', 'R', 'M', 'S', 'R', INHER, 0x30, 4, 'X', 'A', 'D', 'D', ExGx, 0xC0, #endif /* I80386 */ #ifdef MC6809 4, 'L', 'B', 'C', 'C', LONG, 0x24, 4, 'L', 'B', 'C', 'S', LONG, 0x25, 4, 'L', 'B', 'E', 'Q', LONG, 0x27, 4, 'L', 'B', 'G', 'E', LONG, 0x2C, 4, 'L', 'B', 'G', 'T', LONG, 0x2E, 4, 'L', 'B', 'H', 'I', LONG, 0x22, 4, 'L', 'B', 'H', 'S', LONG, 0x24, 4, 'L', 'B', 'L', 'E', LONG, 0x2F, 4, 'L', 'B', 'L', 'O', LONG, 0x25, 4, 'L', 'B', 'L', 'S', LONG, 0x23, 4, 'L', 'B', 'L', 'T', LONG, 0x2D, 4, 'L', 'B', 'M', 'I', LONG, 0x2B, 4, 'L', 'B', 'N', 'E', LONG, 0x26, 4, 'L', 'B', 'P', 'L', LONG, 0x2A, 4, 'L', 'B', 'R', 'N', LONG, 0x21, 4, 'L', 'B', 'V', 'C', LONG, 0x28, 4, 'L', 'B', 'V', 'S', LONG, 0x29, 4, 'C', 'M', 'P', 'D', ALL, 0x83, 4, 'C', 'M', 'P', 'Y', ALL, 0x8C, 3, 'L', 'D', 'S', ALL, 0xCE, 3, 'L', 'D', 'Y', ALL, 0x8E, 3, 'S', 'T', 'S', ALTER, 0xCF, 3, 'S', 'T', 'Y', ALTER, 0x8F, 4, 'S', 'W', 'I', '2', INHER, 0x3F, #endif /* MC6809 */ 0 /* end of page 1 ops */ }; PUBLIC char page2ops[] = { #ifdef MC6809 4, 'C', 'M', 'P', 'S', ALL, 0x8C, 4, 'C', 'M', 'P', 'U', ALL, 0x83, 4, 'S', 'W', 'I', '3', INHER, 0x3F, #endif 0 /* end of page 2 ops */ }; #ifdef I80386 # ifdef MNSIZE PUBLIC char bytesizeops[] = { 4, 'A', 'D', 'C', 'B', GROUP1, 0x10, 4, 'A', 'D', 'D', 'B', GROUP1, 0x00, 4, 'A', 'N', 'D', 'B', GROUP1, 0x20, 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE, 4, 'D', 'E', 'C', 'B', INCDEC, 0x08, 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30, 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38, 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28, 3, 'I', 'N', 'B', IN, 0xEC, 4, 'I', 'N', 'C', 'B', INCDEC, 0x00, 4, 'M', 'O', 'V', 'B', MOV, 0x88, 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20, 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18, 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10, 3, 'O', 'R', 'B', GROUP1, 0x08, 4, 'O', 'U', 'T', 'B', OUT, 0xEE, 4, 'R', 'C', 'L', 'B', GROUP2, 0x10, 4, 'R', 'C', 'R', 'B', GROUP2, 0x18, 4, 'R', 'O', 'L', 'B', GROUP2, 0x00, 4, 'R', 'O', 'R', 'B', GROUP2, 0x08, 4, 'S', 'A', 'L', 'B', GROUP2, 0x20, 4, 'S', 'A', 'R', 'B', GROUP2, 0x38, 4, 'S', 'H', 'L', 'B', GROUP2, 0x20, 4, 'S', 'H', 'R', 'B', GROUP2, 0x28, 4, 'S', 'B', 'B', 'B', GROUP1, 0x18, 4, 'S', 'U', 'B', 'B', GROUP1, 0x28, 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84, 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86, 4, 'X', 'O', 'R', 'B', GROUP1, 0x30, 0 /* end of byte size ops */ }; # endif /* MNSIZE */ #endif /* I80386 */ /* --- end of keywords --- */ dev86-0.16.17/as/asm/0000755000000000000000000000000005727442400013747 5ustar rootroot00000000000000dev86-0.16.17/as/asm/seg.asm0000644000000000000000000000006004252751120015215 0ustar rootroot00000000000000 SEG CS SEG DS SEG ES SEG FS SEG GS SEG SS dev86-0.16.17/as/asm/inher.asm0000644000000000000000000000124404254117004015550 0ustar rootroot00000000000000; INHER.ASM ; INHER opcodes AAA AAS CLC CLD CLI CLTS CMC CMPSB DAA DAS HLT INTO INSB LAHF LEAVE LOCK LODSB MOVSB NOP OUTSB REP REPE REPNE SAHF SCASB STC STD STI STOSB WAIT ; INHER16 and INHER32 opcodes USE16 CBW CWD CWDE CDQ CMPSW CMPSD INSW INSD IRET IRETD LODSW LODSD MOVSW MOVSD OUTSW OUTSD POPA POPAD POPF POPFD PUSHA PUSHAD PUSHF PUSHFD SCASW SCASD STOSW STOSW XLAT XLATB USE32 CBW CWD CWDE CDQ CMPSW CMPSD INSW INSD IRET IRETD LODSW LODSD MOVSW MOVSD OUTSW OUTSD POPA POPAD POPF POPFD PUSHA PUSHAD PUSHF PUSHFD SCASW SCASD STOSW STOSW XLAT XLATB dev86-0.16.17/as/asm/group7.asm0000644000000000000000000000104705060264106015671 0ustar rootroot00000000000000; group7.asm ; 0F 01 /nnn ; INVLPG m nnn = 111 ; LGDT m16&32 nnn = 010 ; LIDT m16&32 nnn = 011 ; LMSW r/m16 nnn = 110 ; SGDT m nnn = 000 ; SIDT m nnn = 001 ; SMSW r/m16 nnn = 100 LGDT EAX ; register not allowed LGDT #$1234 ; immed not allowed LGDT WORD PTR [BX] ; illegal size LGDT [BX] LGDT PWORD PTR [BX] LGDT FWORD PTR [BX] LGDT [EAX] INVLPG [EDI] SGDT [BP] SIDT [EBX] LMSW AL ; illeg size LMSW EAX ; illeg size LMSW #$1234 ; immed not allowed LMSW DS ; segreg not allowed LMSW AX LMSW [BX] LMSW [EAX] SMSW BX dev86-0.16.17/as/asm/calljmp.asm0000644000000000000000000000122504252744562016101 0ustar rootroot00000000000000 CALL 0x10:0x20 ; not implemented CALL AL; ; illeg CALL DS ; illeg CALL REL16 CALL AX CALL BX CALL CX CALL DX CALL SP CALL BP CALL SI CALL DI CALL BYTE [BX] ; illeg CALL [BX] CALL WORD [BX] USE32 CALL REL32 USE16 CALL EAX CALL EBX CALL ECX CALL EDX CALL ESP CALL EBP CALL ESI CALL EDI CALL DWORD [BX] JMP 0x10:0x20 ; not implemented JMP AL; ; illeg JMP DS ; illeg JMP REL16 JMP AX JMP BX JMP CX JMP DX JMP SP JMP BP JMP SI JMP DI JMP BYTE [BX] ; illeg JMP [BX] JMP WORD [BX] USE32 JMP REL32 USE16 JMP EAX JMP EBX JMP ECX JMP EDX JMP ESP JMP EBP JMP ESI JMP EDI JMP DWORD [BX] REL16: REL32: dev86-0.16.17/as/asm/group1.asm0000644000000000000000000000070005060266107015661 0ustar rootroot00000000000000 ADD AL,#3 ADD AX,#$1234 ADD EAX,#$12345678 ADD BL,#3 ADD BX,#$1234 ADD EBX,#$12345678 ADD BYTE [BX],#3 ADD BYTE 3[BX],#4 ADD BYTE [BX+SI],#4 ADD WORD [BX],#$1234 ADD DWORD [BX],#$12345678 ADD BYTE [BX],#3 ADD WORD [BX],#-3 ADD DWORD [BX],#-3 ADD CL,BL ADD CX,BX ADD ECX,EBX ADD [BX],CL ADD [BX],CX ADD [BX],ECX ADD CL,[BX] ADD CX,[BX] ADD ECX,[BX] ADC CL,BL AND CL,BL CMP CL,BL OR CL,BL SUB CL,BL SBB CL,BL XOR CL,BL dev86-0.16.17/as/asm/xchg.asm0000644000000000000000000000242505060267266015412 0ustar rootroot00000000000000 XCHG AX,BL ; illeg XCHG AX,BYTE [BX] ; illeg XCHG AX,DS ; illeg XCHG AX,#1 ; illeg XCHG AX,AX XCHG AX,BX XCHG AX,CX XCHG AX,DX XCHG AX,SP XCHG AX,BP XCHG AX,SI XCHG AX,DI XCHG AX,AX XCHG BX,AX XCHG CX,AX XCHG DX,AX XCHG SP,AX XCHG BP,AX XCHG SI,AX XCHG DI,AX XCHG EAX,EAX XCHG EAX,EBX XCHG EAX,ECX XCHG EAX,EDX XCHG EAX,ESP XCHG EAX,EBP XCHG EAX,ESI XCHG EAX,EDI XCHG EAX,EAX XCHG EBX,EAX XCHG ECX,EAX XCHG EDX,EAX XCHG ESP,EAX XCHG EBP,EAX XCHG ESI,EAX XCHG EDI,EAX XCHG AL,AL XCHG AL,AH XCHG AL,BL XCHG AL,BH XCHG BL,CL XCHG BL,CH XCHG BL,DL XCHG BL,DH XCHG [BX],AL XCHG [BX],AH XCHG [BX],BL XCHG [BX],BH XCHG [BX],CL XCHG [BX],CH XCHG [BX],DL XCHG [BX],DH XCHG AL,[BX] XCHG AH,[BX] XCHG BL,[BX] XCHG BH,[BX] XCHG CL,[BX] XCHG CH,[BX] XCHG DL,[BX] XCHG DH,[BX] XCHG [BX],AX XCHG [BX],BX XCHG [BX],CX XCHG [BX],DX XCHG [BX],SP XCHG [BX],BP XCHG [BX],SI XCHG [BX],DI XCHG AX,[BX] XCHG BX,[BX] XCHG CX,[BX] XCHG DX,[BX] XCHG SP,[BX] XCHG BP,[BX] XCHG SI,[BX] XCHG DI,[BX] XCHG [BX],EAX XCHG [BX],EBX XCHG [BX],ECX XCHG [BX],EDX XCHG [BX],ESP XCHG [BX],EBP XCHG [BX],ESI XCHG [BX],EDI XCHG AX,[EBX] XCHG BX,[EBX] XCHG CX,[EBX] XCHG DX,[EBX] XCHG SP,[EBX] XCHG BP,[EBX] XCHG SI,[EBX] XCHG DI,[EBX] dev86-0.16.17/as/asm/pushpop.asm0000644000000000000000000000220505060270332016137 0ustar rootroot00000000000000 PUSH AL ; illeg PUSH AH ; illeg PUSH BL ; illeg PUSH BH ; illeg PUSH CL ; illeg PUSH CH ; illeg PUSH DL ; illeg PUSH DH ; illeg PUSH #1 ; illeg PUSH BYTE #1 ; illeg PUSH [BX] ; illeg PUSH BYTE [BX] ; illeg PUSH WORD #-1 ; right way to push a signed byte value PUSH AX PUSH BX PUSH CX PUSH DX PUSH SP PUSH BP PUSH SI PUSH DI PUSH CS PUSH DS PUSH ES PUSH FS PUSH GS PUSH SS PUSH #$1234 ; illeg PUSH WORD #$1234 PUSH WORD [BX] PUSH EAX PUSH EBX PUSH ECX PUSH EDX PUSH ESP PUSH EBP PUSH ESI PUSH EDI PUSH #$12345678 ; illeg PUSH DWORD #$12345678 PUSH DWORD [BX] POP AL ; illeg POP AH ; illeg POP BL ; illeg POP BH ; illeg POP CL ; illeg POP CH ; illeg POP DL ; illeg POP DH ; illeg POP #1 ; illeg POP BYTE #1 ; illeg POP [BX] ; illeg POP BYTE [BX] ; illeg POP AX POP BX POP CX POP DX POP SP POP BP POP SI POP DI POP CS ; illeg POP DS POP ES POP FS POP GS POP SS POP #$1234 ; illeg POP WORD #$1234 ; illeg POP WORD [BX] POP EAX POP EBX POP ECX POP EDX POP ESP POP EBP POP ESI POP EDI POP #$12345678 ; illeg POP DWORD #$12345678 ; illeg POP DWORD [BX] dev86-0.16.17/as/asm/easlow.as0000644000000000000000000006747404250225300015574 0ustar rootroot00000000000000 MOV AL,[0] MOV AH,[1] MOV BL,[-1] ; illeg MOV BH,[127] MOV CL,[-128] ; illeg MOV CH,[128] MOV DL,[-129] ; illeg MOV DH,[32767] MOV AL,[-32768] ; illeg MOV AH,[32768] MOV BL,[-32769] ; illeg MOV BH,[$7FFFFFFF] ; illeg MOV CL,[$80000000] ; illeg MOV AL,AL MOV AL,AH MOV AL,BL MOV AL,BH MOV AL,CL MOV AL,CH MOV AL,DL MOV AL,DH MOV AL,AX ; illeg MOV AL,BX ; illeg MOV AL,CX ; illeg MOV AL,DX ; illeg MOV AL,BP ; illeg MOV AL,DI ; illeg MOV AL,SI ; illeg MOV AL,SP ; illeg MOV AH,AL MOV AH,AH MOV AH,BL MOV AH,BH MOV AH,CL MOV AH,CH MOV AH,DL MOV AH,DH MOV AH,AX ; illeg MOV AH,BX ; illeg MOV AH,CX ; illeg MOV AH,DX ; illeg MOV AH,BP ; illeg MOV AH,DI ; illeg MOV AH,SI ; illeg MOV AH,SP ; illeg MOV BL,AL MOV BL,AH MOV BL,BL MOV BL,BH MOV BL,CL MOV BL,CH MOV BL,DL MOV BL,DH MOV BL,AX ; illeg MOV BL,BX ; illeg MOV BL,CX ; illeg MOV BL,DX ; illeg MOV BL,BP ; illeg MOV BL,DI ; illeg MOV BL,SI ; illeg MOV BL,SP ; illeg MOV BH,AL MOV BH,AH MOV BH,BL MOV BH,BH MOV BH,CL MOV BH,CH MOV BH,DL MOV BH,DH MOV BH,AX ; illeg MOV BH,BX ; illeg MOV BH,CX ; illeg MOV BH,DX ; illeg MOV BH,BP ; illeg MOV BH,DI ; illeg MOV BH,SI ; illeg MOV BH,SP ; illeg MOV CL,AL MOV CL,AH MOV CL,BL MOV CL,BH MOV CL,CL MOV CL,CH MOV CL,DL MOV CL,DH MOV CL,AX ; illeg MOV CL,BX ; illeg MOV CL,CX ; illeg MOV CL,DX ; illeg MOV CL,BP ; illeg MOV CL,DI ; illeg MOV CL,SI ; illeg MOV CL,SP ; illeg MOV CH,AL MOV CH,AH MOV CH,BL MOV CH,BH MOV CH,CL MOV CH,CH MOV CH,DL MOV CH,DH MOV CH,AX ; illeg MOV CH,BX ; illeg MOV CH,CX ; illeg MOV CH,DX ; illeg MOV CH,BP ; illeg MOV CH,DI ; illeg MOV CH,SI ; illeg MOV CH,SP ; illeg MOV DL,AL MOV DL,AH MOV DL,BL MOV DL,BH MOV DL,CL MOV DL,CH MOV DL,DL MOV DL,DH MOV DL,AX ; illeg MOV DL,BX ; illeg MOV DL,CX ; illeg MOV DL,DX ; illeg MOV DL,BP ; illeg MOV DL,DI ; illeg MOV DL,SI ; illeg MOV DL,SP ; illeg MOV DH,AL MOV DH,AH MOV DH,BL MOV DH,BH MOV DH,CL MOV DH,CH MOV DH,DL MOV DH,DH MOV DH,AX ; illeg MOV DH,BX ; illeg MOV DH,CX ; illeg MOV DH,DX ; illeg MOV DH,BP ; illeg MOV DH,DI ; illeg MOV DH,SI ; illeg MOV DH,SP ; illeg MOV AL,[AL] ; illeg MOV AH,[AH] ; illeg MOV BL,[BL] ; illeg MOV BH,[BH] ; illeg MOV CL,[CL] ; illeg MOV CH,[CH] ; illeg MOV DL,[DL] ; illeg MOV DH,[DH] ; illeg MOV AL,[AX] ; illeg MOV AH,[BX] MOV BL,[CX] ; illeg MOV BH,[DX] ; illeg MOV CL,[BP] MOV CH,[DI] MOV DL,[SI] MOV DH,[SP] ; illeg MOV AL,[AX+1] ; illeg MOV AH,[BX+1] MOV BL,[CX+1] ; illeg MOV BH,[DX+1] ; illeg MOV CL,[BP+1] MOV CH,[DI+1] MOV DL,[SI+1] MOV DH,[SP+1] ; illeg MOV AL,[AX-1] ; illeg MOV AH,[BX-1] MOV BL,[CX-1] ; illeg MOV BH,[DX-1] ; illeg MOV CL,[BP-1] MOV CH,[DI-1] MOV DL,[SI-1] MOV DH,[SP-1] ; illeg MOV AL,[AX+127] ; illeg MOV AH,[BX+127] MOV BL,[CX+127] ; illeg MOV BH,[DX+127] ; illeg MOV CL,[BP+127] MOV CH,[DI+127] MOV DL,[SI+127] MOV DH,[SP+127] ; illeg MOV AL,[AX-128] ; illeg MOV AH,[BX-128] MOV BL,[CX-128] ; illeg MOV BH,[DX-128] ; illeg MOV CL,[BP-128] MOV CH,[DI-128] MOV DL,[SI-128] MOV DH,[SP-128] ; illeg MOV AL,[AX+128] ; illeg MOV AH,[BX+128] MOV BL,[CX+128] ; illeg MOV BH,[DX+128] ; illeg MOV CL,[BP+128] MOV CH,[DI+128] MOV DL,[SI+128] MOV DH,[SP+128] ; illeg MOV AL,[AX-129] ; illeg MOV AH,[BX-129] MOV BL,[CX-129] ; illeg MOV BH,[DX-129] ; illeg MOV CL,[BP-129] MOV CH,[DI-129] MOV DL,[SI-129] MOV DH,[SP-129] ; illeg MOV AL,[AX+32767] ; illeg MOV AH,[BX+32767] MOV BL,[CX+32767] ; illeg MOV BH,[DX+32767] ; illeg MOV CL,[BP+32767] MOV CH,[DI+32767] MOV DL,[SI+32767] MOV DH,[SP+32767] ; illeg MOV AL,[AX-32768] ; illeg MOV AH,[BX-32768] MOV BL,[CX-32768] ; illeg MOV BH,[DX-32768] ; illeg MOV CL,[BP-32768] MOV CH,[DI-32768] MOV DL,[SI-32768] MOV DH,[SP-32768] ; illeg MOV AL,[AX+32768] ; illeg MOV AH,[BX+32768] MOV BL,[CX+32768] ; illeg MOV BH,[DX+32768] ; illeg MOV CL,[BP+32768] MOV CH,[DI+32768] MOV DL,[SI+32768] MOV DH,[SP+32768] ; illeg MOV AL,[AX-32769] ; illeg MOV AH,[BX-32769] MOV BL,[CX-32769] ; illeg MOV BH,[DX-32769] ; illeg MOV CL,[BP-32769] MOV CH,[DI-32769] MOV DL,[SI-32769] MOV DH,[SP-32769] ; illeg MOV AL,[AX+$7FFFFFFF] ; illeg MOV AH,[BX+$7FFFFFFF] ; illeg (bounds) MOV BL,[CX+$7FFFFFFF] ; illeg MOV BH,[DX+$7FFFFFFF] ; illeg MOV CL,[BP+$7FFFFFFF] ; illeg (bounds) MOV CH,[DI+$7FFFFFFF] ; illeg (bounds) MOV DL,[SI+$7FFFFFFF] ; illeg (bounds) MOV DH,[SP+$7FFFFFFF] ; illeg MOV AL,[AX-$80000000] ; illeg MOV AH,[BX-$80000000] ; illeg (bounds) MOV BL,[CX-$80000000] ; illeg MOV BH,[DX-$80000000] ; illeg MOV CL,[BP-$80000000] ; illeg (bounds) MOV CH,[DI-$80000000] ; illeg (bounds) MOV DL,[SI-$80000000] ; illeg (bounds) MOV DH,[SP-$80000000] ; illeg MOV AL,[AX+AX] ; illeg MOV AH,[AX+BX] ; illeg MOV BL,[AX+CX] ; illeg MOV BH,[AX+DX] ; illeg MOV CL,[AX+BP] ; illeg MOV CH,[AX+DI] ; illeg MOV DL,[AX+SI] ; illeg MOV DH,[AX+SP] ; illeg MOV AL,[BX+AX] ; illeg MOV AH,[BX+BX] ; illeg MOV BL,[BX+CX] ; illeg MOV BH,[BX+DX] ; illeg MOV CL,[BX+BP] ; illeg MOV CH,[BX+DI] MOV DL,[BX+SI] MOV DH,[BX+SP] ; illeg MOV AL,[CX+AX] ; illeg MOV AH,[CX+BX] ; illeg MOV BL,[CX+CX] ; illeg MOV BH,[CX+DX] ; illeg MOV CL,[CX+BP] ; illeg MOV CH,[CX+DI] ; illeg MOV DL,[CX+SI] ; illeg MOV DH,[CX+SP] ; illeg MOV AL,[DX+AX] ; illeg MOV AH,[DX+BX] ; illeg MOV BL,[DX+CX] ; illeg MOV BH,[DX+DX] ; illeg MOV CL,[DX+BP] ; illeg MOV CH,[DX+DI] ; illeg MOV DL,[DX+SI] ; illeg MOV DH,[DX+SP] ; illeg MOV AL,[BP+AX] ; illeg MOV AH,[BP+BX] ; illeg MOV BL,[BP+CX] ; illeg MOV BH,[BP+DX] ; illeg MOV CL,[BP+BP] ; illeg MOV CH,[BP+DI] MOV DL,[BP+SI] MOV DH,[BP+SP] ; illeg MOV AL,[DI+AX] ; illeg MOV AH,[DI+BX] MOV BL,[DI+CX] ; illeg MOV BH,[DI+DX] ; illeg MOV CL,[DI+BP] MOV CH,[DI+DI] ; illeg MOV DL,[DI+SI] ; illeg MOV DH,[DI+SP] ; illeg MOV AL,[SI+AX] ; illeg MOV AH,[SI+BX] MOV BL,[SI+CX] ; illeg MOV BH,[SI+DX] ; illeg MOV CL,[SI+BP] MOV CH,[SI+DI] ; illeg MOV DL,[SI+SI] ; illeg MOV DH,[SI+SP] ; illeg MOV AL,[SP+AX] ; illeg MOV AH,[SP+BX] ; illeg MOV BL,[SP+CX] ; illeg MOV BH,[SP+DX] ; illeg MOV CL,[SP+BP] ; illeg MOV CH,[SP+DI] ; illeg MOV DL,[SP+SI] ; illeg MOV DH,[SP+SP] ; illeg MOV AL,[AX+AX+1] ; illeg MOV AH,[AX+BX+1] ; illeg MOV BL,[AX+CX+1] ; illeg MOV BH,[AX+DX+1] ; illeg MOV CL,[AX+BP+1] ; illeg MOV CH,[AX+DI+1] ; illeg MOV DL,[AX+SI+1] ; illeg MOV DH,[AX+SP+1] ; illeg MOV AL,[BX+AX+1] ; illeg MOV AH,[BX+BX+1] ; illeg MOV BL,[BX+CX+1] ; illeg MOV BH,[BX+DX+1] ; illeg MOV CL,[BX+BP+1] ; illeg MOV CH,[BX+DI+1] MOV DL,[BX+SI+1] MOV DH,[BX+SP+1] ; illeg MOV AL,[CX+AX+1] ; illeg MOV AH,[CX+BX+1] ; illeg MOV BL,[CX+CX+1] ; illeg MOV BH,[CX+DX+1] ; illeg MOV CL,[CX+BP+1] ; illeg MOV CH,[CX+DI+1] ; illeg MOV DL,[CX+SI+1] ; illeg MOV DH,[CX+SP+1] ; illeg MOV AL,[DX+AX+1] ; illeg MOV AH,[DX+BX+1] ; illeg MOV BL,[DX+CX+1] ; illeg MOV BH,[DX+DX+1] ; illeg MOV CL,[DX+BP+1] ; illeg MOV CH,[DX+DI+1] ; illeg MOV DL,[DX+SI+1] ; illeg MOV DH,[DX+SP+1] ; illeg MOV AL,[BP+AX+1] ; illeg MOV AH,[BP+BX+1] ; illeg MOV BL,[BP+CX+1] ; illeg MOV BH,[BP+DX+1] ; illeg MOV CL,[BP+BP+1] ; illeg MOV CH,[BP+DI+1] MOV DL,[BP+SI+1] MOV DH,[BP+SP+1] ; illeg MOV AL,[DI+AX+1] ; illeg MOV AH,[DI+BX+1] MOV BL,[DI+CX+1] ; illeg MOV BH,[DI+DX+1] ; illeg MOV CL,[DI+BP+1] MOV CH,[DI+DI+1] ; illeg MOV DL,[DI+SI+1] ; illeg MOV DH,[DI+SP+1] ; illeg MOV AL,[SI+AX+1] ; illeg MOV AH,[SI+BX+1] MOV BL,[SI+CX+1] ; illeg MOV BH,[SI+DX+1] ; illeg MOV CL,[SI+BP+1] MOV CH,[SI+DI+1] ; illeg MOV DL,[SI+SI+1] ; illeg MOV DH,[SI+SP+1] ; illeg MOV AL,[SP+AX+1] ; illeg MOV AH,[SP+BX+1] ; illeg MOV BL,[SP+CX+1] ; illeg MOV BH,[SP+DX+1] ; illeg MOV CL,[SP+BP+1] ; illeg MOV CH,[SP+DI+1] ; illeg MOV DL,[SP+SI+1] ; illeg MOV DH,[SP+SP+1] ; illeg MOV AL,[AX+AX-1] ; illeg MOV AH,[AX+BX-1] ; illeg MOV BL,[AX+CX-1] ; illeg MOV BH,[AX+DX-1] ; illeg MOV CL,[AX+BP-1] ; illeg MOV CH,[AX+DI-1] ; illeg MOV DL,[AX+SI-1] ; illeg MOV DH,[AX+SP-1] ; illeg MOV AL,[BX+AX-1] ; illeg MOV AH,[BX+BX-1] ; illeg MOV BL,[BX+CX-1] ; illeg MOV BH,[BX+DX-1] ; illeg MOV CL,[BX+BP-1] ; illeg MOV CH,[BX+DI-1] MOV DL,[BX+SI-1] MOV DH,[BX+SP-1] ; illeg MOV AL,[CX+AX-1] ; illeg MOV AH,[CX+BX-1] ; illeg MOV BL,[CX+CX-1] ; illeg MOV BH,[CX+DX-1] ; illeg MOV CL,[CX+BP-1] ; illeg MOV CH,[CX+DI-1] ; illeg MOV DL,[CX+SI-1] ; illeg MOV DH,[CX+SP-1] ; illeg MOV AL,[DX+AX-1] ; illeg MOV AH,[DX+BX-1] ; illeg MOV BL,[DX+CX-1] ; illeg MOV BH,[DX+DX-1] ; illeg MOV CL,[DX+BP-1] ; illeg MOV CH,[DX+DI-1] ; illeg MOV DL,[DX+SI-1] ; illeg MOV DH,[DX+SP-1] ; illeg MOV AL,[BP+AX-1] ; illeg MOV AH,[BP+BX-1] ; illeg MOV BL,[BP+CX-1] ; illeg MOV BH,[BP+DX-1] ; illeg MOV CL,[BP+BP-1] ; illeg MOV CH,[BP+DI-1] MOV DL,[BP+SI-1] MOV DH,[BP+SP-1] ; illeg MOV AL,[DI+AX-1] ; illeg MOV AH,[DI+BX-1] MOV BL,[DI+CX-1] ; illeg MOV BH,[DI+DX-1] ; illeg MOV CL,[DI+BP-1] MOV CH,[DI+DI-1] ; illeg MOV DL,[DI+SI-1] ; illeg MOV DH,[DI+SP-1] ; illeg MOV AL,[SI+AX-1] ; illeg MOV AH,[SI+BX-1] MOV BL,[SI+CX-1] ; illeg MOV BH,[SI+DX-1] ; illeg MOV CL,[SI+BP-1] MOV CH,[SI+DI-1] ; illeg MOV DL,[SI+SI-1] ; illeg MOV DH,[SI+SP-1] ; illeg MOV AL,[SP+AX-1] ; illeg MOV AH,[SP+BX-1] ; illeg MOV BL,[SP+CX-1] ; illeg MOV BH,[SP+DX-1] ; illeg MOV CL,[SP+BP-1] ; illeg MOV CH,[SP+DI-1] ; illeg MOV DL,[SP+SI-1] ; illeg MOV DH,[SP+SP-1] ; illeg MOV AL,[AX+AX+127] ; illeg MOV AH,[AX+BX+127] ; illeg MOV BL,[AX+CX+127] ; illeg MOV BH,[AX+DX+127] ; illeg MOV CL,[AX+BP+127] ; illeg MOV CH,[AX+DI+127] ; illeg MOV DL,[AX+SI+127] ; illeg MOV DH,[AX+SP+127] ; illeg MOV AL,[BX+AX+127] ; illeg MOV AH,[BX+BX+127] ; illeg MOV BL,[BX+CX+127] ; illeg MOV BH,[BX+DX+127] ; illeg MOV CL,[BX+BP+127] ; illeg MOV CH,[BX+DI+127] MOV DL,[BX+SI+127] MOV DH,[BX+SP+127] ; illeg MOV AL,[CX+AX+127] ; illeg MOV AH,[CX+BX+127] ; illeg MOV BL,[CX+CX+127] ; illeg MOV BH,[CX+DX+127] ; illeg MOV CL,[CX+BP+127] ; illeg MOV CH,[CX+DI+127] ; illeg MOV DL,[CX+SI+127] ; illeg MOV DH,[CX+SP+127] ; illeg MOV AL,[DX+AX+127] ; illeg MOV AH,[DX+BX+127] ; illeg MOV BL,[DX+CX+127] ; illeg MOV BH,[DX+DX+127] ; illeg MOV CL,[DX+BP+127] ; illeg MOV CH,[DX+DI+127] ; illeg MOV DL,[DX+SI+127] ; illeg MOV DH,[DX+SP+127] ; illeg MOV AL,[BP+AX+127] ; illeg MOV AH,[BP+BX+127] ; illeg MOV BL,[BP+CX+127] ; illeg MOV BH,[BP+DX+127] ; illeg MOV CL,[BP+BP+127] ; illeg MOV CH,[BP+DI+127] MOV DL,[BP+SI+127] MOV DH,[BP+SP+127] ; illeg MOV AL,[DI+AX+127] ; illeg MOV AH,[DI+BX+127] MOV BL,[DI+CX+127] ; illeg MOV BH,[DI+DX+127] ; illeg MOV CL,[DI+BP+127] MOV CH,[DI+DI+127] ; illeg MOV DL,[DI+SI+127] ; illeg MOV DH,[DI+SP+127] ; illeg MOV AL,[SI+AX+127] ; illeg MOV AH,[SI+BX+127] MOV BL,[SI+CX+127] ; illeg MOV BH,[SI+DX+127] ; illeg MOV CL,[SI+BP+127] MOV CH,[SI+DI+127] ; illeg MOV DL,[SI+SI+127] ; illeg MOV DH,[SI+SP+127] ; illeg MOV AL,[SP+AX+127] ; illeg MOV AH,[SP+BX+127] ; illeg MOV BL,[SP+CX+127] ; illeg MOV BH,[SP+DX+127] ; illeg MOV CL,[SP+BP+127] ; illeg MOV CH,[SP+DI+127] ; illeg MOV DL,[SP+SI+127] ; illeg MOV DH,[SP+SP+127] ; illeg MOV AL,[AX+AX-128] ; illeg MOV AH,[AX+BX-128] ; illeg MOV BL,[AX+CX-128] ; illeg MOV BH,[AX+DX-128] ; illeg MOV CL,[AX+BP-128] ; illeg MOV CH,[AX+DI-128] ; illeg MOV DL,[AX+SI-128] ; illeg MOV DH,[AX+SP-128] ; illeg MOV AL,[BX+AX-128] ; illeg MOV AH,[BX+BX-128] ; illeg MOV BL,[BX+CX-128] ; illeg MOV BH,[BX+DX-128] ; illeg MOV CL,[BX+BP-128] ; illeg MOV CH,[BX+DI-128] MOV DL,[BX+SI-128] MOV DH,[BX+SP-128] ; illeg MOV AL,[CX+AX-128] ; illeg MOV AH,[CX+BX-128] ; illeg MOV BL,[CX+CX-128] ; illeg MOV BH,[CX+DX-128] ; illeg MOV CL,[CX+BP-128] ; illeg MOV CH,[CX+DI-128] ; illeg MOV DL,[CX+SI-128] ; illeg MOV DH,[CX+SP-128] ; illeg MOV AL,[DX+AX-128] ; illeg MOV AH,[DX+BX-128] ; illeg MOV BL,[DX+CX-128] ; illeg MOV BH,[DX+DX-128] ; illeg MOV CL,[DX+BP-128] ; illeg MOV CH,[DX+DI-128] ; illeg MOV DL,[DX+SI-128] ; illeg MOV DH,[DX+SP-128] ; illeg MOV AL,[BP+AX-128] ; illeg MOV AH,[BP+BX-128] ; illeg MOV BL,[BP+CX-128] ; illeg MOV BH,[BP+DX-128] ; illeg MOV CL,[BP+BP-128] ; illeg MOV CH,[BP+DI-128] MOV DL,[BP+SI-128] MOV DH,[BP+SP-128] ; illeg MOV AL,[DI+AX-128] ; illeg MOV AH,[DI+BX-128] MOV BL,[DI+CX-128] ; illeg MOV BH,[DI+DX-128] ; illeg MOV CL,[DI+BP-128] MOV CH,[DI+DI-128] ; illeg MOV DL,[DI+SI-128] ; illeg MOV DH,[DI+SP-128] ; illeg MOV AL,[SI+AX-128] ; illeg MOV AH,[SI+BX-128] MOV BL,[SI+CX-128] ; illeg MOV BH,[SI+DX-128] ; illeg MOV CL,[SI+BP-128] MOV CH,[SI+DI-128] ; illeg MOV DL,[SI+SI-128] ; illeg MOV DH,[SI+SP-128] ; illeg MOV AL,[SP+AX-128] ; illeg MOV AH,[SP+BX-128] ; illeg MOV BL,[SP+CX-128] ; illeg MOV BH,[SP+DX-128] ; illeg MOV CL,[SP+BP-128] ; illeg MOV CH,[SP+DI-128] ; illeg MOV DL,[SP+SI-128] ; illeg MOV DH,[SP+SP-128] ; illeg MOV AL,[AX+AX+128] ; illeg MOV AH,[AX+BX+128] ; illeg MOV BL,[AX+CX+128] ; illeg MOV BH,[AX+DX+128] ; illeg MOV CL,[AX+BP+128] ; illeg MOV CH,[AX+DI+128] ; illeg MOV DL,[AX+SI+128] ; illeg MOV DH,[AX+SP+128] ; illeg MOV AL,[BX+AX+128] ; illeg MOV AH,[BX+BX+128] ; illeg MOV BL,[BX+CX+128] ; illeg MOV BH,[BX+DX+128] ; illeg MOV CL,[BX+BP+128] ; illeg MOV CH,[BX+DI+128] MOV DL,[BX+SI+128] MOV DH,[BX+SP+128] ; illeg MOV AL,[CX+AX+128] ; illeg MOV AH,[CX+BX+128] ; illeg MOV BL,[CX+CX+128] ; illeg MOV BH,[CX+DX+128] ; illeg MOV CL,[CX+BP+128] ; illeg MOV CH,[CX+DI+128] ; illeg MOV DL,[CX+SI+128] ; illeg MOV DH,[CX+SP+128] ; illeg MOV AL,[DX+AX+128] ; illeg MOV AH,[DX+BX+128] ; illeg MOV BL,[DX+CX+128] ; illeg MOV BH,[DX+DX+128] ; illeg MOV CL,[DX+BP+128] ; illeg MOV CH,[DX+DI+128] ; illeg MOV DL,[DX+SI+128] ; illeg MOV DH,[DX+SP+128] ; illeg MOV AL,[BP+AX+128] ; illeg MOV AH,[BP+BX+128] ; illeg MOV BL,[BP+CX+128] ; illeg MOV BH,[BP+DX+128] ; illeg MOV CL,[BP+BP+128] ; illeg MOV CH,[BP+DI+128] MOV DL,[BP+SI+128] MOV DH,[BP+SP+128] ; illeg MOV AL,[DI+AX+128] ; illeg MOV AH,[DI+BX+128] MOV BL,[DI+CX+128] ; illeg MOV BH,[DI+DX+128] ; illeg MOV CL,[DI+BP+128] MOV CH,[DI+DI+128] ; illeg MOV DL,[DI+SI+128] ; illeg MOV DH,[DI+SP+128] ; illeg MOV AL,[SI+AX+128] ; illeg MOV AH,[SI+BX+128] MOV BL,[SI+CX+128] ; illeg MOV BH,[SI+DX+128] ; illeg MOV CL,[SI+BP+128] MOV CH,[SI+DI+128] ; illeg MOV DL,[SI+SI+128] ; illeg MOV DH,[SI+SP+128] ; illeg MOV AL,[SP+AX+128] ; illeg MOV AH,[SP+BX+128] ; illeg MOV BL,[SP+CX+128] ; illeg MOV BH,[SP+DX+128] ; illeg MOV CL,[SP+BP+128] ; illeg MOV CH,[SP+DI+128] ; illeg MOV DL,[SP+SI+128] ; illeg MOV DH,[SP+SP+128] ; illeg MOV AL,[AX+AX-129] ; illeg MOV AH,[AX+BX-129] ; illeg MOV BL,[AX+CX-129] ; illeg MOV BH,[AX+DX-129] ; illeg MOV CL,[AX+BP-129] ; illeg MOV CH,[AX+DI-129] ; illeg MOV DL,[AX+SI-129] ; illeg MOV DH,[AX+SP-129] ; illeg MOV AL,[BX+AX-129] ; illeg MOV AH,[BX+BX-129] ; illeg MOV BL,[BX+CX-129] ; illeg MOV BH,[BX+DX-129] ; illeg MOV CL,[BX+BP-129] ; illeg MOV CH,[BX+DI-129] MOV DL,[BX+SI-129] MOV DH,[BX+SP-129] ; illeg MOV AL,[CX+AX-129] ; illeg MOV AH,[CX+BX-129] ; illeg MOV BL,[CX+CX-129] ; illeg MOV BH,[CX+DX-129] ; illeg MOV CL,[CX+BP-129] ; illeg MOV CH,[CX+DI-129] ; illeg MOV DL,[CX+SI-129] ; illeg MOV DH,[CX+SP-129] ; illeg MOV AL,[DX+AX-129] ; illeg MOV AH,[DX+BX-129] ; illeg MOV BL,[DX+CX-129] ; illeg MOV BH,[DX+DX-129] ; illeg MOV CL,[DX+BP-129] ; illeg MOV CH,[DX+DI-129] ; illeg MOV DL,[DX+SI-129] ; illeg MOV DH,[DX+SP-129] ; illeg MOV AL,[BP+AX-129] ; illeg MOV AH,[BP+BX-129] ; illeg MOV BL,[BP+CX-129] ; illeg MOV BH,[BP+DX-129] ; illeg MOV CL,[BP+BP-129] ; illeg MOV CH,[BP+DI-129] MOV DL,[BP+SI-129] MOV DH,[BP+SP-129] ; illeg MOV AL,[DI+AX-129] ; illeg MOV AH,[DI+BX-129] MOV BL,[DI+CX-129] ; illeg MOV BH,[DI+DX-129] ; illeg MOV CL,[DI+BP-129] MOV CH,[DI+DI-129] ; illeg MOV DL,[DI+SI-129] ; illeg MOV DH,[DI+SP-129] ; illeg MOV AL,[SI+AX-129] ; illeg MOV AH,[SI+BX-129] MOV BL,[SI+CX-129] ; illeg MOV BH,[SI+DX-129] ; illeg MOV CL,[SI+BP-129] MOV CH,[SI+DI-129] ; illeg MOV DL,[SI+SI-129] ; illeg MOV DH,[SI+SP-129] ; illeg MOV AL,[SP+AX-129] ; illeg MOV AH,[SP+BX-129] ; illeg MOV BL,[SP+CX-129] ; illeg MOV BH,[SP+DX-129] ; illeg MOV CL,[SP+BP-129] ; illeg MOV CH,[SP+DI-129] ; illeg MOV DL,[SP+SI-129] ; illeg MOV DH,[SP+SP-129] ; illeg MOV AL,[AX+AX+32767] ; illeg MOV AH,[AX+BX+32767] ; illeg MOV BL,[AX+CX+32767] ; illeg MOV BH,[AX+DX+32767] ; illeg MOV CL,[AX+BP+32767] ; illeg MOV CH,[AX+DI+32767] ; illeg MOV DL,[AX+SI+32767] ; illeg MOV DH,[AX+SP+32767] ; illeg MOV AL,[BX+AX+32767] ; illeg MOV AH,[BX+BX+32767] ; illeg MOV BL,[BX+CX+32767] ; illeg MOV BH,[BX+DX+32767] ; illeg MOV CL,[BX+BP+32767] ; illeg MOV CH,[BX+DI+32767] MOV DL,[BX+SI+32767] MOV DH,[BX+SP+32767] ; illeg MOV AL,[CX+AX+32767] ; illeg MOV AH,[CX+BX+32767] ; illeg MOV BL,[CX+CX+32767] ; illeg MOV BH,[CX+DX+32767] ; illeg MOV CL,[CX+BP+32767] ; illeg MOV CH,[CX+DI+32767] ; illeg MOV DL,[CX+SI+32767] ; illeg MOV DH,[CX+SP+32767] ; illeg MOV AL,[DX+AX+32767] ; illeg MOV AH,[DX+BX+32767] ; illeg MOV BL,[DX+CX+32767] ; illeg MOV BH,[DX+DX+32767] ; illeg MOV CL,[DX+BP+32767] ; illeg MOV CH,[DX+DI+32767] ; illeg MOV DL,[DX+SI+32767] ; illeg MOV DH,[DX+SP+32767] ; illeg MOV AL,[BP+AX+32767] ; illeg MOV AH,[BP+BX+32767] ; illeg MOV BL,[BP+CX+32767] ; illeg MOV BH,[BP+DX+32767] ; illeg MOV CL,[BP+BP+32767] ; illeg MOV CH,[BP+DI+32767] MOV DL,[BP+SI+32767] MOV DH,[BP+SP+32767] ; illeg MOV AL,[DI+AX+32767] ; illeg MOV AH,[DI+BX+32767] MOV BL,[DI+CX+32767] ; illeg MOV BH,[DI+DX+32767] ; illeg MOV CL,[DI+BP+32767] MOV CH,[DI+DI+32767] ; illeg MOV DL,[DI+SI+32767] ; illeg MOV DH,[DI+SP+32767] ; illeg MOV AL,[SI+AX+32767] ; illeg MOV AH,[SI+BX+32767] MOV BL,[SI+CX+32767] ; illeg MOV BH,[SI+DX+32767] ; illeg MOV CL,[SI+BP+32767] MOV CH,[SI+DI+32767] ; illeg MOV DL,[SI+SI+32767] ; illeg MOV DH,[SI+SP+32767] ; illeg MOV AL,[SP+AX+32767] ; illeg MOV AH,[SP+BX+32767] ; illeg MOV BL,[SP+CX+32767] ; illeg MOV BH,[SP+DX+32767] ; illeg MOV CL,[SP+BP+32767] ; illeg MOV CH,[SP+DI+32767] ; illeg MOV DL,[SP+SI+32767] ; illeg MOV DH,[SP+SP+32767] ; illeg MOV AL,[AX+AX-32768] ; illeg MOV AH,[AX+BX-32768] ; illeg MOV BL,[AX+CX-32768] ; illeg MOV BH,[AX+DX-32768] ; illeg MOV CL,[AX+BP-32768] ; illeg MOV CH,[AX+DI-32768] ; illeg MOV DL,[AX+SI-32768] ; illeg MOV DH,[AX+SP-32768] ; illeg MOV AL,[BX+AX-32768] ; illeg MOV AH,[BX+BX-32768] ; illeg MOV BL,[BX+CX-32768] ; illeg MOV BH,[BX+DX-32768] ; illeg MOV CL,[BX+BP-32768] ; illeg MOV CH,[BX+DI-32768] MOV DL,[BX+SI-32768] MOV DH,[BX+SP-32768] ; illeg MOV AL,[CX+AX-32768] ; illeg MOV AH,[CX+BX-32768] ; illeg MOV BL,[CX+CX-32768] ; illeg MOV BH,[CX+DX-32768] ; illeg MOV CL,[CX+BP-32768] ; illeg MOV CH,[CX+DI-32768] ; illeg MOV DL,[CX+SI-32768] ; illeg MOV DH,[CX+SP-32768] ; illeg MOV AL,[DX+AX-32768] ; illeg MOV AH,[DX+BX-32768] ; illeg MOV BL,[DX+CX-32768] ; illeg MOV BH,[DX+DX-32768] ; illeg MOV CL,[DX+BP-32768] ; illeg MOV CH,[DX+DI-32768] ; illeg MOV DL,[DX+SI-32768] ; illeg MOV DH,[DX+SP-32768] ; illeg MOV AL,[BP+AX-32768] ; illeg MOV AH,[BP+BX-32768] ; illeg MOV BL,[BP+CX-32768] ; illeg MOV BH,[BP+DX-32768] ; illeg MOV CL,[BP+BP-32768] ; illeg MOV CH,[BP+DI-32768] MOV DL,[BP+SI-32768] MOV DH,[BP+SP-32768] ; illeg MOV AL,[DI+AX-32768] ; illeg MOV AH,[DI+BX-32768] MOV BL,[DI+CX-32768] ; illeg MOV BH,[DI+DX-32768] ; illeg MOV CL,[DI+BP-32768] MOV CH,[DI+DI-32768] ; illeg MOV DL,[DI+SI-32768] ; illeg MOV DH,[DI+SP-32768] ; illeg MOV AL,[SI+AX-32768] ; illeg MOV AH,[SI+BX-32768] MOV BL,[SI+CX-32768] ; illeg MOV BH,[SI+DX-32768] ; illeg MOV CL,[SI+BP-32768] MOV CH,[SI+DI-32768] ; illeg MOV DL,[SI+SI-32768] ; illeg MOV DH,[SI+SP-32768] ; illeg MOV AL,[SP+AX-32768] ; illeg MOV AH,[SP+BX-32768] ; illeg MOV BL,[SP+CX-32768] ; illeg MOV BH,[SP+DX-32768] ; illeg MOV CL,[SP+BP-32768] ; illeg MOV CH,[SP+DI-32768] ; illeg MOV DL,[SP+SI-32768] ; illeg MOV DH,[SP+SP-32768] ; illeg MOV AL,[AX+AX+32768] ; illeg MOV AH,[AX+BX+32768] ; illeg MOV BL,[AX+CX+32768] ; illeg MOV BH,[AX+DX+32768] ; illeg MOV CL,[AX+BP+32768] ; illeg MOV CH,[AX+DI+32768] ; illeg MOV DL,[AX+SI+32768] ; illeg MOV DH,[AX+SP+32768] ; illeg MOV AL,[BX+AX+32768] ; illeg MOV AH,[BX+BX+32768] ; illeg MOV BL,[BX+CX+32768] ; illeg MOV BH,[BX+DX+32768] ; illeg MOV CL,[BX+BP+32768] ; illeg MOV CH,[BX+DI+32768] MOV DL,[BX+SI+32768] MOV DH,[BX+SP+32768] ; illeg MOV AL,[CX+AX+32768] ; illeg MOV AH,[CX+BX+32768] ; illeg MOV BL,[CX+CX+32768] ; illeg MOV BH,[CX+DX+32768] ; illeg MOV CL,[CX+BP+32768] ; illeg MOV CH,[CX+DI+32768] ; illeg MOV DL,[CX+SI+32768] ; illeg MOV DH,[CX+SP+32768] ; illeg MOV AL,[DX+AX+32768] ; illeg MOV AH,[DX+BX+32768] ; illeg MOV BL,[DX+CX+32768] ; illeg MOV BH,[DX+DX+32768] ; illeg MOV CL,[DX+BP+32768] ; illeg MOV CH,[DX+DI+32768] ; illeg MOV DL,[DX+SI+32768] ; illeg MOV DH,[DX+SP+32768] ; illeg MOV AL,[BP+AX+32768] ; illeg MOV AH,[BP+BX+32768] ; illeg MOV BL,[BP+CX+32768] ; illeg MOV BH,[BP+DX+32768] ; illeg MOV CL,[BP+BP+32768] ; illeg MOV CH,[BP+DI+32768] MOV DL,[BP+SI+32768] MOV DH,[BP+SP+32768] ; illeg MOV AL,[DI+AX+32768] ; illeg MOV AH,[DI+BX+32768] MOV BL,[DI+CX+32768] ; illeg MOV BH,[DI+DX+32768] ; illeg MOV CL,[DI+BP+32768] MOV CH,[DI+DI+32768] ; illeg MOV DL,[DI+SI+32768] ; illeg MOV DH,[DI+SP+32768] ; illeg MOV AL,[SI+AX+32768] ; illeg MOV AH,[SI+BX+32768] MOV BL,[SI+CX+32768] ; illeg MOV BH,[SI+DX+32768] ; illeg MOV CL,[SI+BP+32768] MOV CH,[SI+DI+32768] ; illeg MOV DL,[SI+SI+32768] ; illeg MOV DH,[SI+SP+32768] ; illeg MOV AL,[SP+AX+32768] ; illeg MOV AH,[SP+BX+32768] ; illeg MOV BL,[SP+CX+32768] ; illeg MOV BH,[SP+DX+32768] ; illeg MOV CL,[SP+BP+32768] ; illeg MOV CH,[SP+DI+32768] ; illeg MOV DL,[SP+SI+32768] ; illeg MOV DH,[SP+SP+32768] ; illeg MOV AL,[AX+AX-32769] ; illeg MOV AH,[AX+BX-32769] ; illeg MOV BL,[AX+CX-32769] ; illeg MOV BH,[AX+DX-32769] ; illeg MOV CL,[AX+BP-32769] ; illeg MOV CH,[AX+DI-32769] ; illeg MOV DL,[AX+SI-32769] ; illeg MOV DH,[AX+SP-32769] ; illeg MOV AL,[BX+AX-32769] ; illeg MOV AH,[BX+BX-32769] ; illeg MOV BL,[BX+CX-32769] ; illeg MOV BH,[BX+DX-32769] ; illeg MOV CL,[BX+BP-32769] ; illeg MOV CH,[BX+DI-32769] MOV DL,[BX+SI-32769] MOV DH,[BX+SP-32769] ; illeg MOV AL,[CX+AX-32769] ; illeg MOV AH,[CX+BX-32769] ; illeg MOV BL,[CX+CX-32769] ; illeg MOV BH,[CX+DX-32769] ; illeg MOV CL,[CX+BP-32769] ; illeg MOV CH,[CX+DI-32769] ; illeg MOV DL,[CX+SI-32769] ; illeg MOV DH,[CX+SP-32769] ; illeg MOV AL,[DX+AX-32769] ; illeg MOV AH,[DX+BX-32769] ; illeg MOV BL,[DX+CX-32769] ; illeg MOV BH,[DX+DX-32769] ; illeg MOV CL,[DX+BP-32769] ; illeg MOV CH,[DX+DI-32769] ; illeg MOV DL,[DX+SI-32769] ; illeg MOV DH,[DX+SP-32769] ; illeg MOV AL,[BP+AX-32769] ; illeg MOV AH,[BP+BX-32769] ; illeg MOV BL,[BP+CX-32769] ; illeg MOV BH,[BP+DX-32769] ; illeg MOV CL,[BP+BP-32769] ; illeg MOV CH,[BP+DI-32769] MOV DL,[BP+SI-32769] MOV DH,[BP+SP-32769] ; illeg MOV AL,[DI+AX-32769] ; illeg MOV AH,[DI+BX-32769] MOV BL,[DI+CX-32769] ; illeg MOV BH,[DI+DX-32769] ; illeg MOV CL,[DI+BP-32769] MOV CH,[DI+DI-32769] ; illeg MOV DL,[DI+SI-32769] ; illeg MOV DH,[DI+SP-32769] ; illeg MOV AL,[SI+AX-32769] ; illeg MOV AH,[SI+BX-32769] MOV BL,[SI+CX-32769] ; illeg MOV BH,[SI+DX-32769] ; illeg MOV CL,[SI+BP-32769] MOV CH,[SI+DI-32769] ; illeg MOV DL,[SI+SI-32769] ; illeg MOV DH,[SI+SP-32769] ; illeg MOV AL,[SP+AX-32769] ; illeg MOV AH,[SP+BX-32769] ; illeg MOV BL,[SP+CX-32769] ; illeg MOV BH,[SP+DX-32769] ; illeg MOV CL,[SP+BP-32769] ; illeg MOV CH,[SP+DI-32769] ; illeg MOV DL,[SP+SI-32769] ; illeg MOV DH,[SP+SP-32769] ; illeg MOV AL,[AX+AX+$7FFFFFFF] ; illeg MOV AH,[AX+BX+$7FFFFFFF] ; illeg MOV BL,[AX+CX+$7FFFFFFF] ; illeg MOV BH,[AX+DX+$7FFFFFFF] ; illeg MOV CL,[AX+BP+$7FFFFFFF] ; illeg MOV CH,[AX+DI+$7FFFFFFF] ; illeg MOV DL,[AX+SI+$7FFFFFFF] ; illeg MOV DH,[AX+SP+$7FFFFFFF] ; illeg MOV AL,[BX+AX+$7FFFFFFF] ; illeg MOV AH,[BX+BX+$7FFFFFFF] ; illeg MOV BL,[BX+CX+$7FFFFFFF] ; illeg MOV BH,[BX+DX+$7FFFFFFF] ; illeg MOV CL,[BX+BP+$7FFFFFFF] ; illeg MOV CH,[BX+DI+$7FFFFFFF] ; illeg (bounds) MOV DL,[BX+SI+$7FFFFFFF] ; illeg (bounds) MOV DH,[BX+SP+$7FFFFFFF] ; illeg MOV AL,[CX+AX+$7FFFFFFF] ; illeg MOV AH,[CX+BX+$7FFFFFFF] ; illeg MOV BL,[CX+CX+$7FFFFFFF] ; illeg MOV BH,[CX+DX+$7FFFFFFF] ; illeg MOV CL,[CX+BP+$7FFFFFFF] ; illeg MOV CH,[CX+DI+$7FFFFFFF] ; illeg MOV DL,[CX+SI+$7FFFFFFF] ; illeg MOV DH,[CX+SP+$7FFFFFFF] ; illeg MOV AL,[DX+AX+$7FFFFFFF] ; illeg MOV AH,[DX+BX+$7FFFFFFF] ; illeg MOV BL,[DX+CX+$7FFFFFFF] ; illeg MOV BH,[DX+DX+$7FFFFFFF] ; illeg MOV CL,[DX+BP+$7FFFFFFF] ; illeg MOV CH,[DX+DI+$7FFFFFFF] ; illeg MOV DL,[DX+SI+$7FFFFFFF] ; illeg MOV DH,[DX+SP+$7FFFFFFF] ; illeg MOV AL,[BP+AX+$7FFFFFFF] ; illeg MOV AH,[BP+BX+$7FFFFFFF] ; illeg MOV BL,[BP+CX+$7FFFFFFF] ; illeg MOV BH,[BP+DX+$7FFFFFFF] ; illeg MOV CL,[BP+BP+$7FFFFFFF] ; illeg MOV CH,[BP+DI+$7FFFFFFF] ; illeg (bounds) MOV DL,[BP+SI+$7FFFFFFF] ; illeg (bounds) MOV DH,[BP+SP+$7FFFFFFF] ; illeg MOV AL,[DI+AX+$7FFFFFFF] ; illeg MOV AH,[DI+BX+$7FFFFFFF] ; illeg (bounds) MOV BL,[DI+CX+$7FFFFFFF] ; illeg MOV BH,[DI+DX+$7FFFFFFF] ; illeg MOV CL,[DI+BP+$7FFFFFFF] ; illeg (bounds) MOV CH,[DI+DI+$7FFFFFFF] ; illeg MOV DL,[DI+SI+$7FFFFFFF] ; illeg MOV DH,[DI+SP+$7FFFFFFF] ; illeg MOV AL,[SI+AX+$7FFFFFFF] ; illeg MOV AH,[SI+BX+$7FFFFFFF] ; illeg (bounds) MOV BL,[SI+CX+$7FFFFFFF] ; illeg MOV BH,[SI+DX+$7FFFFFFF] ; illeg MOV CL,[SI+BP+$7FFFFFFF] ; illeg (bounds) MOV CH,[SI+DI+$7FFFFFFF] ; illeg MOV DL,[SI+SI+$7FFFFFFF] ; illeg MOV DH,[SI+SP+$7FFFFFFF] ; illeg MOV AL,[SP+AX+$7FFFFFFF] ; illeg MOV AH,[SP+BX+$7FFFFFFF] ; illeg MOV BL,[SP+CX+$7FFFFFFF] ; illeg MOV BH,[SP+DX+$7FFFFFFF] ; illeg MOV CL,[SP+BP+$7FFFFFFF] ; illeg MOV CH,[SP+DI+$7FFFFFFF] ; illeg MOV DL,[SP+SI+$7FFFFFFF] ; illeg MOV DH,[SP+SP+$7FFFFFFF] ; illeg MOV AL,[AX+AX-$80000000] ; illeg MOV AH,[AX+BX-$80000000] ; illeg MOV BL,[AX+CX-$80000000] ; illeg MOV BH,[AX+DX-$80000000] ; illeg MOV CL,[AX+BP-$80000000] ; illeg MOV CH,[AX+DI-$80000000] ; illeg MOV DL,[AX+SI-$80000000] ; illeg MOV DH,[AX+SP-$80000000] ; illeg MOV AL,[BX+AX-$80000000] ; illeg MOV AH,[BX+BX-$80000000] ; illeg MOV BL,[BX+CX-$80000000] ; illeg MOV BH,[BX+DX-$80000000] ; illeg MOV CL,[BX+BP-$80000000] ; illeg MOV CH,[BX+DI-$80000000] ; illeg (bounds) MOV DL,[BX+SI-$80000000] ; illeg (bounds) MOV DH,[BX+SP-$80000000] ; illeg MOV AL,[CX+AX-$80000000] ; illeg MOV AH,[CX+BX-$80000000] ; illeg MOV BL,[CX+CX-$80000000] ; illeg MOV BH,[CX+DX-$80000000] ; illeg MOV CL,[CX+BP-$80000000] ; illeg MOV CH,[CX+DI-$80000000] ; illeg MOV DL,[CX+SI-$80000000] ; illeg MOV DH,[CX+SP-$80000000] ; illeg MOV AL,[DX+AX-$80000000] ; illeg MOV AH,[DX+BX-$80000000] ; illeg MOV BL,[DX+CX-$80000000] ; illeg MOV BH,[DX+DX-$80000000] ; illeg MOV CL,[DX+BP-$80000000] ; illeg MOV CH,[DX+DI-$80000000] ; illeg MOV DL,[DX+SI-$80000000] ; illeg MOV DH,[DX+SP-$80000000] ; illeg MOV AL,[BP+AX-$80000000] ; illeg MOV AH,[BP+BX-$80000000] ; illeg MOV BL,[BP+CX-$80000000] ; illeg MOV BH,[BP+DX-$80000000] ; illeg MOV CL,[BP+BP-$80000000] ; illeg MOV CH,[BP+DI-$80000000] ; illeg (bounds) MOV DL,[BP+SI-$80000000] ; illeg (bounds) MOV DH,[BP+SP-$80000000] ; illeg MOV AL,[DI+AX-$80000000] ; illeg MOV AH,[DI+BX-$80000000] ; illeg (bounds) MOV BL,[DI+CX-$80000000] ; illeg MOV BH,[DI+DX-$80000000] ; illeg MOV CL,[DI+BP-$80000000] ; illeg (bounds) MOV CH,[DI+DI-$80000000] ; illeg MOV DL,[DI+SI-$80000000] ; illeg MOV DH,[DI+SP-$80000000] ; illeg MOV AL,[SI+AX-$80000000] ; illeg MOV AH,[SI+BX-$80000000] ; illeg (bounds) MOV BL,[SI+CX-$80000000] ; illeg MOV BH,[SI+DX-$80000000] ; illeg MOV CL,[SI+BP-$80000000] ; illeg (bounds) MOV CH,[SI+DI-$80000000] ; illeg MOV DL,[SI+SI-$80000000] ; illeg MOV DH,[SI+SP-$80000000] ; illeg MOV AL,[SP+AX-$80000000] ; illeg MOV AH,[SP+BX-$80000000] ; illeg MOV BL,[SP+CX-$80000000] ; illeg MOV BH,[SP+DX-$80000000] ; illeg MOV CL,[SP+BP-$80000000] ; illeg MOV CH,[SP+DI-$80000000] ; illeg MOV DL,[SP+SI-$80000000] ; illeg MOV DH,[SP+SP-$80000000] ; illeg dev86-0.16.17/as/asm/incdec.asm0000644000000000000000000000172705060267736015714 0ustar rootroot00000000000000 INC AL INC AH INC BL INC BH INC CL INC CH INC DL INC DH INC #1 ; illeg INC BYTE #1 ; illeg INC [BX] ; illeg INC BYTE [BX] INC AX INC BX INC CX INC DX INC SP INC BP INC SI INC DI INC CS ; illeg INC DS ; illeg INC ES ; illeg INC FS ; illeg INC GS ; illeg INC #$1234 ; illeg INC WORD #$1234 ; illeg INC WORD [BX] INC EAX INC EBX INC ECX INC EDX INC ESP INC EBP INC ESI INC EDI INC #$12345678 ; illeg INC DWORD #$12345678 ; illeg INC DWORD [BX] DEC AL DEC AH DEC BL DEC BH DEC CL DEC CH DEC DL DEC DH DEC #1 ; illeg DEC BYTE #1 ; illeg DEC [BX] ; illeg DEC BYTE [BX] DEC AX DEC BX DEC CX DEC DX DEC SP DEC BP DEC SI DEC DI DEC CS ; illeg DEC DS ; illeg DEC ES ; illeg DEC FS ; illeg DEC GS ; illeg DEC #$1234 ; illeg DEC WORD #$1234 ; illeg DEC WORD [BX] DEC EAX DEC EBX DEC ECX DEC EDX DEC ESP DEC EBP DEC ESI DEC EDI DEC #$12345678 ; illeg DEC DWORD #$12345678 ; illeg DEC DWORD [BX] dev86-0.16.17/as/asm/f.asm0000644000000000000000000000347605060262257014710 0ustar rootroot00000000000000; [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] fadd qword [ebx] fadd dword [ebx] fadd st,st(1) fadd st(1),st fdiv qword [ebx] fdiv dword [ebx] fdiv st,st(1) ; special swapping for this ; [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st faddp st(1),st ; [fbld fbstp] mem10r fbld tbyte [ebx] fbstp tbyte [ebx] ; [fcom fcomp] [mem4r mem8r optional-st(i)] fcom dword [ebx] fcom qword [ebx] fcom fcom st(1) ; ffree st(i) ffree st(1) ; [fucom fucomp fxch] optional-st(i) fucom fucom st(1) ; [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] fiadd word [ebx] fiadd dword [ebx] ; [fild fistp] [mem2i mem4i mem8i] fild word [ebx] fild dword [ebx] fild qword [ebx] ; [fld fstp] [mem4r mem8r mem10r st(i)] fld dword [ebx] fld qword [ebx] fld tbyte [ebx] fld st(1) ; [fldcw fnstcw] mem2i fldcw word [ebx] fnstcw word [ebx] ; [fldenv fnsave fnstenv frstor] mem fldenv [ebx] fnsave [ebx] fnstenv [ebx] frstor [ebx] ; fnstsw [mem2i ax] fnstsw word [ebx] fnstsw ax ; fst [mem4r mem8r st(i)] fst dword [ebx] fst qword [ebx] fst st(1) ; fstcw mem2i (wait) fstcw word [ebx] ; fstsw [mem2i ax] (wait) fstsw word [ebx] fstsw ax ; [fsave fstenv] mem (wait) fsave [ebx] fstenv [ebx] ; [fxxx] (no operands) fnop ; D9D0 fchs ; D9E0 fabs ; D9E1 ftst ; D9E4 fxam ; D9E5 fld1 ; D9E8 fldl2t ; D9E9 fldl2e ; D9EA fldpi ; D9EB fldlg2 ; D9EC fldln2 ; D9ED fldz ; D9EE f2xm1 ; D9F0 fyl2x ; D9F1 fptan ; D9F2 fpatan ; D9F3 fxtract ; D9F4 fprem1 ; D9F5 fdecstp ; D9F6 fincstp ; D9F7 fprem ; D9F8 fyl2xp1 ; D9F9 fsqrt ; D9FA fsincos ; D9FB frndint ; D9FC fscale ; D9FD fsin ; D9FE fcos ; D9FF fucompp ; DAE9 feni ; 9BDBE0 fneni ; DBE0 fdisi ; 9BDBE1 fndisi ; DBE1 fclex ; 9BDBE2 fnclex ; DBE2 finit ; 9BDBE3 fninit ; DBE3 fsetpm ; DBE4 fcompp ; DED9 dev86-0.16.17/as/asm/farcall.asm0000644000000000000000000000012604361264167016061 0ustar rootroot00000000000000call 1:2 call far [1] use32 call far [1] use16 jmp 1:2 jmp far [1] use32 jmp far [1] dev86-0.16.17/as/asm/shift.asm0000644000000000000000000000267205060267235015576 0ustar rootroot00000000000000 RCL AL,CL RCL AH,CL RCL BL,CL RCL BH,CL RCL CL,CL RCL CH,CL RCL DL,CL RCL DH,CL RCL #1,CL ; illeg RCL [BX],CL ; illeg RCL BYTE [BX],CL RCL AX,CL RCL BX,CL RCL CX,CL RCL DX,CL RCL SP,CL RCL BP,CL RCL SI,CL RCL DI,CL RCL CS,CL ; illeg RCL DS,CL ; illeg RCL ES,CL ; illeg RCL FS,CL ; illeg RCL GS,CL ; illeg RCL WORD [BX],CL RCL EAX,CL RCL EBX,CL RCL ECX,CL RCL EDX,CL RCL ESP,CL RCL EBP,CL RCL ESI,CL RCL EDI,CL RCL DWORD [BX],CL RCL AL,1 RCL AH,1 RCL BL,1 RCL BH,1 RCL CL,1 RCL CH,1 RCL DL,1 RCL DH,1 RCL #1,1 ; illeg RCL [BX],1 ; illeg RCL BYTE [BX],1 RCL AX,1 RCL BX,1 RCL CX,1 RCL DX,1 RCL SP,1 RCL BP,1 RCL SI,1 RCL DI,1 RCL CS,1 ; illeg RCL DS,1 ; illeg RCL ES,1 ; illeg RCL FS,1 ; illeg RCL GS,1 ; illeg RCL WORD [BX],1 RCL EAX,1 RCL EBX,1 RCL ECX,1 RCL EDX,1 RCL ESP,1 RCL EBP,1 RCL ESI,1 RCL EDI,1 RCL DWORD [BX],1 RCL AL,15 RCL AH,15 RCL BL,15 RCL BH,15 RCL CL,15 RCL CH,15 RCL DL,15 RCL DH,15 RCL #1,15 ; illeg RCL [BX],15 ; illeg RCL BYTE [BX],15 RCL AL,$1000 RCL AX,15 RCL BX,15 RCL CX,15 RCL DX,15 RCL SP,15 RCL BP,15 RCL SI,15 RCL DI,15 RCL CS,15 ; illeg RCL DS,15 ; illeg RCL ES,15 ; illeg RCL FS,15 ; illeg RCL GS,15 ; illeg RCL WORD [BX],15 RCL EAX,15 RCL EBX,15 RCL ECX,15 RCL EDX,15 RCL ESP,15 RCL EBP,15 RCL ESI,15 RCL EDI,15 RCL DWORD [BX],15 RCR AX,7 ROL AX,7 ROR AX,7 SAL AX,7 SAR AX,7 SHL AX,7 SHR AX,7 dev86-0.16.17/as/asm/summary.as0000644000000000000000000001221505060771442015773 0ustar rootroot00000000000000general: ; AL,imm8 ; AX,imm16 ; EAX,imm32 ; r/m8,imm8 ; r/m16,imm16 ; r/m32.imm32 ; r/m16,signed imm8 ; r/m32,signed imm8 ; r/m8,r8 ; r/m16,r16 ; r/m32,r32 ; r8,r/m8 ; r16,r/m16 ; r32,r/m32 shiftcount: ; 1 ; CL ; imm8 unary alterable: ; r/m8 ; r/m16 ; r/m32 AAA AAD ; [unsupported base] AAM ; [unsupported base] AAS ADC ; general ADD ; general AND ; general ARPL ; r/m16,r16 BOUND ; r16,m16&16 BOUND ; r32,m32&32 BSF ; r16,r/m16 BSF ; r32,r/m32 BSR ; r16,r/m16 BSR ; r32,r/m32 BSWAP ; r32 BT ; r/m16,r16 BT ; r/m32,r32 BT ; r/m16,imm8 BT ; r/m32,imm8 BTC ; r/m16,r16 BTC ; r/m32,r32 BTC ; r/m16,imm8 BTC ; r/m32,imm8 BTR ; r/m16,r16 BTR ; r/m32,r32 BTR ; r/m16,imm8 BTR ; r/m32,imm8 BTS ; r/m16,r16 BTS ; r/m32,r32 BTS ; r/m16,imm8 BTS ; r/m32,imm8 CALL ; rel16 CALL ; r/m16 CALL ; ptr16:16 CALL ; m16:16 CALL ; rel32 CALL ; r/m32 CALL ; ptr16:32 CALL ; m16:32 CBW CDQ CLC CLD CLI CLTS CMC CMP ; general CMPS ; [segreg:]m8,m8 CMPS ; [segreg:]m16,m16 CMPS ; [segreg:]m32,m32 CMPSB CMPSW CMPSD CMPXCHG ; r/m8,r8 CMPXCHG ; r/m16,r16 CMPXCHG ; r/m32,r32 CWD CWDE DAA DAS DEC ; unary alterable DEC ; r16 DEC ; r32 DIV ; AL,r/m8 DIV ; AX,r/m16 DIV ; EAX,r/m32 ENTER ; imm16,imm8 HLT IDIV ; AL,r/m8 IDIV ; AX,r/m16 IDIV ; EAX,r/m32 IMUL ; r/m8 IMUL ; r/m16 IMUL ; r/m32 IMUL ; r16,r/m16 IMUL ; r32,r/m32 IMUL ; r16,r/m16,imm8 IMUL ; r32,r/m32,imm8 IMUL ; r16,imm8 IMUL ; r32,imm8 IMUL ; r16,r/m16,imm16 IMUL ; r32,r/m32,imm32 IMUL ; r16,imm16 IMUL ; r32,imm32 IN ; AL,imm8 IN ; AX,imm8 IN ; EAX,imm8 IN ; AL,DX IN ; AX,DX IN ; EAX,DX INC ; unary alterable INC ; r16 INC ; r32 INSB INSW INSD INT ; imm8 INTO INVD INVLPG ; m IRET IRETD JCC ; rel8 JCC ; rel16/32 JA JAE JB JBE JC JCXZ JECXZ JE JG JGE JL JLE JNA JNAE JNB JNBE JNC JNE JNG JNGE JNL JNLE JNO JNP JNS JNZ JO JP JPE JPO JS JZ JMP ; rel8 JMP ; rel16 JMP ; r/m16 JMP ; ptr16:16 JMP ; m16:16 JMP ; rel32 JMP ; r/m32 JMP ; ptr16:32 JMP ; m16:32 LAHF LAR ; r16,r/m16 LAR ; r32,r/m32 LEA ; r16,m LEA ; r32,m LEAVE LGDT ; m16&32 LIDT ; m16&32 LDS ; r16,m16:16 LDS ; r32,m16:32 LES ; r16,m16:16 LES ; r32,m16:32 LFS ; r16,m16:16 LFS ; r32,m16:32 LGS ; r16,m16:16 LGS ; r32,m16:32 LSS ; r16,m16:16 LSS ; r32,m16:32 LLDT ; r/m16 LMSW ; r/m16 LOCK LODS ; [segreg:]m8 LODS ; [segreg:]m16 LODS ; [segreg:]m32 LODSB LODSW LODSD LOOP ; rel8 LOOPE ; rel8 LOOPZ ; rel8 LOOPNE ; rel8 LOOPNZ ; rel8 LSL ; r16,r/m16 LSL ; r32,r/m32 LTR ; r/m16 MOV ; r/m8,r8 MOV ; r/m16,r16 MOV ; r/m32,r32 MOV ; r8,r/m8 MOV ; r16,r/m16 MOV ; r32,r/m32 MOV ; r/m16,Sreg MOV ; Sreg,r/m16 MOV ; AL,moffs8 MOV ; AX,moffs16 MOV ; EAX,moffs32 MOV ; moffs8,AL MOV ; moffs16,AX MOV ; moffs32,EAX MOV ; r8,imm8 MOV ; r16,imm16 MOV ; r32,imm32 MOV ; r32,CR0/CR2/CR3 MOV ; r/m8,imm8 MOV ; r/m16,imm16 MOV ; r/m32,imm32 MOV ; r32,CR0/CR2/CR3 MOV ; CR0/CR2/CR3,r32 MOV ; r32,DR0/DR1/DR2/DR3/DR6/DR7 MOV ; DR0/DR1/DR2/DR3/DR6/DR7,r32 MOV ; r32,TR6/TR7 MOV ; TR6/TR7,r32 MOVS ; [segreg:]m8,m8 MOVS ; [segreg:]m16,m16 MOVS ; [segreg:]m32,m32 MOVSB MOVSW MOVSD MOVSX ; r16,r/m8 MOVSX ; r32,r/m8 MOVSX ; r32,r/m16 MOVZX ; r16,r/m8 MOVZX ; r32,r/m8 MOVZX ; r32,r/m16 MUL ; AL,r/m8 MUL ; AX,r/m16 MUL ; EAX,r/m32 NEG ; unary alterable NOP NOT ; unary alterable OR ; general OUT ; imm8,AL OUT ; imm8,AX OUT ; imm8,EAX OUT ; DX,AL OUT ; DX,AX OUT ; DX,EAX OUTS ; [segreg:]m8 OUTS ; [segreg:]m16 OUTS ; [segreg:]m32 OUTSB OUTSW OUTSD POP ; m16 POP ; m32 POP ; r16 POP ; r32 POP ; DS POP ; ES POP ; FS POP ; GS POP ; SS POPA POPAD POPF POPFD PUSH ; m16 PUSH ; m32 PUSH ; r16 PUSH ; r32 PUSH ; imm8 PUSH ; imm16 PUSH ; imm32 PUSH ; CS PUSH ; DS PUSH ; ES PUSH ; FS PUSH ; GS PUSH ; SS PUSHA PUSHAD PUSHF PUSHFD RCL ; shiftcount RCR ; shiftcount ROL ; shiftcount ROR ; shiftcount REP ; INS/MOVS/OUTS/STOS REPE ; CMPS/SCAS REPNE ; CMPS/SCAS RET RET ; imm16 SAHF SAL ; shiftcount SAR ; shiftcount SHL ; shiftcount SHR ; shiftcount SBB ; general SCASB SCASW SCASD SETA ; r/m8 SETAE ; r/m8 SETB ; r/m8 SETBE ; r/m8 SETC ; r/m8 SETE ; r/m8 SETG ; r/m8 SETGE ; r/m8 SETL ; r/m8 SETLE ; r/m8 SETNA ; r/m8 SETNAE ; r/m8 SETNB ; r/m8 SETNBE ; r/m8 SETNC ; r/m8 SETNE ; r/m8 SETNG ; r/m8 SETNGE ; r/m8 SETNL ; r/m8 SETNLE ; r/m8 SETNO ; r/m8 SETNP ; r/m8 SETNS ; r/m8 SETNZ ; r/m8 SETO ; r/m8 SETP ; r/m8 SETPE ; r/m8 SETPO ; r/m8 SETS ; r/m8 SETZ ; r/m8 SGDT ; m SHLD ; r/m16,r16,imm8 SHLD ; r/m32,r32,imm8 SHLD ; r/m16,r16,CL SHLD ; r/m32,r32,CL SHRD ; r/m16,r16,imm8 SHRD ; r/m32,r32,imm8 SHRD ; r/m16,r16,CL SHRD ; r/m32,r32,CL SIDT ; m SLDT ; r/m16 SMSW ; r/m16 STC STD STI STOSB STOSW STOSD STR ; r/m16 SUB ; general TEST ; AL,imm8 TEST ; AX,imm16 TEST ; EAX,imm32 TEST ; r/m8,imm8 TEST ; r/m16,imm16 TEST ; r/m32,imm32 TEST ; r/m8,r8 TEST ; r/m16,r16 TEST ; r/m32/r32 VERR ; r/m16 VERW ; r/m16 WAIT WBINVD XADD ; r/m8,r8 XADD ; r/m16,r16 XADD ; r/m32,r32 XCHG ; AX,r16 XCHG ; EAX,r32 XCHG ; r/m8,r8 XCHG ; r/m16,r16 XCHG ; r/m32,r32 XLAT ; [segreg:]m8 XLATB XOR ; general dev86-0.16.17/as/asm/shdouble.asm0000644000000000000000000000124104253722700016251 0ustar rootroot00000000000000; SHDOUBLE.ASM ILLEGALS EQU 1 ; 0F A4 SHLD r/m16,r16,imm8 3/7 ; 0F A4 SHLD r/m32,r32,imm8 3/7 ; 0F A5 SHLD r/m16,r16,CL 3/7 ; 0F A5 SHLD r/m32,r32,CL 3/7 ; 0F AC SHRD r/m16,r16,imm8 3/7 ; 0F AC SHRD r/m32,r32,imm8 3/7 ; 0F AD SHRD r/m16,r16,CL 3/7 ; 0F AD SHRD r/m32,r32,CL 3/7 IF ILLEGALS SHLD AL,BL,8 ; byte size SHLD AX,8,8 ; immediate source SHLD AX,DS,8 ; segment register SHLD AX,[BX],8 ; non-register source SHLD AX,BX,256 ; shift count too big SHLD AL,BL,8 ; byte size ENDIF SHLD BX,CX,3 SHLD EDX,ESI,1 SHLD CX,BX,CL SHLD ESI,EDX,1 SHLD [BX],CX,3 SHLD [BX],ECX,1 SHLD [SI],BX,CL SHLD [SI],EBX,CL SHRD BX,CX,3 SHRD CX,BX,CL dev86-0.16.17/as/asm/inout.asm0000644000000000000000000000050705061007121015575 0ustar rootroot00000000000000 IN EAX,DX ; plain IN is no longer allowed INB IN AL,DX INW IN AX,DX IN EAX,DX IN AL,$20 IN AL,$101 IN AX,$20 IN AX,$101 IN EAX,$20 IN EAX,$101 OUTB DX,EAX ; plain OUT is no longer allowed OUTB OUT DX,AL OUTW OUT DX,AX OUT DX,EAX OUT $20,AL OUT $101,AL OUT $20,AX OUT #101,AX OUT $20,EAX OUT $101,EAX dev86-0.16.17/as/asm/each.asm0000644000000000000000000000263005061123264015345 0ustar rootroot00000000000000aaa aad aam aas adc bx,[esi*4] add bx,[esi*4] and bx,[esi*4] arpl [esi*4],bx bound bx,[esi*4] bsf bx,[esi*4] bsr bx,[esi*4] bswap ebx bt [esi*4],bx btc [esi*4],bx btr [esi*4],bx bts [esi*4],bx call [esi*4] cbw cwde clc cld cli clts cmc cmp bx,[esi*4] cmpsb cmpsw cmpsd cmpxchg [esi*4],bx cwd cdq daa das dec [esi*4] div [esi*4] enter 0x200,3 hlt idiv [esi*4] imul [esi*4] in al,0x20 inc [esi*4] insb insw insd int 0x20 into invd invlpg [esi*4] iret iretd jnz many many: jmp [esi*4] lahf lar bx,[esi*4] lea bx,[esi*4] leave lgdt [esi*4] lidt [esi*4] lds bx,[esi*4] les bx,[esi*4] lfs bx,[esi*4] lgs bx,[esi*4] lss bx,[esi*4] lldt [esi*4] lmsw [esi*4] lock lodsb lodsw lodsd loop alot alot: lsl bx,[esi*4] ltr [esi*4] mov ax,[esi*4] mov bx,[esi*4] mov cr0,eax movsb movsw movsd movsx bx,byte [esi*4] movzx bx,byte [esi*4] mul [esi*4] neg [esi*4] nop not [esi*4] or bx,[esi*4] out 0x20,al outsb outsw outsd pop [esi*4] popa popad popf popfd push [esi*4] pusha pushad pushf pushfd rcl [esi*4],1 rcr [esi*4],1 rol [esi*4],1 ror [esi*4],1 rep repe repz repne repnz ret retf sahf sal [esi*4],1 sar [esi*4],1 shl [esi*4],1 shr [esi*4],1 sbb bx,[esi*4] scasb scasw scasd setnz byte [esi*4] sgdt [esi*4] sidt [esi*4] shld [esi*4],bx,1 shrd [esi*4],bx,1 sldt [esi*4] smsw [esi*4] stc std sti stosb stosw stosd str [esi*4] sub bx,[esi*4] test bx,[esi*4] verr [esi*4] verw [esi*4] wait wbinvd xadd [esi*4],bx xchg bx,[esi*4] xlat xor bx,[esi*4] dev86-0.16.17/as/asm/imul.asm0000644000000000000000000000066005060266506015422 0ustar rootroot00000000000000 use32 imul bl imul byte ptr [esi] imul bx imul word ptr [esi] imul ebx imul dword ptr [esi] imul ax,bx imul ax,[esi] imul eax,ebx imul eax,[esi] imul ax,bx,22 imul ax,[esi],22 imul eax,ebx,22 imul eax,[esi],22 imul ax,[22] imul eax,[22] imul ax,#22 imul eax,#22 imul ax,bx,300 imul ax,[esi],300 imul eax,ebx,300000 imul eax,[esi],300000 imul ax,[300] imul eax,[300000] imul ax,#300 imul eax,#300000 dev86-0.16.17/as/asm/fadd.asm0000644000000000000000000001151105060250330015333 0ustar rootroot00000000000000_fadd: PUSH BP MOV BP,SP MOV EAX,DWORD PTR [BP+4] MOV EDX,DWORD PTR [BP+8] MOV EBX,DWORD PTR [BP+12] MOV ECX,DWORD PTR [BP+16] CALL faddfxfy MOV DWORD PTR _facc,EAX MOV DWORD PTR _facc+4,EDX POP BP RET fsubfxfy: XOR ECX,#$80000000 ; complement sign bit, fall into add routine faddfxfy: PUSH EBP PUSH EDI PUSH ESI MOV EDI,ECX ; free CL for shifts MOV ESI,EDX ; this mainly for consistent naming AND ESI,#$7FFFFFFF ; discard sign so comparison is simple AND EDI,#$7FFFFFFF CMP ESI,EDI JA XBIG JB SWAP CMP EAX,EBX JAE XBIG SWAP: XCHG EDX,ECX XCHG ESI,EDI XCHG EAX,EBX XBIG: AND ESI,#$000FFFFF ; discard exponent AND EDI,#$000FFFFF OR ESI,#$00100000 ; normalize OR EDI,#$00100000 SHR ECX,32-(1+11) SHR EDX,32-(1+11) MOV EBP,ECX ; prepare to compare signs (want high bits 0) SUB CX,DX ; get difference of signs in CX NEG CX ; D holds sign and exponent of both throughout CMP CX,#(64-11)+2 JAE TO_DONE1 ; x dominates y XOR BP,DX AND BP,#$0800 ; see if signs are same JNZ TO_SUBTRACT ; else roundoff reg EBP is 0 CMP CL,#32 JAE TO_ADD_BIGSHIFT SHRD EBP,EBX,CL SHRD EBX,EDI,CL SHR EDI,CL ADD EAX,EBX ADC ESI,EDI SUB EBX,EBX ; result DX(1+11):SI:AX:BP:BX but needs normalization NORMALIZE: MOV CX,DX AND CX,#$07FF TEST ESI,#$00200000 JZ NORMALIZE2 BR LOVERFLOW TO_DONE1: JMP DONE1 TO_SUBTRACT: BR SUBTRACT TO_ADD_BIGSHIFT: BR ADD_BIGSHIFT TO_NORMLITTLE: BR NORMLITTLE ; result DX(1):CX(11):SI:AX:BP:BX NORMALIZE2: SHRD EDI,ESI,32-11 ; top 11 bits of ESI known 0 and BSR is slooow BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual) SUB DI,#31 NEG DI PUSH CX ; gr MOV CX,DI ; rr SHLD ESI,EAX,CL SHLD EAX,EBP,CL SHLD EBP,EBX,CL SHL EBX,CL POP CX ; rr SUB CX,DI JC UNDERFLOW ROUND: CMP EBP,#$80000000 ; test roundoff register JA ROUNDUP JB DONE ; no rounding TEST EBX,EBX JNZ ROUNDUP TEST AL,#1 ; ambiguous case, round to even JZ DONE ; even, no rounding ROUNDUP: ADD EAX,#1 ADC ESI,#0 SUB EBP,EBP SUB EBX,EBX TEST ESI,#$00200000 JNZ LOVERFLOW ; rounding may cause overflow! DONE: AND DX,#$0800 ; extract sign of largest and result OR DX,CX ; include exponent with sign DONE1: SHL EDX,32-(1+11) AND ESI,#$000FFFFF ; discard normalization bit OR EDX,ESI POP ESI POP EDI POP EBP RET UNDERFLOW: ; should have error message here ANSWER0: SUB EDX,EDX MOV EAX,EDX POP ESI POP EDI POP EBP RET LOVERFLOW: ; carry bit must be right-shifted back in SHR ESI,1 RCR EAX,1 RCR EBP,1 RCR EBX,1 INC CX CMP CX,#$0800 JNZ ROUND OVERFLOW: ; should have error message here MOV EDX,#$FFE00000 ; + infinity SUB EAX,EAX POP ESI POP EDI POP EBP RET ADD_BIGSHIFT: SUB CL,#32 SHRD EBP,EBX,CL SHRD EBX,EDI,CL SHR EDI,CL ADD EAX,EDI ADC ESI,#0 XCHG EBP,EBX BR NORMALIZE NORMLITTLE: SHLD ESI,EAX,32-(1+11) SHLD EAX,EBP,32-(1+11) SHLD EBP,EBX,32-(1+11) SHL EBX,20 SUB CL,#32-(1+11) JC UNDERFLOW BR NORMALIZE2 SUBTRACT: SUB EBP,EBP ; set up roundoff register CMP CL,#32 JAE SUBTRACT_BIGSHIFT SHRD EBP,EBX,CL SHRD EBX,EDI,CL SHR EDI,CL NEG EBP SBB EAX,EBX SBB ESI,EDI SUB EBX,EBX MOV CX,DX AND CX,#$07FF BR NORMALIZE2 SUBTRACT_BIGSHIFT: SUB CL,#32 SHRD EBP,EBX,CL SHRD EBX,EDI,CL SHR EDI,CL NEG EBX NEG EBP SBB EBX,#0 SBB EAX,EDI SBB ESI,#0 XCHG EBP,EBX MOV CX,DX AND CX,#$07FF BR NORMALIZE2 TO_ANSWER0: BR ANSWER0 TO_OVERFLOW: JMP TO_OVERFLOW TO_UNDERFLOW: BR UNDERFLOW fmulfxfy: PUSH EBP PUSH EDI PUSH ESI MOV ESI,EDX ; free DX for multiplications MOV EDI,ECX ; this mainly for consistent naming SHR EDX,32-(1+11) SHR ECX,32-(1+11) MOV BP,DX XOR BP,CX AND BP,#$0800 ; extract sign AND DX,#$07FF ; exp(x) JZ TO_ANSWER0 AND CX,#$07FF ; exp(y) JZ TO_ANSWER0 ADD CX,DX SUB CX,#$0400 JB TO_UNDERFLOW CMP CX,#$07FF JA TO_OVERFLOW ; probably not quite right AND ESI,#$000FFFFF ; discard sign and exponent AND EDI,#$000FFFFF OR ESI,#$00100000 ; normalize OR EDI,#$00100000 ; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free ; product to go in ESI:EAX:EBP:EBX ; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0 PUSH CX PUSH BP MOV ECX,EAX MUL EBX ; x0y0 MOV EBP,EDX ; x0y0.high in EBP XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX MUL ESI ; x32y0 PUSH EAX ; x32y0.low on stack PUSH EDX ; x32y0.high on stack MOV EAX,ESI MUL EDI ; x32y32 MOV ESI,EDX ; x32y32.high in ESI (final except carries) XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX MUL EDI ; x0y32 ADD EBP,EAX ; x0y0.high + x0y32.low POP EAX ; x32y0.high ADC EAX,EDX ; x32y0.high + x0y32.high ADC ESI,#0 POP EDX ; x32y0.low ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low ADC ESI,#0 POP DX ; sign POP CX ; exponent ADD CX,#13 ; temp fixup BR NORMALIZE2 _facc: .word 0,0 dev86-0.16.17/as/asm/movspec.asm0000644000000000000000000000522605060160502016120 0ustar rootroot00000000000000mov eax,cr0 mov eax,cr2 mov eax,cr3 mov eax,dr0 mov eax,dr1 mov eax,dr2 mov eax,dr3 mov eax,dr6 mov eax,dr7 mov eax,tr3 mov eax,tr4 mov eax,tr5 mov eax,tr6 mov eax,tr7 mov cr0,eax mov cr2,eax mov cr3,eax mov dr0,eax mov dr1,eax mov dr2,eax mov dr3,eax mov dr6,eax mov dr7,eax mov tr3,eax mov tr4,eax mov tr5,eax mov tr6,eax mov tr7,eax mov ebx,cr0 mov ebx,cr2 mov ebx,cr3 mov ebx,dr0 mov ebx,dr1 mov ebx,dr2 mov ebx,dr3 mov ebx,dr6 mov ebx,dr7 mov ebx,tr3 mov ebx,tr4 mov ebx,tr5 mov ebx,tr6 mov ebx,tr7 mov cr0,ebx mov cr2,ebx mov cr3,ebx mov dr0,ebx mov dr1,ebx mov dr2,ebx mov dr3,ebx mov dr6,ebx mov dr7,ebx mov tr3,ebx mov tr4,ebx mov tr5,ebx mov tr6,ebx mov tr7,ebx mov ecx,cr0 mov ecx,cr2 mov ecx,cr3 mov ecx,dr0 mov ecx,dr1 mov ecx,dr2 mov ecx,dr3 mov ecx,dr6 mov ecx,dr7 mov ecx,tr3 mov ecx,tr4 mov ecx,tr5 mov ecx,tr6 mov ecx,tr7 mov cr0,ecx mov cr2,ecx mov cr3,ecx mov dr0,ecx mov dr1,ecx mov dr2,ecx mov dr3,ecx mov dr6,ecx mov dr7,ecx mov tr3,ecx mov tr4,ecx mov tr5,ecx mov tr6,ecx mov tr7,ecx mov edx,cr0 mov edx,cr2 mov edx,cr3 mov edx,dr0 mov edx,dr1 mov edx,dr2 mov edx,dr3 mov edx,dr6 mov edx,dr7 mov edx,tr3 mov edx,tr4 mov edx,tr5 mov edx,tr6 mov edx,tr7 mov cr0,edx mov cr2,edx mov cr3,edx mov dr0,edx mov dr1,edx mov dr2,edx mov dr3,edx mov dr6,edx mov dr7,edx mov tr3,edx mov tr4,edx mov tr5,edx mov tr6,edx mov tr7,edx mov esi,cr0 mov esi,cr2 mov esi,cr3 mov esi,dr0 mov esi,dr1 mov esi,dr2 mov esi,dr3 mov esi,dr6 mov esi,dr7 mov esi,tr3 mov esi,tr4 mov esi,tr5 mov esi,tr6 mov esi,tr7 mov cr0,esi mov cr2,esi mov cr3,esi mov dr0,esi mov dr1,esi mov dr2,esi mov dr3,esi mov dr6,esi mov dr7,esi mov tr3,esi mov tr4,esi mov tr5,esi mov tr6,esi mov tr7,esi mov edi,cr0 mov edi,cr2 mov edi,cr3 mov edi,dr0 mov edi,dr1 mov edi,dr2 mov edi,dr3 mov edi,dr6 mov edi,dr7 mov edi,tr3 mov edi,tr4 mov edi,tr5 mov edi,tr6 mov edi,tr7 mov cr0,edi mov cr2,edi mov cr3,edi mov dr0,edi mov dr1,edi mov dr2,edi mov dr3,edi mov dr6,edi mov dr7,edi mov tr3,edi mov tr4,edi mov tr5,edi mov tr6,edi mov tr7,edi mov esp,cr0 mov esp,cr2 mov esp,cr3 mov esp,dr0 mov esp,dr1 mov esp,dr2 mov esp,dr3 mov esp,dr6 mov esp,dr7 mov esp,tr3 mov esp,tr4 mov esp,tr5 mov esp,tr6 mov esp,tr7 mov cr0,esp mov cr2,esp mov cr3,esp mov dr0,esp mov dr1,esp mov dr2,esp mov dr3,esp mov dr6,esp mov dr7,esp mov tr3,esp mov tr4,esp mov tr5,esp mov tr6,esp mov tr7,esp mov ebp,cr0 mov ebp,cr2 mov ebp,cr3 mov ebp,dr0 mov ebp,dr1 mov ebp,dr2 mov ebp,dr3 mov ebp,dr6 mov ebp,dr7 mov ebp,tr3 mov ebp,tr4 mov ebp,tr5 mov ebp,tr6 mov ebp,tr7 mov cr0,ebp mov cr2,ebp mov cr3,ebp mov dr0,ebp mov dr1,ebp mov dr2,ebp mov dr3,ebp mov dr6,ebp mov dr7,ebp mov tr3,ebp mov tr4,ebp mov tr5,ebp mov tr6,ebp mov tr7,ebp dev86-0.16.17/as/asm/ea.asm0000644000000000000000000000342604321573736015051 0ustar rootroot00000000000000 MOV AX,[BX+SI] MOV AX,[BX+DI] MOV AX,[BP+SI] MOV AX,[BP+DI] MOV AX,[SI] MOV AX,[DI] MOV AX,[0x1234] MOV AX,[BX] MOV AX,[BX+SI+0x12] MOV AX,[BX+DI+0x12] MOV AX,[BP+SI+0x12] MOV AX,[BP+DI+0x12] MOV AX,[SI+0x12] MOV AX,[DI+0x12] MOV AX,[BP+0x12] MOV AX,[BX+0x12] MOV AX,[BX+SI+0x1234] MOV AX,[BX+DI+0x1234] MOV AX,[BP+SI+0x1234] MOV AX,[BP+DI+0x1234] MOV AX,[SI+0x1234] MOV AX,[DI+0x1234] MOV AX,[BP+0x1234] MOV AX,[BX+0x1234] MOV AL,AL MOV AL,AH MOV AL,BL MOV AL,BH MOV AL,CL MOV AL,CH MOV AL,DL MOV AL,DH MOV AX,AX MOV AX,CX MOV AX,DX MOV AX,BX MOV AX,SP MOV AX,BP MOV AX,SI MOV AX,DI MOV AX,[EAX] MOV AX,[ECX] MOV AX,[EDX] MOV AX,[EBX] MOV AX,[0x12345678] MOV AX,[ESI] MOV AX,[EDI] MOV AX,[EAX+0x12] MOV AX,[ECX+0x12] MOV AX,[EDX+0x12] MOV AX,[EBX+0x12] MOV AX,[EBP+0x12] MOV AX,[ESI+0x12] MOV AX,[EDI+0x12] MOV AX,[EAX+0x12345678] MOV AX,[ECX+0x12345678] MOV AX,[EDX+0x12345678] MOV AX,[EBX+0x12345678] MOV AX,[EBP+0x12345678] MOV AX,[ESI+0x12345678] MOV AX,[EDI+0x12345678] MOV EAX,EAX MOV EAX,ECX MOV EAX,EDX MOV EAX,EBX MOV EAX,ESP MOV EAX,EBP MOV EAX,ESI MOV EAX,EDI MOV AX,[EAX+ESI*2] MOV AX,[ECX+ESI*2] MOV AX,[EDX+ESI*2] MOV AX,[EBX+ESI*2] MOV AX,[ESP+ESI*2] MOV AX,[ESI*2+0x12345678] MOV AX,[ESI+ESI*2] MOV AX,[EDI+ESI*2] MOV AX,[EAX+ESI*2+0x12] MOV AX,[ECX+ESI*2+0x12] MOV AX,[EDX+ESI*2+0x12] MOV AX,[EBX+ESI*2+0x12] MOV AX,[ESP+ESI*2+0x12] MOV AX,[ESP+0x12] MOV AX,[EBP+ESI*2+0x12] MOV AX,[ESI+ESI*2+0x12] MOV AX,[EDI+ESI*2+0x12] MOV AX,[EAX+ESI*2+0x12345678] MOV AX,[ECX+ESI*2+0x12345678] MOV AX,[EDX+ESI*2+0x12345678] MOV AX,[EBX+ESI*2+0x12345678] MOV AX,[ESP+ESI*2+0x12345678] MOV AX,[ESP+0x12345678] MOV AX,[EBP+ESI*2+0x12345678] MOV AX,[ESI+ESI*2+0x12345678] MOV AX,[EDI+ESI*2+0x12345678] dev86-0.16.17/as/asm/group6.asm0000644000000000000000000000056104263040352015667 0ustar rootroot00000000000000; group6.asm ; 0F 00 /nnn ; LLDT r/m16 nnn = 010 ; LTR r/m16 nnn = 011 ; SLDT r/m16 nnn = 000 ; STR r/m16 nnn = 001 ; VERR r/m16 nnn = 100 ; VERW r/m16 nnn = 101 LLDT AL ; illeg size LLDT EAX ; illeg size LLDT WORD $1234 ; immed not allowed LLDT DS ; segreg not allowed LLDT AX LLDT [BX] LLDT [EAX] LTR BX SLDT [BP] STR [EBX] VERR CX VERW [SI] dev86-0.16.17/as/pops.c0000644000000000000000000004713307315173043014323 0ustar rootroot00000000000000/* pops.c - handle pseudo-ops for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "flag.h" #include "globvar.h" #include "opcode.h" #include "scan.h" PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */ /* depends on zero = FALSE init */ PRIVATE bool_t lcommflag; FORWARD void bumpsem P((struct flags_s *flagptr, int defval)); FORWARD void constdata P((unsigned size)); FORWARD void docomm P((void)); FORWARD void doelseif P((pfv func)); FORWARD void doequset P((int labits)); FORWARD void doentexp P((int entbits, int impbits)); FORWARD void dofcc P((void)); FORWARD void doif P((pfv func)); FORWARD struct sym_s *needlabel P((void)); FORWARD void showredefinedlabel P((void)); FORWARD void setloc P((unsigned seg)); PRIVATE void bumpsem(flagptr, defval) register struct flags_s *flagptr; int defval; { int newcount; if (flagptr->global && pass == last_pass) { /* bump semaphore count by an expression (default 1), */ /* then set currentflag iff semaphore count is plus */ if (sym == EOLSYM) lastexp.offset = defval; else { absexpres(); if (lastexp.data & UNDBIT) return; } newcount = (int) lastexp.offset; #ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */ if (newcount != lastexp.offset) datatoobig(); #endif newcount += flagptr->semaphore; if ((int) lastexp.offset >= 0) { if (newcount < flagptr->semaphore) { error(COUNTOV); newcount = 0x7fff; } } else if (newcount >= flagptr->semaphore) { error(COUNTUN); newcount = -0x8000; } flagptr->semaphore = newcount; flagptr->current = newcount >= 0; } } /* check symbol is either undefined */ /* or has the same segment & relocatability as lc */ PUBLIC bool_pt checksegrel(symptr) register struct sym_s *symptr; { if ((symptr->type & LABIT || (symptr->data & IMPBIT && !(symptr->data & UNDBIT))) && ((symptr->data ^ lcdata) & (RELBIT | SEGM))) { error(SEGREL); return FALSE; } return TRUE; } /* check address fits in 1 byte (possibly with sign truncated) */ PUBLIC void checkdatabounds() { if (!(lastexp.data & UNDBIT) && (offset_t) (lastexp.offset + 0x80) >= 0x180) datatoobig(); } /* allocate constant data (zero except for size 1), default zero for size 1 */ PRIVATE void constdata(size) unsigned size; { offset_t remaining; absexpres(); if (!((lcdata |= lastexp.data) & UNDBIT)) { lcjump = lastexp.offset * size; popflags = POPLONG | POPHI | POPLO | POPLC; if (size == 1 && sym == COMMA) { symabsexpres(); checkdatabounds(); for (remaining = lcjump; remaining != 0; --remaining) { putbin((opcode_pt) lastexp.offset); /* fill byte */ putabs((opcode_pt) lastexp.offset); } lastexp.offset = lcjump; } else accumulate_rmb(lastexp.offset * size); } } PUBLIC void datatoobig() { error(DBOUNDS); } /* common routine for COMM/.COMM */ PRIVATE void docomm() { register struct sym_s *labptr; absexpres(); /* if undefined, value 0 and size unchanged */ labptr = label; if (checksegrel(labptr)) { if (labptr->type & (EXPBIT | LABIT)) labelerror(ALREADY); else { if (!(labptr->type & COMMBIT) || lastexp.offset > labptr->value_reg_or_op.value) labptr->value_reg_or_op.value = lastexp.offset; labptr->type |= COMMBIT; if (lcommflag) labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */ if( last_pass == 1 ) labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT); else labptr->data = (lcdata & SEGM) | (IMPBIT | RELBIT); showlabel(); } } lcommflag = FALSE; } /* common routine for ELSEIF/ELSEIFC */ PRIVATE void doelseif(func) pfv func; { if (iflevel == 0) error(ELSEIFBAD); else { ifflag = FALSE; if (elseflag) { (*func) (); if (!(lastexp.data & UNDBIT) && lastexp.offset != 0) /* expression valid and TRUE, enable assembling */ { ifflag = TRUE; elseflag = FALSE; } } else { /* Skip to EOL */ while (sym != EOLSYM) getsym(); } } } /* common routine for EQU/SET */ PRIVATE void doequset(labits) unsigned char labits; { register struct sym_s *labptr; unsigned char olddata; unsigned char oldtype; labptr = label; /* set up new label flags in case labe isl used in expression */ labptr->type = (oldtype = labptr->type) | labits; labptr->data = (olddata = labptr->data) & ~IMPBIT; /* non-imported now */ nonimpexpres(); lastexp.data |= olddata & FORBIT; /* take all but FORBIT from expression */ if (oldtype & LABIT && !(olddata & UNDBIT) && !pass) /* this is a previously defined label */ /* redefinition only allowed if same relocatability, segment and value */ { if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) || labptr->value_reg_or_op.value != lastexp.offset) { showredefinedlabel(); return; } } labptr->data = lastexp.data; labptr->value_reg_or_op.value = lastexp.offset; showlabel(); if(pass && !(labits & VARBIT) && labptr->value_reg_or_op.value != oldlabel) { dirty_pass = TRUE; if( pass == last_pass ) error(UNSTABLE_LABEL); } } /* common routine for ENTRY/EXPORT */ PRIVATE void doentexp(entbits, impbits) unsigned char entbits; unsigned char impbits; { struct sym_s *symptr; while (TRUE) { if ((symptr = needlabel()) != NUL_PTR) { if (symptr->type & COMMBIT) error(ALREADY); else if (impbits != 0) { if (pass == last_pass) ; else if (symptr->type & (EXPBIT | LABIT)) symptr->type |= EXPBIT; else { symptr->type |= REDBIT; if (!(symptr->data & IMPBIT)) symptr->data |= IMPBIT | SEGM; } } else { if (pass == last_pass) { if (!(symptr->type & LABIT)) error(UNLAB); } else { symptr->type |= entbits | EXPBIT; symptr->data &= ~IMPBIT; } } } getsym(); if (sym != COMMA) break; getsym(); } } /* common routine for FCC (== .ASCII) and .ASCIZ */ PRIVATE void dofcc() { register char *bufptr; char byte; char delimiter; register char *reglineptr; bufptr = databuf.fcbuf; reglineptr = symname; if ((delimiter = *reglineptr) != EOLCHAR) ++reglineptr; while (TRUE) { if ((byte = *reglineptr) == EOLCHAR) { symname = reglineptr; error(DELEXP); break; } if (byte == delimiter) { if ((byte = *++reglineptr) != delimiter) break; } else if (byte == '\\') { switch (byte = *++reglineptr) { case '"': case '\'': case '\\': case '?': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': byte -= '0'; if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8') { byte = 8 * byte + *++reglineptr - '0'; if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8') byte = 8 * byte + *++reglineptr - '0'; } break; case 'a': byte = 7; break; case 'b': byte = 8; break; case 'f': byte = 12; break; case 'n': byte = 10; break; case 'r': byte = 13; break; case 't': byte = 9; break; case 'v': byte = 11; break; case 'x': byte = '0'; while (TRUE) { ++reglineptr; if (*reglineptr >= '0' && *reglineptr <= '9') byte = 16 * byte + *reglineptr - '0'; else if (*reglineptr >= 'F' && *reglineptr <= 'F') byte = 16 * byte + *reglineptr - 'A'; else if (*reglineptr >= 'a' && *reglineptr <= 'f') byte = 16 * byte + *reglineptr - 'F'; else break; } --reglineptr; break; default: symname = reglineptr; error(UNKNOWN_ESCAPE_SEQUENCE); break; } } else if (byte < ' ' && byte >= 0) { symname = reglineptr; error(CTLINS); byte = ' '; } ++reglineptr; *bufptr++ = byte; } lineptr = reglineptr; getsym(); lastexp.offset = databuf.fcbuf[0]; /* show only 1st char (if any) */ mcount = bufptr - databuf.fcbuf; /* won't overflow, line length limits it */ /* XXX - but now line length is unlimited */ } /* common routine for IF/IFC */ PRIVATE void doif(func) pfv func; { if (iflevel >= MAXIF) error(IFOV); else { ++iflevel; --ifstak; ifstak->elseflag = elseflag; elseflag = FALSE; /* prepare */ if ((ifstak->ifflag = ifflag) != FALSE) /* else not assembling before, so not now & no ELSE's */ { (*func) (); if (!(lastexp.data & UNDBIT) && lastexp.offset == 0) /* else expression invalid or FALSE, don't change flags */ { ifflag = FALSE; /* not assembling */ elseflag = TRUE;/* but ELSE will change that */ } } else { /* Skip to EOL */ while (sym != EOLSYM) getsym(); } } } PUBLIC void fatalerror(err_str) char * err_str; { error(err_str); skipline(); listline(); finishup(); } /* swap position with label position, do error, put back posn */ /* also clear label ptr */ PUBLIC void labelerror(err_str) char * err_str; { struct sym_s *oldgsymptr; char *oldlineptr; unsigned char oldsym; char *oldsymname; oldgsymptr = gsymptr; oldlineptr = lineptr; oldsym = sym; oldsymname = symname; lineptr = linebuf; getsym(); /* 1st symbol is label or symbol after * missing one */ error(err_str); gsymptr = oldgsymptr; lineptr = oldlineptr; sym = oldsym; symname = oldsymname; label = NUL_PTR; } PRIVATE struct sym_s *needlabel() { register struct sym_s *symptr; if (sym != IDENT || (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT)) { error(LABEXP); return NUL_PTR; } return symptr; } /* .ALIGN pseudo-op */ PUBLIC void palign() { absexpres(); if (!((lcdata |= lastexp.data) & UNDBIT)) { popflags = POPLONG | POPHI | POPLO | POPLC; if (lastexp.offset != 0 && (lcjump = lc % lastexp.offset) != 0) accumulate_rmb(lcjump = lastexp.offset - lcjump); } } /* .ASCIZ pseudo-op */ PUBLIC void pasciz() { dofcc(); databuf.fcbuf[mcount++] = 0; fcflag = TRUE; popflags = POPLO | POPLC; } /* .BLKW pseudo-op */ PUBLIC void pblkw() { constdata(2); } /* BLOCK pseudo-op */ PUBLIC void pblock() { if (blocklevel >= MAXBLOCK) error(BLOCKOV); else { register struct block_s *blockp; ++blocklevel; blockp = blockstak; blockstak = --blockp; blockp->data = lcdata; blockp->dp = dirpag; blockp->lc = lc; porg(); /* same as ORG apart from stacking */ } } /* .BSS pseudo-op */ PUBLIC void pbss() { setloc(BSSLOC); } /* COMM pseudo-op */ PUBLIC void pcomm() { if (label == NUL_PTR) labelerror(MISLAB); else if (label->type & VARBIT) labelerror(VARLAB); /* variable cannot be COMM'd */ else docomm(); } /* .COMM pseudo-op */ PUBLIC void pcomm1() { unsigned oldseg; if (label != NUL_PTR) labelerror(ILLAB); oldseg = lcdata & SEGM; setloc(BSSLOC); if ((label = needlabel()) != NUL_PTR && checksegrel(label)) { /* Like import. */ if (label->type & (EXPBIT | LABIT)) error(ALREADY); else if( last_pass == 1 ) label->data = lcdata | (FORBIT | IMPBIT | RELBIT); else label->data = lcdata | (IMPBIT | RELBIT); getsym(); getcomma(); if (label->type & (EXPBIT | LABIT)) absexpres(); /* just to check it */ else docomm(); } setloc(oldseg); } /* .DATA pseudo-op */ PUBLIC void pdata() { setloc(DATALOC); } /* ELSE pseudo-op */ PUBLIC void pelse() { if (iflevel == 0) error(ELSEBAD); else { ifflag = FALSE; /* assume ELSE disabled */ if (elseflag) { ifflag = TRUE; /* ELSE enabled */ elseflag = FALSE; } } } /* ELSEIF pseudo-op */ PUBLIC void pelseif() { doelseif(absexpres); } /* ELSEIFC pseudo-op */ PUBLIC void pelsifc() { doelseif(scompare); } /* ENDB pseudo-op */ PUBLIC void pendb() { if (label != NUL_PTR) labelerror(ILLAB); if (blocklevel == 0) error(ENDBBAD); else { register struct block_s *blockp; blockp = blockstak; lcdata = blockp->data; dirpag = blockp->dp; accumulate_rmb(blockp->lc - lc); lc = blockp->lc; --blocklevel; blockstak = blockp + 1; } } /* ENDIF pseudo-op */ PUBLIC void pendif() { if (iflevel == 0) error(ENDIFBAD); else { ifflag = ifstak->ifflag; elseflag = ifstak->elseflag; ++ifstak; --iflevel; } } /* ENTER pseudo-op */ PUBLIC void penter() { if (!(pedata & UNDBIT)) error(REENTER); else { if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT)) { progent = lc; popflags = POPLC; } } } /* ENTRY pseudo-op */ PUBLIC void pentry() { doentexp(ENTBIT, 0); } /* EQU pseudo-op */ PUBLIC void pequ() { register struct sym_s *labptr; if ((labptr = label) == NUL_PTR) labelerror(MISLAB); else if (labptr->type & COMMBIT) showredefinedlabel(); /* common cannot be EQU'd */ else if (labptr->type & VARBIT) labelerror(VARLAB); /* variable cannot be EQU'd */ else doequset(LABIT); } /* .EVEN pseudo-op */ PUBLIC void peven() { popflags = POPLONG | POPHI | POPLO | POPLC; accumulate_rmb(lcjump = lastexp.data = lc & 1); } /* EXPORT pseudo-op */ PUBLIC void pexport() { doentexp(0, 0); } /* FAIL pseudo-op */ PUBLIC void pfail() { if(pass==last_pass) error(FAILERR); } /* FCB pseudo-op */ PUBLIC void pfcb() { char *bufptr; offset_t firstbyte; bufptr = databuf.fcbuf; absexpres(); firstbyte = lastexp.offset; while (TRUE) { checkdatabounds(); *bufptr++ = lastexp.offset; ++mcount; /* won't overflow, line length limits it */ if (sym != COMMA) break; symabsexpres(); } lastexp.offset = firstbyte; popflags = POPLO | POPLC; fcflag = TRUE; } /* FCC pseudo-op */ PUBLIC void pfcc() { dofcc(); if (mcount != 0) { fcflag = TRUE; popflags = POPLO | POPLC; } } /* FDB pseudo-op */ PUBLIC void pfdb() { struct address_s *adrptr; unsigned firstdata; offset_t firstword; adrptr = databuf.fdbuf; expres(); firstword = lastexp.offset; firstdata = lastexp.data; while (TRUE) { *adrptr++ = lastexp; mcount += 2; /* won't overflow, line length limits it */ if (sym != COMMA) break; symexpres(); } lastexp.offset = firstword; lastexp.data = firstdata; popflags = POPHI | POPLO | POPLC; fdflag = TRUE; } #if SIZEOF_OFFSET_T > 2 /* FQB pseudo-op */ PUBLIC void pfqb() { struct address_s *adrptr; offset_t firstdata; offset_t firstword; adrptr = databuf.fqbuf; expres(); firstword = lastexp.offset; firstdata = lastexp.data; while (TRUE) { *adrptr++ = lastexp; mcount += 4; /* won't overflow, line length limits it */ if (sym != COMMA) break; symexpres(); } lastexp.offset = firstword; lastexp.data = firstdata; popflags = POPLONG | POPHI | POPLO | POPLC; fqflag = TRUE; } #endif /* SIZEOF_OFFSET_T > 2 */ /* .GLOBL pseudo-op */ PUBLIC void pglobl() { if (binaryg) error(NOIMPORT); doentexp(0, IMPBIT); } /* IDENT pseudo-op (not complete) */ PUBLIC void pident() { if (sym != IDENT) error(LABEXP); else getsym_nolookup(); /* should save ident string */ } /* IF pseudo-op */ PUBLIC void pif() { doif(absexpres); } /* IFC pseudo-op */ PUBLIC void pifc() { doif(scompare); } /* IMPORT pseudo-op */ PUBLIC void pimport() { struct sym_s *symptr; if (binaryg) error(NOIMPORT); while (TRUE) { if ((symptr = needlabel()) != NUL_PTR && checksegrel(symptr)) { if (symptr->type & (COMMBIT | EXPBIT | LABIT)) /* IMPORT is null if label (to be) declared */ error(ALREADY); else if( last_pass == 1 ) /* get current segment from lcdata, no need to mask rest */ symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT); else symptr->data = lcdata | (IMPBIT | RELBIT); } getsym(); if (sym != COMMA) break; getsym(); } } /* LCOMM pseudo-op */ PUBLIC void plcomm() { lcommflag = TRUE; pcomm(); } /* .LCOMM pseudo-op */ PUBLIC void plcomm1() { lcommflag = TRUE; pcomm1(); } /* .LIST pseudo-op */ PUBLIC void plist() { bumpsem(&list, 1); } /* .NOLIST pseudo-op */ PUBLIC void pnolist() { bumpsem(&list, -1); } /* LOC pseudo-op */ PUBLIC void ploc() { if (label != NUL_PTR) labelerror(ILLAB); absexpres(); if (!(lastexp.data & UNDBIT)) { if (lastexp.offset >= NLOC) datatoobig(); else setloc((unsigned) lastexp.offset); } } /* .MACLIST pseudo-op */ PUBLIC void pmaclist() { bumpsem(&maclist, 1); } /* .MAP pseudo-op */ PUBLIC void pmap() { absexpres(); if (!(lastexp.data & UNDBIT)) { mapnum = lastexp.offset; popflags = POPLO; if (lastexp.offset >= 0x100) datatoobig(); } } /* ORG pseudo-op */ PUBLIC void porg() { if (label != NUL_PTR) labelerror(ILLAB); absexpres(); if (!((lcdata = lastexp.data) & UNDBIT)) { accumulate_rmb(lastexp.offset - lc); binmbuf = lc = lastexp.offset; binmbuf_set = 1; popflags = POPLC; } } /* RMB pseudo-op */ PUBLIC void prmb() { constdata(1); } /* .SECT pseudo-op */ PUBLIC void psect() { if (label != NUL_PTR) labelerror(ILLAB); while (sym == IDENT) { if (!(gsymptr->type & MNREGBIT)) error(ILL_SECTION); else switch (gsymptr->value_reg_or_op.op.routine) { case BSSOP: pbss(); break; case DATAOP: pdata(); break; case TEXTOP: ptext(); break; default: error(ILL_SECTION); break; } getsym(); if (sym == COMMA) getsym(); } } /* SET pseudo-op */ PUBLIC void pset() { register struct sym_s *labptr; if ((labptr = label) == NUL_PTR) labelerror(MISLAB); else if (labptr->type & COMMBIT) labelerror(RELAB); /* common cannot be SET'd */ else doequset(labptr->type & LABIT ? 0 : VARBIT); } /* SETDP pseudo-op */ PUBLIC void psetdp() { absexpres(); if (!(lastexp.data & UNDBIT)) { dirpag = lastexp.offset; popflags = POPLO; if (lastexp.offset >= 0x100) datatoobig(); } } /* .TEXT pseudo-op */ PUBLIC void ptext() { if( textseg <= 0 ) setloc(TEXTLOC); else setloc(textseg); } /* .WARN pseudo-op */ PUBLIC void pwarn() { bumpsem(&as_warn, -1); } #ifdef I80386 /* USE16 pseudo-op */ PUBLIC void puse16() { defsize = 2; #ifdef iscpu if( sym != EOLSYM ) { absexpres(); if (lastexp.data & UNDBIT) return; if( lastexp.offset > 8000 ) setcpu((int) lastexp.offset / 100 % 10); else if( lastexp.offset > 15 ) setcpu((int) lastexp.offset / 100); else setcpu((int) lastexp.offset); } #endif } /* USE16 pseudo-op */ PUBLIC void puse32() { defsize = 4; #ifdef iscpu if(!iscpu(3)) setcpu(3); if( sym != EOLSYM ) { absexpres(); if (lastexp.data & UNDBIT) return; if( lastexp.offset > 15 ) setcpu((int) lastexp.offset / 100); else setcpu((int) lastexp.offset); } #endif } #endif /* show redefined label and error, and set REDBIT */ PRIVATE void showredefinedlabel() { register struct sym_s *labptr; labptr = label; /* showlabel() will kill label prematurely */ showlabel(); if (!(labptr->type & REDBIT)) { labptr->type |= REDBIT; labelerror(RELAB); } } PUBLIC void showlabel() { register struct sym_s *labptr; labptr = label; lastexp.data = labptr->data; lastexp.offset = labptr->value_reg_or_op.value; popflags = POPLONG | POPHI | POPLO; label = NUL_PTR; /* show handled by COMM, EQU or SET */ } /* set location segment */ PRIVATE void setloc(seg) unsigned seg; { if (pass == last_pass && seg != (lcdata & SEGM)) putobj((opcode_pt) (seg | OBJ_SET_SEG)); { register struct lc_s *lcp; lcp = lcptr; lcp->data = lcdata; lcp->lc = lc; lcptr = lcp = lctab + (unsigned char) seg; lcdata = (lcp->data & ~SEGM) | (unsigned char) seg; binmbuf = lc = lcp->lc; popflags = POPLC; } } dev86-0.16.17/as/scan.c0000644000000000000000000001435307316373142014267 0ustar rootroot00000000000000/* scan.c - lexical analyser for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #undef EXTERN #define EXTERN #include "scan.h" PRIVATE int numbase; /* base for number */ PRIVATE char symofchar[256] = /* table to convert chars to their symbols */ { EOLSYM, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */ HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ COMMA, SUBOP, IDENT, SLASH, /* ,-./ */ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */ LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */ INDIRECT, IDENT, IDENT, IDENT, /* @ABC */ IDENT, IDENT, IDENT, IDENT, /* DEFG */ IDENT, IDENT, IDENT, IDENT, /* HIJK */ IDENT, IDENT, IDENT, IDENT, /* LMNO */ IDENT, IDENT, IDENT, IDENT, /* PQRS */ IDENT, IDENT, IDENT, IDENT, /* TUVW */ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */ OTHERSYM, IDENT, IDENT, IDENT, /* `abc */ IDENT, IDENT, IDENT, IDENT, /* defg */ IDENT, IDENT, IDENT, IDENT, /* hijk */ IDENT, IDENT, IDENT, IDENT, /* lmno */ IDENT, IDENT, IDENT, IDENT, /* pqrs */ IDENT, IDENT, IDENT, IDENT, /* tuvw */ IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */ OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE }; FORWARD void intconst P((void)); PUBLIC void context_hexconst() { numbase = 16; intconst(); } PUBLIC void getsym() { register char *reglineptr; reglineptr = lineptr; advance: symname = reglineptr; switch (sym = symofchar[(unsigned char) *reglineptr++]) { case WHITESPACE: goto advance; case ADDOP: if (*reglineptr == '+') { sym = POSTINCOP; ++reglineptr; } break; case BINCONST: numbase = 2; lineptr = reglineptr; intconst(); return; case CHARCONST: if ((number = *reglineptr) < ' ') number = ' '; if (*reglineptr != EOL) ++reglineptr; sym = INTCONST; break; case GREATERTHAN: /* context-sensitive */ if (*reglineptr == '>') { sym = SROP; ++reglineptr; } break; case HEXCONST: numbase = 16; lineptr = reglineptr; intconst(); return; case IDENT: /* walk to end of identifier - magic INTCONST is max of INT, IDENT */ while (symofchar[(unsigned char) *reglineptr] <= INTCONST) ++reglineptr; lineptr = reglineptr; gsymptr = lookup(); return; case INTCONST: if (*(reglineptr - 1) == '0') { if (*reglineptr != 'x' && *reglineptr != 'X') numbase = 8; else { numbase = 16; ++reglineptr; } } else { --reglineptr; numbase = 10; } lineptr = reglineptr; intconst(); return; case LESSTHAN: /* context-sensitive */ if (*reglineptr == '<') { sym = SLOP; ++reglineptr; } break; case SUBOP: if (*reglineptr == '-') { sym = PREDECOP; ++reglineptr; } break; } lineptr = reglineptr; return; } PUBLIC void getsym_nolookup() { bool_t old_ifflag; old_ifflag = ifflag; ifflag = FALSE; getsym(); ifflag = old_ifflag; } PRIVATE void intconst() { register char *reglineptr; number = 0; reglineptr = lineptr; for (; *reglineptr >= '0'; ++reglineptr) { if (*reglineptr > '9') { if (numbase != 16) break; if (*reglineptr >= 'a' && *reglineptr <= 'f') { if (number != 0) number = numbase * number + (*reglineptr - 'a' + 10); else number = *reglineptr - 'a' + 10; } else if (*reglineptr >= 'A' && *reglineptr <= 'F') { if (number != 0) number = numbase * number + (*reglineptr - 'A' + 10); else number = *reglineptr - 'A' + 10; } else break; } else if (number != 0) number = numbase * number + (*reglineptr - '0'); else number = *reglineptr - '0'; } if (*reglineptr == 'L' || *reglineptr == 'l') ++reglineptr; sym = INTCONST; lineptr = reglineptr; } PUBLIC void initscan() { #ifndef MC6809 if (asld_compatible) { lindirect = LPAREN; rindexp = RPEXP; rindirect = RPAREN; } else { #endif lindirect = LBRACKET; rindexp = RBEXP; rindirect = RBRACKET; #ifndef MC6809 } #endif } dev86-0.16.17/as/errors.c0000644000000000000000000001156107774532307014665 0ustar rootroot00000000000000 #include "syshead.h" #include "const.h" #include "errors.h" /* Error codes. */ /* Syntax errors. */ PUBLIC char COMEXP[] = "comma expected"; PUBLIC char DELEXP[] = "delimiter expected"; PUBLIC char FACEXP[] = "factor expected"; PUBLIC char IREGEXP[] = "index register expected"; PUBLIC char LABEXP[] = "label expected"; PUBLIC char LPEXP[] = "left parentheses expected"; PUBLIC char OPEXP[] = "opcode expected"; PUBLIC char RBEXP[] = "right bracket expected"; PUBLIC char REGEXP[] = "register expected"; PUBLIC char RPEXP[] = "right parentheses expected"; PUBLIC char SPEXP[] = "space expected"; /* Expression errors. */ PUBLIC char ABSREQ[] = "absolute expression required"; PUBLIC char NONIMPREQ[] = "non-imported expression required"; PUBLIC char RELBAD[] = "relocation impossible"; /* Label errors. */ PUBLIC char ILLAB[] = "illegal label"; PUBLIC char MACUID[] = "MACRO used as identifier"; PUBLIC char MISLAB[] = "missing label"; PUBLIC char MNUID[] = "opcode used as identifier"; PUBLIC char REGUID[] = "register used as identifier"; PUBLIC char RELAB[] = "redefined label"; PUBLIC char UNBLAB[] = "unbound label"; PUBLIC char UNLAB[] = "undefined label"; PUBLIC char VARLAB[] = "variable used as label"; /* Addressing errors. */ PUBLIC char ABOUNDS[] = "address out of bounds"; PUBLIC char DBOUNDS[] = "data out of bounds"; PUBLIC char ILLMOD[] = "illegal address mode"; PUBLIC char ILLREG[] = "illegal register"; /* Control structure errors. */ PUBLIC char ELSEBAD[] = "no matching IF"; PUBLIC char ENDBBAD[] = "no matching BLOCK"; PUBLIC char EOFBLOCK[] = "end of file in BLOCK"; PUBLIC char EOFIF[] = "end of file in IF"; PUBLIC char EOFLC[] = "location counter was undefined at end"; PUBLIC char EOFMAC[] = "end of file in MACRO"; PUBLIC char FAILERR[] = "user-generated error"; /* Overflow errors. */ PUBLIC char BLOCKOV[] = "BLOCK stack overflow"; PUBLIC char BWRAP[] = "binary file wrap-around"; PUBLIC char COUNTOV[] = "counter overflow"; PUBLIC char COUNTUN[] = "counter underflow"; PUBLIC char GETOV[] = "GET stack overflow"; PUBLIC char IFOV[] = "IF stack overflow"; PUBLIC char LINLONG[] = "line too long"; PUBLIC char MACOV[] = "MACRO stack overflow"; PUBLIC char OBJSYMOV[] = "object symbol table overflow"; PUBLIC char OWRITE[] = "program overwrite"; PUBLIC char PAROV[] = "parameter table overflow"; PUBLIC char SYMOV[] = "symbol table overflow"; PUBLIC char SYMOUTOV[] = "output symbol table overflow"; /* I/O errors. */ PUBLIC char OBJOUT[] = "error writing object file"; /* Miscellaneous errors. */ PUBLIC char AL_AX_EAX_EXP[] = "al ax or eax expected"; PUBLIC char CTLINS[] = "control character in string"; PUBLIC char FURTHER[] = "futher errors suppressed"; PUBLIC char ILL_IMM_MODE[] = "illegal immediate mode"; PUBLIC char ILL_IND_TO_IND[] = "illegal indirect to indirect"; PUBLIC char ILL_IND[] = "illegal indirection"; PUBLIC char ILL_IND_PTR[] = "illegal indirection from previous 'ptr'"; PUBLIC char ILL_SCALE[] = "illegal scale"; PUBLIC char ILL_SECTION[] = "illegal section"; PUBLIC char ILL_SEG_REG[] = "illegal segment register"; PUBLIC char ILL_SOURCE_EA[] = "illegal source effective address"; PUBLIC char ILL_SIZE[] = "illegal size"; PUBLIC char IMM_REQ[] = "immediate expression expected"; PUBLIC char INDEX_REG_EXP[] = "index register expected"; PUBLIC char IND_REQ[] = "indirect expression required"; PUBLIC char MISMATCHED_SIZE[] = "mismatched size"; PUBLIC char NOIMPORT[] = "no imports with binary file output"; PUBLIC char REENTER[] = "multiple ENTER pseudo-ops"; PUBLIC char REL_REQ[] = "relative expression required"; PUBLIC char REPEATED_DISPL[] = "repeated displacement"; PUBLIC char SEGREL[] = "segment or relocatability redefined"; PUBLIC char SEG_REG_REQ[] = "segment register required"; PUBLIC char SIZE_UNK[] = "size unknown"; PUBLIC char UNKNOWN_ESCAPE_SEQUENCE[] = "unknown escape sequence"; PUBLIC char FP_REG_REQ[] = "FP register required"; PUBLIC char FP_REG_NOT_ALLOWED[] = "FP register not allowed"; PUBLIC char ILL_FP_REG[] = "illegal FP register"; PUBLIC char ILL_FP_REG_PAIR[] = "illegal FP register pair"; PUBLIC char JUNK_AFTER_OPERANDS[] = "junk after operands"; PUBLIC char ALREADY[] = "already defined"; PUBLIC char UNSTABLE_LABEL[] = "label moved in last pass add -O?"; /* Warnings. */ PUBLIC char CPUCLASH[] = "instruction illegal for current cpu"; PUBLIC char SHORTB[] = "short branch would do"; dev86-0.16.17/as/errors.h0000644000000000000000000001240007774532307014663 0ustar rootroot00000000000000/* Error codes. */ /* Syntax errors. */ EXTERN char COMEXP[]; /* "comma expected" */ EXTERN char DELEXP[]; /* "delimiter expected" */ EXTERN char FACEXP[]; /* "factor expected" */ EXTERN char IREGEXP[]; /* "index register expected" */ EXTERN char LABEXP[]; /* "label expected" */ EXTERN char LPEXP[]; /* "left parentheses expected" */ EXTERN char OPEXP[]; /* "opcode expected" */ EXTERN char RBEXP[]; /* "right bracket expected" */ EXTERN char REGEXP[]; /* "register expected" */ EXTERN char RPEXP[]; /* "right parentheses expected" */ EXTERN char SPEXP[]; /* "space expected" */ /* Expression errors. */ EXTERN char ABSREQ[]; /* "absolute expression required" */ EXTERN char NONIMPREQ[]; /* "non-imported expression required" */ EXTERN char RELBAD[]; /* "relocation impossible" */ /* Label errors. */ EXTERN char ILLAB[]; /* "illegal label" */ EXTERN char MACUID[]; /* "MACRO used as identifier" */ EXTERN char MISLAB[]; /* "missing label" */ EXTERN char MNUID[]; /* "opcode used as identifier" */ EXTERN char REGUID[]; /* "register used as identifier" */ EXTERN char RELAB[]; /* "redefined label" */ EXTERN char UNBLAB[]; /* "unbound label" */ EXTERN char UNLAB[]; /* "undefined label" */ EXTERN char VARLAB[]; /* "variable used as label" */ /* Addressing errors. */ EXTERN char ABOUNDS[]; /* "address out of bounds" */ EXTERN char DBOUNDS[]; /* "data out of bounds" */ EXTERN char ILLMOD[]; /* "illegal address mode" */ EXTERN char ILLREG[]; /* "illegal register" */ /* Control structure errors. */ EXTERN char ELSEBAD[]; /* "no matching IF" */ #define ELSEIFBAD ELSEBAD EXTERN char ENDBBAD[]; /* "no matching BLOCK" */ #define ENDIFBAD ELSEBAD EXTERN char EOFBLOCK[]; /* "end of file in BLOCK" */ EXTERN char EOFIF[]; /* "end of file in IF" */ EXTERN char EOFLC[]; /* "location counter was undefined at end" */ EXTERN char EOFMAC[]; /* "end of file in MACRO" */ EXTERN char FAILERR[]; /* "user-generated error" */ /* Overflow errors. */ EXTERN char BLOCKOV[]; /* "BLOCK stack overflow" */ EXTERN char BWRAP[]; /* "binary file wrap-around" */ EXTERN char COUNTOV[]; /* "counter overflow" */ EXTERN char COUNTUN[]; /* "counter underflow" */ EXTERN char GETOV[]; /* "GET stack overflow" */ EXTERN char IFOV[]; /* "IF stack overflow" */ EXTERN char LINLONG[]; /* "line too long" */ EXTERN char MACOV[]; /* "MACRO stack overflow" */ EXTERN char OBJSYMOV[]; /* "object symbol table overflow" */ EXTERN char OWRITE[]; /* "program overwrite" */ EXTERN char PAROV[]; /* "parameter table overflow" */ EXTERN char SYMOV[]; /* "symbol table overflow" */ EXTERN char SYMOUTOV[]; /* "output symbol table overflow" */ /* I/O errors. */ EXTERN char OBJOUT[]; /* "error writing object file" */ /* Miscellaneous errors. */ EXTERN char AL_AX_EAX_EXP[]; /* "al ax or eax expected" */ EXTERN char CTLINS[]; /* "control character in string" */ EXTERN char FURTHER[]; /* "futher errors suppressed" */ EXTERN char ILL_IMM_MODE[]; /* "illegal immediate mode" */ EXTERN char ILL_IND_TO_IND[]; /* "illegal indirect to indirect" */ EXTERN char ILL_IND[]; /* "illegal indirection" */ EXTERN char ILL_IND_PTR[]; /* "illegal indirection from previous 'ptr'" */ EXTERN char ILL_SCALE[]; /* "illegal scale" */ EXTERN char ILL_SECTION[]; /* "illegal section" */ EXTERN char ILL_SEG_REG[]; /* "illegal segment register" */ EXTERN char ILL_SOURCE_EA[]; /* "illegal source effective address" */ EXTERN char ILL_SIZE[]; /* "illegal size" */ EXTERN char IMM_REQ[]; /* "immediate expression expected" */ EXTERN char INDEX_REG_EXP[]; /* "index register expected" */ EXTERN char IND_REQ[]; /* "indirect expression required" */ EXTERN char MISMATCHED_SIZE[]; /* "mismatched size" */ EXTERN char NOIMPORT[]; /* "no imports with binary file output" */ EXTERN char REENTER[]; /* "multiple ENTER pseudo-ops" */ EXTERN char REL_REQ[]; /* "relative expression required" */ EXTERN char REPEATED_DISPL[]; /* "repeated displacement" */ EXTERN char SEGREL[]; /* "segment or relocatability redefined" */ EXTERN char SEG_REG_REQ[]; /* "segment register required" */ EXTERN char SIZE_UNK[]; /* "size unknown" */ EXTERN char UNKNOWN_ESCAPE_SEQUENCE[]; /* "unknown escape sequence" */ EXTERN char FP_REG_REQ[]; /* "FP register required" */ EXTERN char FP_REG_NOT_ALLOWED[]; /* "FP register not allowed" */ EXTERN char ILL_FP_REG[]; /* "illegal FP register" */ EXTERN char ILL_FP_REG_PAIR[]; /* "illegal FP register pair" */ EXTERN char JUNK_AFTER_OPERANDS[]; /* "junk after operands" */ EXTERN char ALREADY[]; /* "already defined" */ EXTERN char UNSTABLE_LABEL[]; /* "label moved in last pass add -O?" */ /* Warnings. */ EXTERN char CPUCLASH[]; /* "instruction illegal for current cpu" */ EXTERN char SHORTB[]; /* "short branch would do" */ dev86-0.16.17/as/syshead.h0000644000000000000000000000261107573467441015015 0ustar rootroot00000000000000 #ifndef POSIX_HEADERS_MISSING #include #include #include #include #endif #ifndef STDC_HEADERS_MISSING #include #include #include #endif #ifdef MSDOS #include #include #include #include #undef min #undef POSIX_HEADERS_MISSING #define VERSION "MSDOS Compile" #endif #if __STDC__ && !defined(__minix) #define P(x) x #else #define P(x) () #endif #ifdef STDC_HEADERS_MISSING char *strcpy P((char *s1, const char *s2)); char *strrchr P((const char *s, int c)); int memcmp P((const void *s1, const void *s2, unsigned n)); int strcmp P((const char *s1, const char *s2)); int strncmp P((const char *s1, const char *s2, unsigned n)); unsigned strlen P((const char *s)); void *malloc P((unsigned size)); void *memset P((void *s, int c, unsigned n)); void exit P((int status)); #endif #ifdef POSIX_HEADERS_MISSING int close P((int fd)); int creat P((const char *path, int mode)); int open P((const char *path, int oflag, ...)); int read P((int fd, void *buf, unsigned nbytes)); int write P((int fd, const void *buf, unsigned nbytes)); typedef long off_t; off_t lseek P((int fd, off_t offset, int whence)); #define BIGBUFFER 0 /* Can't use a big buffer ... sorry */ #endif #ifndef O_RDONLY #define O_RDONLY 0 #endif #ifndef O_WRONLY #define O_WRONLY 1 #endif #ifndef O_RDWR #define O_RDWR 2 #endif dev86-0.16.17/as/table.c0000644000000000000000000001214610065302440014414 0ustar rootroot00000000000000/* table.c - keyword tables and symbol table lookup for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "opcode.h" #include "scan.h" #define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */ #ifdef I80386 # ifdef MNSIZE EXTERN char bytesizeops[]; # endif #endif EXTERN char ops[]; EXTERN char page1ops[]; EXTERN char page2ops[]; EXTERN char regs[]; #ifdef I80386 EXTERN char typesizes[]; #endif #ifdef DEBUG_HASH unsigned nhash; unsigned nlookup; unsigned nsym; unsigned nx[30]; FORWARD void printchain P((void)); #endif FORWARD void install P((register char *keyptr, int data)); PUBLIC void inst_keywords() { install(regs, REGBIT); #ifdef I80386 install(typesizes, SIZEBIT); #endif install(ops, 0); install(page1ops, PAGE1); install(page2ops, PAGE2); #ifdef I80386 # ifdef MNSIZE install(bytesizeops, PAGE1 | PAGE2); # endif #endif } PRIVATE void install(keyptr, data) register char *keyptr; unsigned char data; { char lowcasebuf[20]; unsigned namelength; char *nameptr; char *namend; register struct sym_s *symptr; while (*keyptr != 0) { namelength = *keyptr++; lineptr = (symname = keyptr) + namelength; for (nameptr = lowcasebuf, namend = lowcasebuf + namelength; nameptr < namend;) { if (*keyptr < 'A' || *keyptr > 'Z') *nameptr++ = *keyptr++; else *nameptr++ = *keyptr++ + ('a' - 'A'); } symptr = lookup(); symptr->type = MNREGBIT; symptr->data = data; symptr->value_reg_or_op.op.routine = *keyptr; symptr->value_reg_or_op.op.opcode = keyptr[1]; lineptr = (symname = lowcasebuf) + namelength; symptr = lookup(); symptr->type = MNREGBIT; symptr->data = data; symptr->value_reg_or_op.op.routine = *keyptr; symptr->value_reg_or_op.op.opcode = keyptr[1]; keyptr += 2; } } /* Lookup() searches symbol table for the string from symname to lineptr - 1. * If string is not found and ifflag is TRUE, string is added to table, with * type = 0 * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM) * Returns pointer to symbol entry (NUL_PTR if not found and not installed) * unless symbol table overflows, when routine aborts. */ PUBLIC struct sym_s *lookup() { struct sym_s **hashptr; register char *nameptr; register struct sym_s *symptr; register unsigned hashval; register unsigned length; #ifdef DEBUG_HASH int tries; ++nlookup; tries = 0; #endif /* Hash function is a weighted xor of 1 to 4 chars in the string. * This works seems to work better than looking at all the chars. * It is important that the function be fast. * The string comparision function should also be fast and it helps * if it is optimized for mostly identical comparisions. * The multiplication by MULTIPLIER should compile as a shift. */ #define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII)) #define USEFUL_BITS_IN_ASCII 6 nameptr = lineptr; length = nameptr - symname; if (length <= 3) { if (length <= 2) hashval = hconv(nameptr[-1]) * MULTIPLIER; else hashval = hconv(nameptr[-2]) * MULTIPLIER, hashval ^= hconv(nameptr[-1]); } else hashval = hconv(symname[length-(length / 2)]) * MULTIPLIER, hashval ^= hconv(nameptr[-2]) << 2, hashval ^= hconv(nameptr[-1]); nameptr = symname; if ((symptr = *(hashptr = spt + (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ)) != NUL_PTR) { do { #ifdef DEBUG_HASH if (tries != 0) --nx[tries]; ++tries; if (tries < sizeof nx / sizeof nx[0]) ++nx[tries]; if (tries >= 5) printchain(hashptr - spt); #endif if ((unsigned char) length != symptr->length) continue; if (memcmp(symptr->name, nameptr, length) == 0) return symptr; } while ((symptr = symptr->next) != NUL_PTR); /* Calculate last non-NUL_PTR hash ptr. * This is faster than keeping hashptr up to date in previous loop * since most lookups are successful and hash ptr is not needed. */ do { symptr = *hashptr; hashptr = &symptr->next; } while (symptr->next != NUL_PTR); } if (!ifflag) return NUL_PTR; #ifdef DEBUG_HASH ++nsym; if (hashptr >= spt && hashptr < spt + SPTSIZ) ++nhash; #endif *hashptr = symptr = asalloc(sizeof(struct sym_s) + length); symptr->type = 0; symptr->data = inidata; symptr->length = length; symptr->value_reg_or_op.value = (offset_t) (symptr->next = NUL_PTR); memcpy(symptr->name, nameptr, length); symptr->name[length] = 0; return symptr; } #ifdef DEBUG_HASH static void printchain(hashval) unsigned hashval; { register struct sym_s *symptr; printf("%04x ", hashval); for (symptr = spt[hashval]; symptr != NUL_PTR; symptr = symptr->next) printf("%s ", symptr->name); printf("\n"); } #endif PUBLIC void statistics() { #ifdef DEBUG_HASH int i; int weight; for (i = 0; i < SPTSIZ; ++i) printchain(i); printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup); weight = 0; for (i = 0; i < 30; ++i) { printf("%5d", nx[i]); weight += nx[i] * i; } printf("\n"); printf("weight = %d%d\n", weight); #endif } dev86-0.16.17/as/const.h0000644000000000000000000001605707316376750014511 0ustar rootroot00000000000000 /* Speed and space hacks for BCC */ #ifdef __AS386_16__ #define LOW_BYTE 0 /* must be changed for big-endian */ #else #define S_ALIGNMENT sizeof(long) #endif /* const.h - constants for assembler */ /* major switches */ /* #define MC6809 */ /* generate 6809 code */ #ifndef MC6809 #define I80386 /* generate 80386 code */ #endif #define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */ #undef SOS_EDOS /* source OS is EDOS */ /* defaults */ #define DIRCHAR '/' /* character separating filename from dir */ #define INBUFSIZE 8192 #define SOS_EOLSTR "\012" /* defaults modified by switches */ #ifdef SOS_EDOS # undef INBUFSIZE # define INBUFSIZE 512 # undef SOS_EOLSTR # define SOS_EOLSTR "\015\012" # define STAKSIZ 256 /* table grows up to stack less this */ #endif #ifdef __AS386_16__ # undef INBUFSIZE # define INBUFSIZE 512 # define STAKSIZ 512 /* table grows up to stack less this */ #endif /* booleans */ #define FALSE 0 #define TRUE 1 /* ASCII constants */ #define ETB 23 /* C tricks */ #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC #define NUL_PTR ((void*)0) /* O/S constants */ #define CREAT_PERMS 0666 #define EOF (-1) #define STDIN 0 #define STDOUT 1 enum { /* Register codes (internal to assembler). */ #ifdef I80386 /* Index regs must be first. */ BPREG, BXREG, DIREG, SIREG, #define MAX16BITINDREG SIREG EAXREG, EBPREG, EBXREG, ECXREG, EDIREG, EDXREG, ESIREG, ESPREG, #define MAXINDREG ESPREG AXREG, CXREG, DXREG, SPREG, AHREG, ALREG, BHREG, BLREG, CHREG, CLREG, DHREG, DLREG, CSREG, DSREG, ESREG, FSREG, GSREG, SSREG, CR0REG, CR2REG, CR3REG, DR0REG, DR1REG, DR2REG, DR3REG, DR6REG, DR7REG, TR3REG, TR4REG, TR5REG, TR6REG, TR7REG, ST0REG, ST1REG, ST2REG, ST3REG, ST4REG, ST5REG, ST6REG, ST7REG, #endif /* I80386 */ #ifdef MC6809 /* Index regs must be first, then PC. */ SREG, UREG, XREG, YREG, #define MAXINDREG YREG PCREG, AREG, BREG, CCREG, DPREG, DREG, #endif /* MC6809 */ NOREG }; #ifdef I80386 enum { /* Type and size keywords. */ BYTEOP, DWORDOP, FWORDOP, FAROP, PTROP, PWORDOP, QWORDOP, TBYTEOP, WORDOP }; #endif /* I80386 */ /* special chars */ #define EOL 0 #define MACROCHAR '?' enum { /* Symbol codes. */ /* The first 2 must be from chars in identifiers. */ IDENT, INTCONST, /* The next few are best for other possibly-multi-char tokens. */ ADDOP, /* also ++ */ BINCONST, CHARCONST, GREATERTHAN, /* also >> and context-sensitive */ HEXCONST, LESSTHAN, /* also << and context-sensitive */ SUBOP, /* also -- */ WHITESPACE, ANDOP, COMMA, EOLSYM, EQOP, IMMEDIATE, INDIRECT, LBRACKET, LPAREN, MACROARG, NOTOP, OROP, OTHERSYM, POSTINCOP, PREDECOP, RBRACKET, RPAREN, SLASH, /* context-sensitive */ SLOP, SROP, STAR, /* context-sensitive */ STRINGCONST, COLON }; /* symbol table entry */ /* type entry contains following flags */ #define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */ #define COMMBIT (1<<1) /* common */ #define LABIT (1<<2) /* label (a PC location or defined by EQU) */ #define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */ #define MACBIT (1<<4) /* macro */ #define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do * with SA_MASK (if with COMMBIT), otherwise * means globl */ #define VARBIT (1<<6) /* variable (i.e. something defined by SET) */ #define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */ /* data entry contains following flags, valid */ /* for expressions as well as syms */ #define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */ #define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */ #define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */ #define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */ #define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */ #define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */ #define FORBIT (1<<5) /* forward referenced */ #define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */ #define UNDBIT (1<<7) /* undefined */ /* object code format (Introl) */ #define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */ #define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */ #define OBJ_ABS 0x40 /* absolute code command */ #define OBJ_OFFSET_REL 0x80 /* offset relocation command */ #define OBJ_SET_SEG 0x20 /* set segment command */ #define OBJ_SKIP_1 0x11 /* skip with 1 byte count */ #define OBJ_SKIP_2 0x12 /* skip with 2 byte count */ #define OBJ_SKIP_4 0x13 /* skip with 4 byte count */ #define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */ #define OBJ_A_MASK 0x10 /* absolute bit(symbols) */ #if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */ oops - RELBIT misplaced #endif #define OBJ_E_MASK 0x80 /* exported bit (symbols) */ #if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */ oops - EXPBIT misplaced #endif #define OBJ_I_MASK 0x40 /* imported bit (symbols) */ #if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */ oops - IMPBIT misplaced #endif #define OBJ_N_MASK 0x01 /* entry bit (symbols) */ #if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */ oops - ENTBIT misplaced #endif #define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */ #define OBJ_SZ_ONE 0x40 /* size one code for symbol value */ #define OBJ_SZ_TWO 0x80 /* size two code for symbol value */ #define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */ #define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */ #define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */ #define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */ #define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */ #define SYMLIS_NAMELEN 26 #define SYMLIS_LEN (sizeof (struct sym_listing_s)) #define FILNAMLEN 64 /* max length of a file name */ #define LINLEN 256 /* max length of input line */ #define LINUM_LEN 5 /* length of formatted line number */ #define SPTSIZ 1024 /* number of symbol ptrs */ /* pseudo-op flags */ #define POPHI 1 /* set to print hi byte of adr */ #define POPLO 2 /* to print lo byte of ADR */ #define POPLC 4 /* to print LC */ #define POPLONG 8 /* to print high word of ADR */ #define MAXBLOCK 8 /* max nesting level of BLOCK stack */ #define MAXGET 8 /* max nesting level of GET stack */ #define MAXIF 8 /* max nesting level of IF stack */ #define MACPSIZ (128 / sizeof (struct schain_s)) /* size of macro param buffer */ #define MAXMAC 8 /* max nesting level of macro stack */ #define NLOC 16 /* number of location counters */ #ifdef I80386 #define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */ #endif /* special segments */ #define BSSLOC 3 #define DATALOC 3 #define DPLOC 2 #define STRLOC 1 #define TEXTLOC 0 #include "errors.h" dev86-0.16.17/as/as.c0000644000000000000000000001652210057671355013751 0ustar rootroot00000000000000/* as.c - assembler */ /* usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw] in any order (but no repeated file options) */ #include "syshead.h" #include "const.h" #include "type.h" #include "byteord.h" #include "macro.h" #undef EXTERN #define EXTERN #include "file.h" #include "flag.h" #include "globvar.h" #include "version.h" PUBLIC char hexdigit[] = "0123456789ABCDEF"; /* XXX - ld uses lower case */ PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */ PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */ PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */ PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */ PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */ PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */ PRIVATE char * binfilename = 0; PRIVATE char * objfilename = 0; PRIVATE int keep_bad_output = 0; FORWARD void initp1 P((void)); FORWARD int my_creat P((char *name, char *message)); FORWARD void process_args P((int argc, char **argv)); FORWARD void summary P((fd_t fd)); FORWARD void summ_number P((unsigned num)); FORWARD void usage P((void)); PUBLIC int main(argc, argv) int argc; char **argv; { init_heap(); initp1(); initp1p2(); inst_keywords(); initbin(); initobj(); initsource(); typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN); as_warn.global = TRUE; /* constant */ as_warn.semaphore = -1; last_pass=1; process_args(argc, argv); initscan(); line_zero(); assemble(); /* doesn't return, maybe use setjmp */ /* NOTREACHED */ return 0; } PUBLIC void as_abort(message) char *message; { write(STDOUT, "as: ", 4); write(STDOUT, message, strlen(message)); write(STDOUT, "\n", 1); exit(1); } PUBLIC void finishup() { bintrailer(); objtrailer(); if (list.global ||symgen) gensym(); /* output to lstfil and/or symfil */ if (list.global ||toterr != 0 || totwarn != 0) summary(lstfil); if (lstfil != STDOUT && (toterr != 0 || totwarn != 0)) summary(STDOUT); statistics(); /* If an output binary is in error remove it */ close(binfil); binfil=0; close(objfil); objfil=0; if (toterr != 0 && !keep_bad_output) { if(binfilename) unlink(binfilename); if(objfilename) unlink(objfilename); } exit(toterr != 0 ? 1 : 0); /* should close output files and check */ } /* initialise constant nonzero values */ PRIVATE void initp1() { #ifdef I80386 idefsize = defsize = 2; /* I think this is probably safer (RDB) */ #endif #if 0 idefsize = defsize = sizeof (char *) > 2 ? 4 : 2; #endif lctabtop = lctab + NLOC; lstfil = STDOUT; mapnum = 15; /* default map number for symbol table */ spt_top = (spt = hid_spt) + SPTSIZ; } /* initialise nonzero values which start same each pass */ PUBLIC void initp1p2() { register struct lc_s *lcp; dirty_pass = 0; ifflag = TRUE; pedata = UNDBIT; /* program entry point not defined */ blockstak = hid_blockstak + MAXBLOCK; ifstak = hid_ifstak + MAXIF; macstak = hid_macstak + MAXMAC; macptop = (macpar = hid_mcpar) + MACPSIZ; lctabtop = (lcptr = lctab = hid_lctab) + NLOC; for (lcp = lctab; lcp < lctabtop; ++lcp) { lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */ lcp->lc = lc = 0; } } PUBLIC void line_zero() { if( textseg >= 0 ) ptext(); } PRIVATE int my_creat(name, message) char *name; char *message; { int fd; #ifdef O_BINARY if ((fd = open(name, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, CREAT_PERMS)) < 0 || fd > 255) #else if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255) #endif as_abort(message); return fd; } PRIVATE void process_args(argc, argv) int argc; char **argv; { char *arg; bool_t isnextarg; char *nextarg = 0; int opened_file = 0; int flag_state; #ifdef I80386 setcpu(0xF); #endif textseg = -1; if (argc <= 1) usage(); do { arg = *++argv; if (arg[0] == '-' && arg[1] != '\0') { flag_state = 1; if (arg[2] == '-' && arg[3] == 0 ) flag_state = 0; else if (arg[2] != 0) usage(); /* no multiple options */ isnextarg = FALSE; if (argc > 2) { nextarg = argv[1]; if (nextarg[0] != 0 && nextarg[0] != '-') isnextarg = TRUE; } switch (arg[1]) { case 'v': outfd = STDOUT; writes("as86 version: "); #ifdef VERSION writesn(VERSION); #else writesn("Unknown!"); #endif exit(1); #ifdef I80386 case '0': case '1': case '2': idefsize = defsize = 0x2; setcpu(arg[1]-'0'); break; case '3': idefsize = defsize = 0x4; setcpu(0xF); break; case 'a': asld_compatible = flag_state; break; #endif case 'b': if (!isnextarg || binfil != 0) usage(); binfil = my_creat(binfilename=nextarg, "error creating binary file"); binaryg = TRUE; --argc; ++argv; break; case 'g': globals_only_in_obj = flag_state; break; #ifdef I80386 case 'j': jumps_long = flag_state; break; case 'O': if( flag_state ) last_pass = 2; else last_pass = 1; break; #endif case 'l': list.global = TRUE; goto get_any_list_file; case 'm': maclist.global = TRUE; get_any_list_file: if (isnextarg) { if (lstfil != STDOUT) usage(); lstfil = my_creat(nextarg, "error creating list file"); --argc; ++argv; } break; case 'n': if (!isnextarg) usage(); truefilename = nextarg; --argc; ++argv; break; case 'o': if (!isnextarg || objfil != 0) usage(); objectg = TRUE; objfil = my_creat(objfilename=nextarg, "error creating object file"); --argc; ++argv; break; case 's': if (!isnextarg || symfil != 0) usage(); symgen = TRUE; symfil = my_creat(nextarg, "error creating symbol file"); --argc; ++argv; break; case 't': if (!isnextarg || binfil != 0) usage(); textseg = atoi(nextarg); if(textseg>0) textseg+=BSSLOC; --argc; ++argv; break; case 'u': if( flag_state ) inidata = IMPBIT | SEGM; else inidata = 0; break; case 'w': if( flag_state ) as_warn.semaphore = -1; else as_warn.semaphore = 0; break; case 'k': keep_bad_output = 1; break; default: usage(); /* bad option */ } } else if (infil != 0) usage(); /* no multiple sources */ else { if (strlen(arg) > FILNAMLEN) as_abort("source file name too long"); infiln = infil0 = 1; infil = open_input(strcpy(filnamptr, arg)); opened_file = 1; } } while (--argc != 1); if( !opened_file ) { infiln = infil0 = 1; infil = open_input(strcpy(filnamptr, "-")); } #ifdef I80386 origcpuid = cpuid; #endif inidata = (~binaryg & inidata) | (RELBIT | UNDBIT); } /* IMPBIT from inidata unless binaryg */ PRIVATE void summary(fd) int fd; { outfd = fd; writenl(); summ_number(toterr); writesn(" errors"); summ_number(totwarn); writesn(" warnings"); } PRIVATE void summ_number(num) unsigned num; { /* format number like line numbers */ char buf[16]; *build_number(num, LINUM_LEN, buf) = 0; writes(buf); } PRIVATE void usage() { as_abort( #ifdef I80386 "usage: as [-03agjuwO] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); #else "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src"); #endif } dev86-0.16.17/as/flag.h0000644000000000000000000000033506252223372014251 0ustar rootroot00000000000000/* flag.h - global structured-flag variables for assembler */ EXTERN struct flags_s list; /* listing on/off */ EXTERN struct flags_s maclist; /* list macros on/off */ EXTERN struct flags_s as_warn; /* warnings on/off */ dev86-0.16.17/as/typeconv.c0000644000000000000000000000664207615574234015223 0ustar rootroot00000000000000 /* * Type conversion routines, these have been rewritten for portability. * * The only requirement is now that the u2_t and u4_t must be big enough. */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" void xxerr P((char *)); void xxerr(x) char * x; { write(2, x, strlen(x)); } #ifdef __AS386_16__ static int no_swap = 1; #endif static int long_off[4] = {0,1,2,3}; static int int_off[2] = {0,1}; PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) bool_pt big_endian; bool_pt long_big_endian; { int i; #ifdef __AS386_16__ no_swap = (!big_endian && !long_big_endian); #endif for(i=0; i<4; i++) long_off[i] = i; for(i=0; i<2; i++) int_off[i] = i; if( long_big_endian ) { i = long_off[0]; long_off[0] = long_off[2]; long_off[2] = i; i = long_off[1]; long_off[1] = long_off[3]; long_off[3] = i; } if( big_endian ) { i = long_off[2]; long_off[2] = long_off[3]; long_off[3] = i; i = long_off[0]; long_off[0] = long_off[1]; long_off[1] = i; i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i; } return 1; } PUBLIC void u2c2(buf, offset) char *buf; u2_pt offset; { #ifdef __AS386_16__ if( no_swap ) { *((unsigned short*)buf) = offset; /* UNALIGNED ACCESS! */ return; } #endif buf[int_off[0]] = offset; buf[int_off[1]] = (offset>>8); } PUBLIC void u4c4(buf, offset) char *buf; u4_t offset; { int i; #ifdef __AS386_16__ if( no_swap ) { *((unsigned long*)buf) = offset; /* UNALIGNED ACCESS! */ return; } #endif for(i=0; i<4; i++) { buf[long_off[i]] = offset; offset >>= 8; } } PUBLIC void u4cn(buf, offset, count) char *buf; u4_t offset; unsigned count; { switch(count) { case 1: buf[0] = (char) offset; return; case 2: u2c2(buf, (u2_pt) offset); return; case 4: u4c4(buf, (u4_t) offset); return; default: xxerr("WARNING: typeconv.c(u4cn) illegal count\n"); return; } } PUBLIC void u2cn(buf, offset, count) char *buf; u2_pt offset; unsigned count; { switch(count) { case 1: buf[0] = (char) offset; return; case 2: u2c2(buf, (u2_pt) offset); return; case 4: u4c4(buf, (u4_t) offset); return; default: xxerr("WARNING: typeconv.c(u2cn) illegal count\n"); return; } } PUBLIC u2_pt c2u2(buf) char *buf; { u2_pt res; #ifdef __AS386_16__ if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */ #endif res = ((unsigned char *)buf) [int_off[0]] + ((((unsigned char *)buf) [int_off[1]]) << 8); return res; } PUBLIC u4_t c4u4(buf) char *buf; { u4_t res; int i; #ifdef __AS386_16__ if( no_swap ) return *((u4_t *)buf); /* UNALIGNED ACCESS! */ #endif res = 0; for(i=3; i>=0; i--) { res = (res<<8) + ((unsigned char *)buf) [long_off[i]]; } return res; } PUBLIC u4_t cnu4(buf, count) char *buf; unsigned count; { switch (count) { case 0: return 0; case 1: return buf[0] & 0xFF; case 2: return c2u2(buf); case 4: return c4u4(buf); default: xxerr("WARNING: typeconv.c(cnu4) illegal count\n"); return 0; } } PUBLIC u2_pt cnu2(buf, count) char *buf; unsigned count; { switch (count) { case 0: return 0; case 1: return buf[0] & 0xFF; case 2: return c2u2(buf); case 4: return (u2_pt) c4u4(buf); default: xxerr("WARNING: typeconv.c(cnu2) illegal count\n"); return 0; } } dev86-0.16.17/as/gensym.c0000644000000000000000000001433707315166436014654 0ustar rootroot00000000000000/* gensym.c - generate symbol table for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "flag.h" #include "file.h" #include "globvar.h" FORWARD int printsym P((register struct sym_s *symptr, unsigned column)); FORWARD void sort P((struct sym_s **array, struct sym_s **top, bool_pt nameflag)); /* sort labels in symbol table on name and value */ /* if listing, write human-readable table to list file */ /* if symbol file, write machine-readable tables to it */ /* pointers become relative to start of file */ PUBLIC void gensym() { unsigned column; struct sym_s **copyptr; struct sym_s **copytop; register struct sym_s **hashptr; unsigned label_count; /* number of labels */ unsigned labels_length; /* length of all label strings */ struct sym_s **symlptr; /* start of symbol output list */ register struct sym_s *symptr; #ifdef BINSYM unsigned label_stringptr; /* offset of label str from start of file */ #endif int symcount = 0; labels_length = label_count = 0; /* make copy of all relavant symbol ptrs on heap */ /* original ptrs can now be modified, but need to be an array for sort */ for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) symcount++; while ((symptr = symptr->next) != NUL_PTR); symlptr = copyptr = asalloc( sizeof(struct sym_s *) * symcount); for (hashptr = spt; hashptr < spt_top;) if ((symptr = *hashptr++) != NUL_PTR) do if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT))) { *copyptr++ = symptr; ++label_count; labels_length += symptr->length + 3; /* 3 for type, value */ } while ((symptr = symptr->next) != NUL_PTR); sort(symlptr, copyptr, TRUE); /* sort on name */ copytop = copyptr; if (list.global) { outfd = lstfil; writenl(); writesn("Symbols:"); for (copyptr = symlptr, column = 0; copyptr < copytop;) column = printsym(*copyptr++, column); if (column != 0) writenl(); } if ((outfd = symfil) != 0) { #ifndef BINSYM for (copyptr = symlptr; copyptr < copytop;) /* for (copyptr = spt; copyptr < spt_top;) */ { int sft; if((symptr = *copyptr++) == NUL_PTR ) continue; if( globals_only_in_obj && !(symptr->type & EXPBIT)) continue; writec(hexdigit[symptr->data & SEGM]); writec(' '); for(sft=SIZEOF_OFFSET_T*8-4; sft >= 0; sft-=4) writec(hexdigit[(symptr->value_reg_or_op.value>>sft) & 0xF]); writec(' '); writec(symptr->type & EXPBIT ? 'E' : '-'); writec(symptr->type & ENTBIT ? 'N' : '-'); writec(symptr->data & IMPBIT ? 'I' : '-'); writec(symptr->data & RELBIT ? 'R' : 'A'); writec(symptr->type & COMMBIT ? 'C' : '-'); writec(' '); write(outfd, symptr->name, (unsigned) (symptr->length)); /* printsym(*copyptr++, 0); */ writenl(); } #else writew(mapnum); label_count *= 2; /* now length of ptr table (2 bytes per ptr) */ label_stringptr = label_count + 6; /* offset to current string in symbol file */ /* 6 is length of header */ labels_length += label_stringptr; /* offset to ptr table sorted on value */ writew(labels_length + label_count); /* total length of symbol file */ writew(label_count); for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) (symptr->next = (struct sym_s *) label_stringptr)); /* reuse "next" to record string position */ label_stringptr += symptr->length + 3; } for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) symptr->value_reg_or_op.value); writec(symptr->type); write(outfd, symptr->name, (unsigned) (symptr->length - 1)); writec(symptr->name[symptr->length - 1] | 0x80); } sort(symlptr, copyptr, FALSE); /* sort on value */ for (copyptr = symlptr; copyptr < copytop;) { symptr = *copyptr++; writew((unsigned) symptr->next); /* now has string position */ } #endif } } /* print symbol nicely formatted for given column */ PRIVATE int printsym(symptr, column) register struct sym_s *symptr; unsigned column; { unsigned char length; register struct sym_listing_s *listptr; char *outname; char *symname; listptr = (struct sym_listing_s *) temp_buf(); memset((char *) listptr, ' ', SYMLIS_LEN); listptr->nullterm = 0; if ((length = symptr->length) > SYMLIS_NAMELEN) { outname = listptr->name; outname[length = SYMLIS_NAMELEN] = '+'; } else outname = listptr->name; /*(listptr->name + SYMLIS_NAMELEN) - length;*/ symname = symptr->name; do *outname++ = *symname++; while (--length != 0); listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A'; listptr->segm[0] = hexdigit[symptr->data & SEGM]; if (symptr->type & COMMBIT) listptr->cein[0] = 'C'; else if (symptr->type & ENTBIT) listptr->cein[0] = 'N'; else if (symptr->type & EXPBIT) listptr->cein[0] = 'E'; else if (symptr->data & IMPBIT) listptr->cein[0] = 'I'; #if SIZEOF_OFFSET_T > 2 build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16), listptr->value); #endif build_2hex_number((unsigned) symptr->value_reg_or_op.value, listptr->value); writes((char *) listptr); if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN)) { writenl(); column = 0; } return column; } /* shell sort symbols */ PRIVATE void sort(array, top, nameflag) struct sym_s **array; struct sym_s **top; bool_pt nameflag; { int gap; int i; int j; register struct sym_s **left; register struct sym_s **right; int size; struct sym_s *swap; size = top - array; /* choose gaps according to Knuth V3 p95 */ for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j) ; do { for (j = gap; j < size; ++j) for (i = j - gap; i >= 0; i -= gap) { left = &array[i]; right = &array[i + gap]; if ((bool_t) nameflag) { if (strcmp((*left)->name, (*right)->name) <= 0) break; } else if ((unsigned) (*left)->value_reg_or_op.value <= (*right)->value_reg_or_op.value) break; swap = *left; *left = *right; *right = swap; } } while ((gap /= 3) != 0); } dev86-0.16.17/as/macro.c0000644000000000000000000000762307315210006014432 0ustar rootroot00000000000000/* macro.c - expand macros for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "scan.h" #undef EXTERN #define EXTERN #include "macro.h" /* Enter macro: stack macro and get its parameters. Parameters form a linked list of null-terminated strings of form next:string. The first string is the macro number in 4 bytes. */ PUBLIC void entermac(symptr) struct sym_s *symptr; { if (maclevel >= MAXMAC) error(MACOV); else if (macpar + 2 > macptop) error(PAROV); /* no room for 0th param */ /* (2 structs to fit it!) */ else { char ch; struct schain_s *param1; register char *reglineptr; register char *stringptr; ++maclevel; (--macstak)->text = (char *) symptr->value_reg_or_op.value; macstak->parameters = param1 = macpar; param1->next = NUL_PTR; *(stringptr = build_number(++macnum, 3, param1->string)) = 0; macpar = (struct schain_s *) (stringptr + 1); /* TODO: alignment */ getsym(); if (sym == EOLSYM) return; /* no other params */ if (sym != LPAREN) reglineptr = symname; else reglineptr = lineptr; stringptr = macpar->string; while (TRUE) { if (stringptr >= (char *) macptop) { symname = reglineptr; error(PAROV); return; } ch = *reglineptr++; if (ch == '\\') /* escaped means no special meaning for slash, comma, paren */ ch = *reglineptr++; else if (ch == ',' || ch == ')' || ch == '!' || ch == ';' || ch == '\n' || ch == 0) { if (stringptr >= (char *) macptop) { symname = reglineptr; error(PAROV); /* no room for null */ return; } *stringptr = 0; param1->next = macpar; /* ptr from previous */ (param1 = macpar)->next = NUL_PTR; /* this goes nowhere */ macpar = (struct schain_s *) (stringptr + 1); /* but is finished OK - TODO align */ stringptr = macpar->string; if (ch != ',') return; continue; } if ((*stringptr++ = ch) == 0) { symname = reglineptr; error(RPEXP); return; } } } } /* MACRO pseudo-op */ PUBLIC void pmacro() { bool_t saving; bool_t savingc; struct sym_s *symptr=0; int maclen = 8; int macoff = 0; char * macbuf = asalloc(8); saving = /* prepare for bad macro */ savingc = FALSE; /* normally don't save comments */ macload = TRUE; /* show loading */ if (label != NUL_PTR) error(ILLAB); else if (sym != IDENT) error(LABEXP); else { symptr = gsymptr; if (symptr->type & MNREGBIT) error(LABEXP); else if (symptr->type & LABIT || symptr->data & FORBIT) error(RELAB); else if (pass != last_pass || symptr->type & REDBIT) /* copy on pass 0, also pass 1 if redefined */ { saving = TRUE; if (symptr->type & MACBIT) symptr->type |= REDBIT; else symptr->type |= MACBIT; symptr->data = UNDBIT; /* undefined till end */ symptr->value_reg_or_op.value = (offset_t) macbuf; getsym_nolookup(); /* test for "C" */ if (sym == IDENT && lineptr == symname + 1 && *symname == 'C') savingc = TRUE; } } while (TRUE) { skipline(); listline(); readline(); if (!macload) break; /* macload cleared to show eof */ getsym_nolookup(); if (sym == IDENT) { if (lineptr == symname + 4 && ( strncmp(symname, "MEND", 4) == 0 || strncmp(symname, "mend", 4) == 0) ) { getsym(); break; } } else if (sym != MACROARG) { if (!savingc) continue; /* don't save comment */ } if (!saving) continue; { char * p = strchr(linebuf, EOLCHAR); int len = (p-linebuf+1); if ( macoff + len > maclen-4 ) { maclen = maclen * 2 + len; macbuf = asrealloc(macbuf, maclen); } memcpy(macbuf+macoff, linebuf, len); macoff += len; } } macload = FALSE; if (saving) { macbuf[macoff] = ETB; symptr->value_reg_or_op.value = (offset_t) macbuf; symptr->data = 0; } } dev86-0.16.17/as/mops.c0000644000000000000000000015567407315312504014327 0ustar rootroot00000000000000/* mops.c - handle pseudo-ops */ #include "syshead.h" #include "const.h" #include "type.h" #include "globvar.h" #include "opcode.h" #include "scan.h" #undef EXTERN #define EXTERN #include "address.h" #define is8bitadr(offset) ((offset_t) offset < 0x100) #define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100) #define pass2 (pass==last_pass) FORWARD void mshort2 P((void)); FORWARD reg_pt regchk P((void)); FORWARD void reldata P((void)); FORWARD void segadj P((void)); #ifdef I80386 #define iswordadr(offset) ((offset_t) (offset) < 0x10000L) #define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L) #define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL) #define BYTE_SEGWORD 0x00 #define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG) #define BASE_MASK 0x07 #define BASE_SHIFT 0 #define INDEX_MASK 0x38 #define INDEX_SHIFT 3 #define MOD_MASK 0xC0 # define REG_MOD 0xC0 # define MEM0_MOD 0x00 # define MEM1_MOD 0x40 # define MEM2_MOD 0x80 #define REG_MASK 0x38 #define REG_SHIFT 3 #define RM_MASK 0x07 #define RM_SHIFT 0 # define D16_RM 0x06 # define D32_RM 0x05 # define SIB_NOBASE 0x05 # define SIB_RM 0x04 #define SREG_MASK 0x38 #define SREG_SHIFT 3 #define SS_MASK 0xC0 #define SS_SHIFT 6 #define SEGMOV 0x04 #define SIGNBIT 0x02 #define TOREGBIT 0x02 #define WORDBIT 0x01 PRIVATE opcode_t baseind16[] = { 0x00, /* BP + BP, illegal */ 0x00, /* BX + BP, illegal */ 0x03, /* DI + BP */ 0x02, /* SI + BP */ 0x00, /* BP + BX, illegal */ 0x00, /* BX + BX, illegal */ 0x01, /* DI + BX */ 0x00, /* SI + BX */ 0x03, /* BP + DI */ 0x01, /* BX + DI */ 0x00, /* DI + DI, illegal */ 0x00, /* SI + DI, illegal */ 0x02, /* BP + SI */ 0x00, /* BX + SI */ 0x00, /* DI + SI, illegal */ 0x00, /* SI + SI, illegal */ }; PRIVATE opcode_t regbits[] = { 0x05 << REG_SHIFT, /* BP */ 0x03 << REG_SHIFT, /* BX */ 0x07 << REG_SHIFT, /* DI */ 0x06 << REG_SHIFT, /* SI */ 0x00 << REG_SHIFT, /* EAX */ 0x05 << REG_SHIFT, /* EBP */ 0x03 << REG_SHIFT, /* EBX */ 0x01 << REG_SHIFT, /* ECX */ 0x07 << REG_SHIFT, /* EDI */ 0x02 << REG_SHIFT, /* EDX */ 0x06 << REG_SHIFT, /* ESI */ 0x04 << REG_SHIFT, /* ESP */ 0x00 << REG_SHIFT, /* AX */ 0x01 << REG_SHIFT, /* CX */ 0x02 << REG_SHIFT, /* DX */ 0x04 << REG_SHIFT, /* SP */ 0x04 << REG_SHIFT, /* AH */ 0x00 << REG_SHIFT, /* AL */ 0x07 << REG_SHIFT, /* BH */ 0x03 << REG_SHIFT, /* BL */ 0x05 << REG_SHIFT, /* CH */ 0x01 << REG_SHIFT, /* CL */ 0x06 << REG_SHIFT, /* DH */ 0x02 << REG_SHIFT, /* DL */ 0x01 << REG_SHIFT, /* CS */ 0x03 << REG_SHIFT, /* DS */ 0x00 << REG_SHIFT, /* ES */ 0x04 << REG_SHIFT, /* FS */ 0x05 << REG_SHIFT, /* GS */ 0x02 << REG_SHIFT, /* SS */ 0x00 << REG_SHIFT, /* CR0 */ 0x02 << REG_SHIFT, /* CR2 */ 0x03 << REG_SHIFT, /* CR3 */ 0x00 << REG_SHIFT, /* DR0 */ 0x01 << REG_SHIFT, /* DR1 */ 0x02 << REG_SHIFT, /* DR2 */ 0x03 << REG_SHIFT, /* DR3 */ 0x06 << REG_SHIFT, /* DR6 */ 0x07 << REG_SHIFT, /* DR7 */ 0x03 << REG_SHIFT, /* TR3 */ 0x04 << REG_SHIFT, /* TR4 */ 0x05 << REG_SHIFT, /* TR5 */ 0x06 << REG_SHIFT, /* TR6 */ 0x07 << REG_SHIFT, /* TR7 */ 0x00 << REG_SHIFT, /* ST(0) */ 0x01 << REG_SHIFT, /* ST(1) */ 0x02 << REG_SHIFT, /* ST(2) */ 0x03 << REG_SHIFT, /* ST(3) */ 0x04 << REG_SHIFT, /* ST(4) */ 0x05 << REG_SHIFT, /* ST(5) */ 0x06 << REG_SHIFT, /* ST(6) */ 0x07 << REG_SHIFT, /* ST(7) */ }; PRIVATE opsize_t regsize[] = { 2, /* BP */ 2, /* BX */ 2, /* DI */ 2, /* SI */ 4, /* EAX */ 4, /* EBP */ 4, /* EBX */ 4, /* ECX */ 4, /* EDI */ 4, /* EDX */ 4, /* ESI */ 4, /* ESP */ 2, /* AX */ 2, /* CX */ 2, /* DX */ 2, /* SP */ 1, /* AH */ 1, /* AL */ 1, /* BH */ 1, /* BL */ 1, /* CH */ 1, /* CL */ 1, /* DH */ 1, /* DL */ 2, /* CS */ 2, /* DS */ 2, /* ES */ 2, /* FS */ 2, /* GS */ 2, /* SS */ 4, /* CR0 */ 4, /* CR2 */ 4, /* CR3 */ 4, /* DR0 */ 4, /* DR1 */ 4, /* DR2 */ 4, /* DR3 */ 4, /* DR6 */ 4, /* DR7 */ 4, /* TR3 */ 4, /* TR4 */ 4, /* TR5 */ 4, /* TR6 */ 4, /* TR7 */ 10, /* ST(0) */ 10, /* ST(1) */ 10, /* ST(2) */ 10, /* ST(3) */ 10, /* ST(4) */ 10, /* ST(5) */ 10, /* ST(6) */ 10, /* ST(7) */ 0, /* NOREG */ }; PRIVATE opcode_t regsegword[] = { WORDBIT, /* BP */ WORDBIT, /* BX */ WORDBIT, /* DI */ WORDBIT, /* SI */ WORDBIT, /* EAX */ WORDBIT, /* EBP */ WORDBIT, /* EBX */ WORDBIT, /* ECX */ WORDBIT, /* EDI */ WORDBIT, /* EDX */ WORDBIT, /* ESI */ WORDBIT, /* ESP */ WORDBIT, /* AX */ WORDBIT, /* CX */ WORDBIT, /* DX */ WORDBIT, /* SP */ BYTE_SEGWORD, /* AH */ BYTE_SEGWORD, /* AL */ BYTE_SEGWORD, /* BH */ BYTE_SEGWORD, /* BL */ BYTE_SEGWORD, /* CH */ BYTE_SEGWORD, /* CL */ BYTE_SEGWORD, /* DH */ BYTE_SEGWORD, /* DL */ SEGMOV, /* CS */ SEGMOV, /* DS */ SEGMOV, /* ES */ SEGMOV, /* FS */ SEGMOV, /* GS */ SEGMOV, /* SS */ 0x20, /* CR0 */ 0x20, /* CR2 */ 0x20, /* CR3 */ 0x21, /* DR0 */ 0x21, /* DR1 */ 0x21, /* DR2 */ 0x21, /* DR3 */ 0x21, /* DR6 */ 0x21, /* DR7 */ 0x24, /* TR3 */ 0x24, /* TR4 */ 0x24, /* TR5 */ 0x24, /* TR6 */ 0x24, /* TR7 */ 0x00, /* ST(0) */ 0x00, /* ST(1) */ 0x00, /* ST(2) */ 0x00, /* ST(3) */ 0x00, /* ST(4) */ 0x00, /* ST(5) */ 0x00, /* ST(6) */ 0x00, /* ST(7) */ 0x00, /* NOREG */ }; PRIVATE opcode_t rm[] = { 0x05, /* BP */ 0x03, /* BX */ 0x07, /* DI */ 0x06, /* SI */ 0x00, /* EAX */ 0x05, /* EBP */ 0x03, /* EBX */ 0x01, /* ECX */ 0x07, /* EDI */ 0x02, /* EDX */ 0x06, /* ESI */ 0x04, /* ESP */ 0x00, /* AX */ 0x01, /* CX */ 0x02, /* DX */ 0x04, /* SP */ 0x04, /* AH */ 0x00, /* AL */ 0x07, /* BH */ 0x03, /* BL */ 0x05, /* CH */ 0x01, /* CL */ 0x06, /* DH */ 0x02, /* DL */ 0x01, /* CS */ 0x03, /* DS */ 0x00, /* ES */ 0x04, /* FS */ 0x05, /* GS */ 0x02, /* SS */ 0x00, /* CR0 */ 0x00, /* CR2 */ 0x00, /* CR3 */ 0x00, /* DR0 */ 0x00, /* DR1 */ 0x00, /* DR2 */ 0x00, /* DR3 */ 0x00, /* DR6 */ 0x00, /* DR7 */ 0x00, /* TR3 */ 0x00, /* TR4 */ 0x00, /* TR5 */ 0x00, /* TR6 */ 0x00, /* TR7 */ 0x00, /* ST(0) */ 0x00, /* ST(1) */ 0x00, /* ST(2) */ 0x00, /* ST(3) */ 0x00, /* ST(4) */ 0x00, /* ST(5) */ 0x00, /* ST(6) */ 0x00, /* ST(7) */ 0x04, /* null index reg for sib only */ }; PRIVATE opcode_t rmfunny[] = { 0x06, /* BP */ 0x07, /* BX */ 0x05, /* DI */ 0x04, /* SI */ }; PRIVATE opcode_t segoverride[] = { 0x2E, /* CS */ 0x3E, /* DS */ 0x26, /* ES */ 0x64, /* FS */ 0x65, /* GS */ 0x36, /* SS */ }; PRIVATE opcode_t ss[] = /* scale to ss bits */ { 0x00, /* x0, illegal */ 0x00 << SS_SHIFT, /* x1 */ 0x01 << SS_SHIFT, /* x2 */ 0x00, /* x3, illegal */ 0x02 << SS_SHIFT, /* x4 */ 0x00, /* x5, illegal */ 0x00, /* x6, illegal */ 0x00, /* x7, illegal */ 0x03 << SS_SHIFT, /* x8 */ }; PRIVATE unsigned char calljmp_kludge; PRIVATE opcode_t direction; PRIVATE bool_t fpreg_allowed; PRIVATE opcode_t segword; /* Values of segword: BYTE_SEGWORD for byte ea's. SEGMOV for segment registers opcode for special registers WORDBIT for other word and dword ea's */ PRIVATE struct ea_s source; PRIVATE struct ea_s source2; PRIVATE struct ea_s target; FORWARD void Eb P((struct ea_s *eap)); FORWARD void Ew P((struct ea_s *eap)); FORWARD void Ev P((struct ea_s *eap)); FORWARD void Ex P((struct ea_s *eap)); FORWARD void Gd P((struct ea_s *eap)); FORWARD void Gw P((struct ea_s *eap)); FORWARD void Gv P((struct ea_s *eap)); FORWARD void Gx P((struct ea_s *eap)); FORWARD void buildea P((struct ea_s *eap)); FORWARD void buildfloat P((void)); FORWARD void buildfreg P((void)); FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag)); FORWARD void buildregular P((void)); FORWARD void buildsegword P((struct ea_s *eap)); FORWARD void buildunary P((opcode_pt opc)); FORWARD opsize_pt displsize P((struct ea_s *eap)); FORWARD reg_pt fpregchk P((void)); FORWARD bool_pt getaccumreg P((struct ea_s *eap)); FORWARD void getbinary P((void)); FORWARD bool_pt getdxreg P((struct ea_s *eap)); FORWARD void getea P((struct ea_s *eap)); FORWARD void getimmed P((struct ea_s *eap, count_t immed_count)); FORWARD void getindirect P((struct ea_s *eap)); FORWARD void getshift P((struct ea_s *eap)); FORWARD reg_pt indregchk P((reg_pt matchreg)); FORWARD void kgerror P((char * err_str)); FORWARD void lbranch P((int backamount)); FORWARD void notbytesize P((struct ea_s *eap)); FORWARD void notimmed P((struct ea_s *eap)); FORWARD void notindirect P((struct ea_s *eap)); FORWARD void notsegorspecreg P((struct ea_s *eap)); FORWARD void yesimmed P((struct ea_s *eap)); FORWARD void yes_samesize P((void)); PRIVATE void Eb(eap) register struct ea_s *eap; { Ex(eap); if (eap->size != 0x1) { #ifndef NODEFAULTSIZE if (eap->size == 0x0) eap->size = 0x1; else #endif kgerror(ILL_SIZE); } } PRIVATE void Ew(eap) register struct ea_s *eap; { Ex(eap); if (eap->size != 0x2) { #ifndef NODEFAULTSIZE if (eap->size == 0x0) eap->size = 0x2; else #endif kgerror(ILL_SIZE); } } PRIVATE void Ev(eap) register struct ea_s *eap; { Ex(eap); notbytesize(eap); } PRIVATE void Ex(eap) register struct ea_s *eap; { getea(eap); notimmed(eap); notsegorspecreg(eap); } PRIVATE void Gd(eap) register struct ea_s *eap; { Gx(eap); if (eap->size != 0x4) kgerror(ILL_SIZE); } PRIVATE void Gw(eap) register struct ea_s *eap; { Gx(eap); if (eap->size != 0x2) kgerror(ILL_SIZE); } PRIVATE void Gv(eap) register struct ea_s *eap; { Gx(eap); notbytesize(eap); } PRIVATE void Gx(eap) register struct ea_s *eap; { Ex(eap); notindirect(eap); } PRIVATE void buildea(eap) register struct ea_s *eap; { opsize_t asize; ++mcount; lastexp = eap->displ; if (eap->indcount == 0x0) postb = REG_MOD | rm[eap->base]; else { if (eap->base == NOREG) { if (eap->index == NOREG) { if ((asize = displsize(eap)) > 0x2) postb = D32_RM; else postb = D16_RM; } else { asize = 0x4; postb = SIB_NOBASE; /* for sib later */ } } else { if (eap->base > MAX16BITINDREG) { asize = 0x4; postb = rm[eap->base]; } else { asize = 0x2; if (!(lastexp.data & UNDBIT) && !iswordorswordoffset(lastexp.offset)) error(ABOUNDS); if (eap->index == NOREG) postb = rmfunny[eap->base]; else if (eap->base <= MAX16BITINDREG) postb = baseind16[eap->base + 0x4 * eap->index]; } } needcpu(asize==4?3:0); if (asize != defsize) aprefix = 0x67; if (eap->base == NOREG) mcount += asize; else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) || !is8bitsignedoffset(lastexp.offset)) { postb |= MEM2_MOD; mcount += asize; } else if (lastexp.offset != 0x0 || (eap->base == BPREG && eap->index == NOREG) || eap->base == EBPREG) { postb |= MEM1_MOD; ++mcount; } if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG)) { sib = ss[eap->scale] | (rm[eap->index] << INDEX_SHIFT) | (postb & RM_MASK); postb = (postb & MOD_MASK) | SIB_RM; ++mcount; } } } PRIVATE void buildfloat() { if (mcount != 0x0) { buildea(&source); oprefix = 0x0; postb |= (opcode & 0x07) << REG_SHIFT; opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); } } PRIVATE void buildfreg() { mcount += 0x2; oprefix = 0x0; postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG); opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4); } PRIVATE void buildimm(eap, signflag) register struct ea_s *eap; bool_pt signflag; { immadr = eap->displ; immcount = eap->size; if (!(immadr.data & (FORBIT | RELBIT | UNDBIT))) { if (immcount == 0x1) { if ((offset_t) (immadr.offset + 0x80) >= 0x180) datatoobig(); } else if (signflag && is8bitsignedoffset(immadr.offset)) { opcode |= SIGNBIT; immcount = 0x1; } else if (immcount == 0x2) { if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L) datatoobig(); } } } PRIVATE void buildregular() { if (mcount != 0x0) { buildea(&target); postb |= regbits[source.base]; } } /* Check size and build segword. */ PRIVATE void buildsegword(eap) register struct ea_s *eap; { if (eap->size == 0x0) #ifdef NODEFAULTSIZE kgerror(SIZE_UNK); #else eap->size = defsize; #endif if (eap->indcount != 0x0 || eap->base == NOREG) { segword = WORDBIT; if (eap->size == 0x1) segword = BYTE_SEGWORD; } else segword = regsegword[eap->base]; } PRIVATE void buildunary(opc) opcode_pt opc; { if (mcount != 0x0) { buildea(&target); postb |= opcode; opcode = opc; } } PRIVATE opsize_pt displsize(eap) register struct ea_s *eap; { opsize_t asize; asize = defsize; if (!(eap->displ.data & UNDBIT)) { if (asize > 0x2) { if (!(eap->displ.data & (FORBIT | RELBIT)) && iswordadr(eap->displ.offset)) asize = 0x2; } else if (!iswordorswordoffset(eap->displ.offset)) /* should really use iswordadr() */ /* but compiler generates signed offsets */ { if (!(eap->displ.data & (FORBIT | RELBIT))) asize = 0x4; else if (pass2) error(ABOUNDS); } } return asize; } PRIVATE reg_pt fpregchk() { reg_pt fpreg; fpreg_allowed = TRUE; fpreg = regchk(); fpreg_allowed = FALSE; if (fpreg != ST0REG) return NOREG; getsym(); if (sym == LPAREN) { getsym(); if (sym != INTCONST || (unsigned) number >= 0x8) error(ILL_FP_REG); else { fpreg += number; getsym(); if (sym != RPAREN) error(RPEXP); else getsym(); } } return fpreg; } PRIVATE bool_pt getaccumreg(eap) register struct ea_s *eap; { if ((eap->base = regchk()) != AXREG && eap->base != ALREG && eap->base != EAXREG) return FALSE; getsym(); if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) oprefix = 0x66; return TRUE; } /* Get binary ea's in target & source (flipped if direction is set). Put size in source if not already. Initialise direction, segword, bump mcount. */ PRIVATE void getbinary() { ++mcount; getea(&target); if (target.indcount == 0x0 && target.base == NOREG) { error(ILL_IMM_MODE); target.base = AXREG; target.size = defsize; } getcomma(); getea(&source); if (source.size == 0x0) source.size = target.size; else if (target.size != 0x0 && target.size != source.size) { kgerror(MISMATCHED_SIZE); return; } if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV) direction = 0x0; else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV) { struct ea_s swap; direction = TOREGBIT; swap = source; source = target; target = swap; } else if (target.indcount != 0x0) { kgerror(ILL_IND_TO_IND); return; } else { kgerror(ILL_SEG_REG); return; } buildsegword(&source); } PRIVATE bool_pt getdxreg(eap) register struct ea_s *eap; { if ((eap->base = regchk()) != DXREG) return FALSE; getsym(); return TRUE; } /* parse effective address */ /* Syntax is restrictive in that displacements must be in the right spots and will not be added up. optional size-type prefix, which is BYTE BYTE PTR WORD WORD PTR DWORD DWORD PTR PTR reg segreg [scaled index] where scaled index = indreg indreg*scale indreg+indreg indreg+indreg*scale [scaled index+displ] [scaled index-displ] optional-immediate-prefix displ[scaled index] [displ] optional-imediate-prefix displ (scaled index) -- anachronism optional-imediate-prefix displ(scaled index) -- anachronism */ PRIVATE void getea(eap) register struct ea_s *eap; { bool_t leading_displ; bool_t leading_immed; register struct sym_s *symptr; leading_immed = leading_displ = lastexp.data = eap->indcount = lastexp.offset = 0x0; eap->index = eap->base = NOREG; eap->scale = 0x1; eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */ if (sym == IDENT) { if ((symptr = gsymptr)->type & MNREGBIT) { if (symptr->data & SIZEBIT) { getsym(); if (symptr->value_reg_or_op.op.opcode == 0x0) eap->indcount = 0x2 - calljmp_kludge; else { if (eap->size != 0x0) { if (eap->size != symptr->value_reg_or_op.op.opcode) error(MISMATCHED_SIZE); } else eap->size = symptr->value_reg_or_op.op.opcode; if (eap->size > 0x1 && eap->size != defsize) oprefix = 0x66; if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && symptr->data & SIZEBIT && symptr->value_reg_or_op.op.routine == PTROP) { getsym(); eap->indcount = 0x2 - calljmp_kludge; } } } } if( last_pass == 1 ) if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT))) symptr->data |= FORBIT; /* show seen in advance */ } if ((eap->base = regchk()) != NOREG) { getsym(); if (eap->indcount != 0x0) { error(ILL_IND_PTR); eap->indcount = 0x0; } if (eap->size != 0x0 && eap->size != regsize[eap->base]) error(MISMATCHED_SIZE); if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize) oprefix = 0x66; eap->displ = lastexp; needcpu(eap->size==4?3:0); return; } if (sym != lindirect) { if (sym == IMMEDIATE || sym == STAR) { /* context-sensitive, STAR means signed immediate here */ leading_immed = TRUE; getsym(); } leading_displ = TRUE; expres(); eap->displ = lastexp; } if (sym == lindirect) { getsym(); eap->indcount = 0x2 - calljmp_kludge; if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG) { if (eap->indcount == 0x0 && leading_displ) error(IND_REQ); getsym(); if (sym == ADDOP) { getsym(); if ((eap->index = indregchk(eap->base)) != NOREG) getsym(); else { if (eap->indcount == 0x0) error(IND_REQ); if (leading_displ) error(REPEATED_DISPL); expres(); /* this eats ADDOP, SUBOP, MULOP */ } } if (sym == STAR) { needcpu(3); /* context-sensitive, STAR means scaled here*/ if (eap->index == NOREG && eap->base == ESPREG) { error(INDEX_REG_EXP); eap->base = EAXREG; } getsym(); factor(); chkabs(); if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1) { if (eap->base <= MAX16BITINDREG || (lastexp.offset != 0x2 && lastexp.offset != 0x4 && lastexp.offset != 0x8)) error(ILL_SCALE); else { eap->scale = lastexp.offset; if (eap->index == NOREG) { eap->index = eap->base; eap->base = NOREG; } } } lastexp.data = lastexp.offset = 0x0; } if ((sym == ADDOP || sym == SUBOP)) { if (eap->indcount == 0x0) error(IND_REQ); if (leading_displ) error(REPEATED_DISPL); expres(); } } else { if (leading_displ) error(REPEATED_DISPL); expres(); } if (sym != rindirect) error(rindexp); else getsym(); } /* RDB */ else if (!leading_immed && defsize <= 0x2) eap->indcount = 0x1; /* compatibility kludge */ if (!leading_displ) eap->displ = lastexp; needcpu(eap->size==4?3:0); } PRIVATE void getimmed(eap, immed_count) struct ea_s *eap; count_t immed_count; { getea(eap); yesimmed(eap); if (mcount != 0x0) { eap->size = immed_count; buildimm(eap, FALSE); } } PRIVATE void getindirect(eap) register struct ea_s *eap; { getea(eap); if (eap->indcount == 0x0) kgerror(IND_REQ); } PRIVATE void getshift(eap) register struct ea_s *eap; { getcomma(); getea(eap); if (eap->base != CLREG) yesimmed(eap); } /* Check if current symbol is a compatible index register. Generate error if it is a reg but not a compatible index. Return register number (adjusted if necessary to a legal index) or NOREG. */ PRIVATE reg_pt indregchk(matchreg) reg_pt matchreg; { reg_pt reg; if ((reg = regchk()) != NOREG) { switch (matchreg) { case BPREG: case BXREG: if (reg != DIREG && reg != SIREG) { reg = SIREG; error(INDEX_REG_EXP); } break; case DIREG: case SIREG: if (reg != BPREG && reg != BXREG) { reg = BXREG; error(INDEX_REG_EXP); } break; case NOREG: break; default: if (reg <= MAX16BITINDREG || reg == ESPREG) { reg = EAXREG; error(INDEX_REG_EXP); } break; } if (reg > MAXINDREG && calljmp_kludge == 0x0) { if (matchreg != NOREG) reg = EAXREG; else reg = BXREG; error(INDEX_REG_EXP); } } return reg; } PRIVATE void kgerror(err_str) char * err_str; { error(err_str); sprefix = oprefix = aprefix = mcount = 0x0; } PRIVATE void lbranch(backamount) int backamount; { mcount += defsize + 0x1; segadj(); if (pass2) { reldata(); if (!(lastexp.data & (RELBIT | UNDBIT))) { lastexp.offset = lastexp.offset - lc - lcjump; if ( last_pass<2 && backamount != 0x0 && !(lastexp.data & IMPBIT) && lastexp.offset + backamount < 0x80 + backamount) warning(SHORTB); /* -0x8? to 0x7F, warning */ } } } /* BCC (long branches emulated by short branch over & long jump) */ PUBLIC void mbcc() { getea(&target); if (target.indcount >= 0x2 || target.base != NOREG) kgerror(REL_REQ); else { #ifdef iscpu if (iscpu(3)) #else if (defsize != 0x2) #endif { page = PAGE1_OPCODE; ++mcount; opcode += 0x10; lbranch(0x84); } else { aprefix = opcode ^ 0x1; /* kludged storage for short branch over */ oprefix = defsize + 0x1; mcount += 0x2; opcode = JMP_OPCODE; lbranch(0x83); mcount -= 0x2; } } } /* bswap r32 */ PUBLIC void mbswap() { needcpu(4); ++mcount; Gd(&target); opcode |= rm[target.base]; } /* BR, CALL, J, JMP */ PUBLIC void mcall() { opcode_pt far_diff; bool_t indirect; register struct sym_s *symptr; far_diff = 0x0; if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT && symptr->data & SIZEBIT ) { if(symptr->value_reg_or_op.op.routine == FAROP) { far_diff = 0x8; getsym(); } if(symptr->value_reg_or_op.op.routine == WORDOP && opcode == JMP_SHORT_OPCODE) { opcode = JMP_OPCODE; getsym(); } } indirect = FALSE; if (asld_compatible && defsize <= 0x2) { calljmp_kludge = 0x2; if (sym == INDIRECT) { calljmp_kludge = 0x0; indirect = TRUE; getsym(); } } getea(&target); if (indirect && target.indcount == 0x1) target.indcount = 0x2; calljmp_kludge = 0x0; if (sym == COLON) { int tsize = target.size?target.size:defsize; if (opcode == JMP_SHORT_OPCODE) opcode = JMP_OPCODE; ++mcount; yesimmed(&target); getsym(); getea(&source); yesimmed(&source); if (mcount != 0x0) { if (opcode == JMP_OPCODE) opcode = 0xEA; else opcode = 0x9A; lastexp = source.displ; if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && tsize == 0x2 && (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) datatoobig(); mcount += tsize; target.size = 0x2; buildimm(&target, FALSE); } } else if (target.indcount >= 0x2 || target.base != NOREG) { ++mcount; notsegorspecreg(&target); if (target.indcount == 0) notbytesize(&target); if (mcount != 0x0) { if (opcode == JMP_SHORT_OPCODE) opcode = JMP_OPCODE; buildea(&target); if (opcode == JMP_OPCODE) opcode = 0x20; else opcode = 0x10; postb |= opcode + far_diff; opcode = 0xFF; } } else if (opcode == JMP_SHORT_OPCODE) { if (jumps_long && ((pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) || (last_pass==1))) { opcode = JMP_OPCODE; lbranch(0x83); } else { lastexp = target.displ; if (lastexp.data & IMPBIT) { error(NONIMPREQ); lastexp.data = FORBIT | UNDBIT; } mshort2(); } } else lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0); } /* CALLI, JMPI */ PUBLIC void mcalli() { bool_t indirect; ++mcount; indirect = FALSE; if (sym == INDIRECT) { getsym(); indirect = TRUE; } getea(&target); if (target.indcount >= 0x2 || target.base != NOREG) indirect = TRUE; if (indirect) { buildea(&target); if (opcode == 0xEA) opcode = 0x28; else opcode = 0x18; postb |= opcode; opcode = 0xFF; } else { int tsize = target.size?target.size:defsize; getcomma(); getea(&source); yesimmed(&source); if (mcount != 0x0) { lastexp = target.displ; if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) && tsize == 0x2 && (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L) { tsize=4; if( tsize != defsize ) oprefix = 0x66; /* datatoobig(); */ } needcpu(tsize==4?3:0); mcount += tsize; source.size = 0x2; buildimm(&source, FALSE); } } } /* DIV, IDIV, MUL */ PUBLIC void mdivmul() { if (getaccumreg(&source)) { ++mcount; getcomma(); Ex(&target); yes_samesize(); buildunary(0xF6 | regsegword[source.base]); } else mnegnot(); } /* ENTER */ PUBLIC void menter() { ++mcount; getimmed(&target, 0x2); getcomma(); getimmed(&source, 0x1); if (mcount != 0x0) { mcount += 2; lastexp = target.displ; /* getimmed(&source) wiped it out */ } needcpu(1); } /* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */ PUBLIC void mEwGw() { ++mcount; Ew(&target); getcomma(); Gw(&source); oprefix = 0x0; buildregular(); } /* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */ PUBLIC void mExGx() { ++mcount; Ex(&target); getcomma(); Gx(&source); yes_samesize(); opcode |= segword; buildregular(); } PUBLIC void mf_inher() { mcount += 0x2; postb = REG_MOD | (opcode & ~REG_MOD); opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6); if (opcode == ESCAPE_OPCODE_BASE) opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */ } /* [fldenv fnsave fnstenv frstor] mem */ PUBLIC void mf_m() { ++mcount; getindirect(&source); if (source.size != 0x0) kgerror(ILL_SIZE); buildfloat(); } /* [fldcw fnstcw] mem2i */ PUBLIC void mf_m2() { ++mcount; getindirect(&source); if (source.size != 0x0 && source.size != 0x2) kgerror(ILL_SIZE); buildfloat(); } /* fnstsw [mem2i ax] */ PUBLIC void mf_m2_ax() { if (getaccumreg(&target)) { if (target.base != AXREG) kgerror(ILLREG); else { opcode = 0x74; target.base = ST0REG; /* fake, really ax */ buildfreg(); } } else mf_m2(); } /* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */ PUBLIC void mf_m2_m4() { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x2) opcode |= 0x40; else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } /* [fild fistp] [mem2i mem4i mem8i] */ PUBLIC void mf_m2_m4_m8() { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x2) opcode |= 0x40; else if (source.size == 0x8) opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */ else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } /* [fcom fcomp] [mem4r mem8r optional-st(i)] */ PUBLIC void mf_m4_m8_optst() { if (sym == EOLSYM) { target.base = ST1REG; buildfreg(); } else mf_m4_m8_st(); } /* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */ PUBLIC void mf_m4_m8_stst() { target.base = fpregchk(); if (target.base != NOREG) { getcomma(); source.base = fpregchk(); if (source.base == NOREG) { error(FP_REG_REQ); source.base = ST0REG; } if (target.base == ST0REG) target.base = source.base; else { if (source.base != ST0REG) error(ILL_FP_REG_PAIR); opcode |= 0x40; if ((opcode & 0x07) >= 0x4) opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */ } buildfreg(); } else { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x8) opcode |= 0x40; else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } } /* fst [mem4r mem8r st(i)] */ PUBLIC void mf_m4_m8_st() { target.base = fpregchk(); if (target.base != NOREG) { if (opcode == FST_ENCODED) opcode |= 0x40; buildfreg(); } else { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x8) opcode |= 0x40; else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } } /* [fld fstp] [mem4r mem8r mem10r st(i)] */ PUBLIC void mf_m4_m8_m10_st() { target.base = fpregchk(); if (target.base != NOREG) { if (opcode == FSTP_ENCODED) opcode |= 0x40; buildfreg(); } else { ++mcount; getindirect(&source); if (source.size == 0x0) kgerror(SIZE_UNK); else if (source.size == 0x8) opcode |= 0x40; else if (source.size == 0xA) opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */ else if (source.size != 0x4) kgerror(ILL_SIZE); buildfloat(); } } /* [fbld fbstp] mem10r */ PUBLIC void mf_m10() { ++mcount; getindirect(&source); if (source.size != 0xA) kgerror(ILL_SIZE); buildfloat(); } /* ffree st(i) */ PUBLIC void mf_st() { target.base = fpregchk(); if (target.base == NOREG) kgerror(FP_REG_REQ); buildfreg(); } /* [fucom fucomp fxch] optional-st(i) */ PUBLIC void mf_optst() { if (sym == EOLSYM) { target.base = ST1REG; buildfreg(); } else mf_st(); } /* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */ PUBLIC void mf_stst() { target.base = fpregchk(); if (target.base == NOREG) { kgerror(FP_REG_REQ); return; } getcomma(); source.base = fpregchk(); if (source.base == NOREG) { kgerror(FP_REG_REQ); return; } if (source.base != ST0REG) { kgerror(ILL_FP_REG); return; } buildfreg(); } PUBLIC void mf_w_inher() { sprefix = WAIT_OPCODE; mf_inher(); } /* [fsave fstenv] mem */ PUBLIC void mf_w_m() { sprefix = WAIT_OPCODE; mf_m(); } /* fstcw mem2i */ PUBLIC void mf_w_m2() { sprefix = WAIT_OPCODE; mf_m2(); } /* fstsw [mem2i ax] */ PUBLIC void mf_w_m2_ax() { sprefix = WAIT_OPCODE; mf_m2_ax(); } /* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */ PUBLIC void mgroup1() { getbinary(); notsegorspecreg(&source); if (mcount != 0x0) { if (source.base == NOREG) { if (target.indcount == 0x0 && (target.base == ALREG || target.base == AXREG || (target.base == EAXREG && (source.displ.data & (FORBIT | RELBIT | UNDBIT) || !is8bitsignedoffset(source.displ.offset))))) { opcode |= 0x04 | segword; buildimm(&source, FALSE); } else { buildunary(0x80 | segword); buildimm(&source, TRUE); } } else { opcode |= direction | segword; buildregular(); } } } /* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */ PUBLIC void mgroup2() { ++mcount; Ex(&target); buildsegword(&target); getshift(&source); if (mcount != 0x0) { buildunary(0xD0 | segword); if (source.base == CLREG) opcode |= 0x2; else if (source.displ.offset != 0x1) { needcpu(1); opcode -= 0x10; source.size = 0x1; buildimm(&source, FALSE); } } } /* LLDT, LTR, SLDT, STR, VERR, VERW */ PUBLIC void mgroup6() { needcpu(2); ++mcount; Ew(&target); oprefix = 0x0; buildunary(0x0); } /* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */ PUBLIC void mgroup7() { needcpu(2); /* I think INVLPG is actually 386 */ ++mcount; if (opcode == 0x20 || opcode == 0x30) { Ew(&target); oprefix = 0x0; } else { getindirect(&target); oprefix = 0x0; if (target.size != 0x0 && target.size != 0x6) error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */ } buildunary(0x1); } /* BT, BTR, BTS, BTC */ PUBLIC void mgroup8() { needcpu(3); ++mcount; Ev(&target); getcomma(); /* Gv or Ib */ getea(&source); notindirect(&source); notsegorspecreg(&source); if (mcount != 0x0) { if (source.base == NOREG) { buildunary(0xBA); source.size = 0x1; buildimm(&source, TRUE); } else { yes_samesize(); opcode += 0x83; buildregular(); } } } /* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */ PUBLIC void mGvEv() { needcpu(2); ++mcount; Gv(&source); getcomma(); Ev(&target); yes_samesize(); buildregular(); } /* bound [r16,m16&16 r32,m32&32] */ PUBLIC void mGvMa() { ++mcount; Gv(&source); getcomma(); getindirect(&target); yes_samesize(); buildregular(); } /* LDS, LES, LFS, LGS, LSS */ PUBLIC void mGvMp() { ++mcount; Gv(&source); getcomma(); getindirect(&target); if (target.size != 0x0 && target.size != 0x2 + source.size) error(MISMATCHED_SIZE); buildregular(); } /* IMUL */ PUBLIC void mimul() { ++mcount; Ex(&target); if (sym != COMMA) { buildsegword(&target); buildunary(0xF6 | segword); return; } getcomma(); notindirect(&target); source = target; /* direction is swapped */ getea(&target); notsegorspecreg(&target); yes_samesize(); if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG)) { needcpu(3); page = PAGE1_OPCODE; ++mcount; opcode = 0xAF; buildregular(); } else { if (sym == COMMA) { getsym(); getea(&source2); yesimmed(&source2); } else { source2 = target; target = source; } source2.size = target.size; if (is8bitsignedoffset(source2.displ.offset)) { source2.size = 0x1; opcode = 0x6B; } else { source2.size = target.size; opcode = 0x69; } buildregular(); if (mcount != 0x0) buildimm(&source2, FALSE); } } /* IN */ PUBLIC void min() { ++mcount; if (opcode & WORDBIT) /* inw; ind not supported */ mnsize = 0x2; if (sym == EOLSYM && mnsize != 0x0) target.size = mnsize; else { if (getaccumreg(&target)) { if (mnsize != 0x0 && regsize[target.base] != mnsize) error(MISMATCHED_SIZE); getcomma(); } else target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG]; opcode |= regsegword[target.base]; if (!getdxreg(&source)) { getimmed(&source, 0x1); opcode -= 0x8; } } if (target.size > 0x1 && target.size != defsize) oprefix = 0x66; } /* DEC, INC */ PUBLIC void mincdec() { ++mcount; Ex(&target); buildsegword(&target); if (target.indcount == 0x0 && segword == WORDBIT) opcode |= 0x40 | rm[target.base]; else buildunary(0xFE | segword); } /* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */ /* MOVSW, OUTSW, SCASW, STOSW */ PUBLIC void minher16() { minher(); if (defsize != 0x2) oprefix = 0x66; } /* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */ /* MOVSD, OUTSD, SCASD, STOSD */ PUBLIC void minher32() { minher(); if (defsize != 0x4) oprefix = 0x66; needcpu(3); } /* AAD, AAM */ PUBLIC void minhera() { ++mcount; if (sym == EOLSYM) { target.displ.offset = 0xA; target.size = 0x1; buildimm(&target, FALSE); } else getimmed(&target, 0x1); } /* INT */ PUBLIC void mint() { ++mcount; getimmed(&target, 0x1); if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) && (opcode_t) immadr.offset == 0x3) { immcount = 0x0; opcode = 0xCC; } } /* JCC */ PUBLIC void mjcc() { /* First look for j* near */ if (sym == IDENT && gsymptr->type & MNREGBIT && gsymptr->data & SIZEBIT && gsymptr->value_reg_or_op.op.routine == WORDOP && opcode < 0x80) { getsym(); getea(&target); if (target.indcount >= 0x2 || target.base != NOREG) kgerror(REL_REQ); else { needcpu(3); page = PAGE1_OPCODE; ++mcount; opcode += 0x10; lbranch(0x84); } } else if (!jumps_long || opcode > 0x80) /* above 0x80 means loop, not long */ mshort(); else /* mbcc */ { getea(&target); lastexp = target.displ; if ( (pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) || last_pass==1) { if (target.indcount >= 0x2 || target.base != NOREG) kgerror(REL_REQ); aprefix = opcode ^ 0x1; /* kludged storage for short branch over */ oprefix = defsize + 0x1; mcount += 0x2; opcode = JMP_OPCODE; lbranch(0x83); mcount -= 0x2; } else { /* 8 bit */ if (lastexp.data & IMPBIT) { error(NONIMPREQ); lastexp.data = FORBIT | UNDBIT; } mshort2(); } } } /* JCXZ, JECXZ */ PUBLIC void mjcxz() { if (opcode != defsize) { aprefix = 0x67; ++mcount; /* quick fix - mshort() needs to know */ } opcode = 0xE3; mshort(); if (aprefix != 0x0) --mcount; /* quick fix - main routine bumps it again */ } /* LEA */ PUBLIC void mlea() { Gv(&source); /* back to front */ getcomma(); ++mcount; getindirect(&target); yes_samesize(); buildregular(); } /* MOV */ PUBLIC void mmov() { getbinary(); if (segword >= SEGMOV) { oprefix = 0x0; notimmed(&target); /* target is actually the source */ if (segword > SEGMOV) /* special reg */ notindirect(&target); } if (mcount != 0x0) { if (target.base == NOREG && target.index == NOREG && (source.base == ALREG || source.base == AXREG || source.base == EAXREG)) { opcode = 0xA0 | (direction ^ TOREGBIT) | segword; lastexp = target.displ; if ((source.size = displsize(&target)) != defsize) aprefix = 0x67; mcount += source.size; needcpu(source.size==4?3:0); } else if (source.base == NOREG) { if (target.indcount == 0x0) opcode = 0xB0 | (segword << 0x3) | rm[target.base]; else { buildea(&target); opcode = 0xC6 | segword; } buildimm(&source, FALSE); } else { if (isspecreg(source.base)) { needcpu(3); page = PAGE1_OPCODE; ++mcount; opcode = 0x0; } opcode |= direction | segword; buildregular(); } } } /* MOVSX, MOVZX */ PUBLIC void mmovx() { ++mcount; Gv(&source); getcomma(); Ex(&target); if (target.size == 0x0) kgerror(SIZE_UNK); if (target.size > 0x2) kgerror(ILL_SIZE); oprefix = 0x0; if (source.size != defsize) oprefix = 0x66; buildsegword(&target); opcode |= segword; buildregular(); } /* NEG, NOT */ PUBLIC void mnegnot() { ++mcount; Ex(&target); buildsegword(&target); buildunary(0xF6 | segword); } /* OUT */ PUBLIC void mout() { ++mcount; if (opcode & WORDBIT) /* outw; outd not supported */ mnsize = 0x2; if (sym == EOLSYM && mnsize != 0x0) source.size = mnsize; else { if (!getdxreg(&target)) { getimmed(&target, 0x1); opcode -= 0x8; } if (sym == COMMA) { getsym(); if (!getaccumreg(&source)) kgerror(AL_AX_EAX_EXP); else if (mnsize != 0x0 && regsize[source.base] != mnsize) error(MISMATCHED_SIZE); } else source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG]; opcode |= regsegword[source.base]; } if (source.size > 0x1 && source.size != defsize) oprefix = 0x66; } /* POP, PUSH */ PUBLIC void mpushpop() { opcode_t oldopcode; ++mcount; getea(&target); buildsegword(&target); notbytesize(&target); if ((oldopcode = opcode) == POP_OPCODE) { notimmed(&target); if (target.base == CSREG) kgerror(ILL_SEG_REG); } if (mcount != 0x0) { if (target.indcount == 0x0) { if (segword == SEGMOV) { switch (target.base) { case CSREG: opcode = 0x0E; break; case DSREG: opcode = 0x1E; break; case ESREG: opcode = 0x06; break; case SSREG: opcode = 0x16; break; case FSREG: opcode = 0xA0; page = PAGE1_OPCODE; ++mcount; break; case GSREG: opcode = 0xA8; page = PAGE1_OPCODE; ++mcount; break; } if (oldopcode == POP_OPCODE) ++opcode; } else if (target.base != NOREG) { opcode = 0x50 | rm[target.base]; if (oldopcode == POP_OPCODE) opcode |= 0x8; } else { opcode = 0x68; if (oldopcode == POP_OPCODE) ++opcode; buildimm(&target, TRUE); } } else { buildea(&target); if (oldopcode == PUSH_OPCODE) postb |= 0x6 << REG_SHIFT; } } } /* RET, RETF */ PUBLIC void mret() { ++mcount; if (sym != EOLSYM) { --opcode; getimmed(&target, 0x2); } } /* SEG CS/DS/ES/FS/GS/SS */ PUBLIC void mseg() { reg_pt reg; if (regsegword[reg = regchk()] != SEGMOV) error(SEG_REG_REQ); else { getsym(); ++mcount; opcode = (segoverride - CSREG)[reg]; } } /* SETCC */ PUBLIC void msetcc() { ++mcount; Eb(&target); if (mcount != 0x0) buildea(&target); } /* SHLD, SHRD */ PUBLIC void mshdouble() { needcpu(3); ++mcount; Ev(&target); getcomma(); Gv(&source); yes_samesize(); buildregular(); getshift(&source2); lastexp = target.displ; /* getshift() wiped it out */ if (mcount != 0x0) { if (source2.base == CLREG) opcode |= 0x1; else { source2.size = 0x1; buildimm(&source2, FALSE); } } } /* TEST Similar to the regular group1 operators. It does not allow the sign extended immediate byte forms and does not use the relevant direction bit. */ PUBLIC void mtest() { getbinary(); notsegorspecreg(&source); if (source.base == NOREG) { if (mcount != 0x0) { if (target.indcount == 0x0 && (target.base == ALREG || target.base == AXREG || target.base == EAXREG)) opcode = 0xA8 | segword; else { buildea(&target); opcode = 0xF6 | segword; } } buildimm(&source, FALSE); } else { opcode |= segword; buildregular(); } } /* XCHG Similar to the regular group1 operators. It does not allow any of the immediate forms and does not use the irrelevant direction bit. */ PUBLIC void mxchg() { getbinary(); notimmed(&source); notsegorspecreg(&source); if (target.indcount == 0x0) { if (target.base == AXREG || target.base == EAXREG) { opcode = 0x90 + rm[source.base]; return; } if (source.base == AXREG || source.base == EAXREG) { opcode = 0x90 + rm[target.base]; return; } } opcode |= segword; buildregular(); } PRIVATE void notbytesize(eap) register struct ea_s *eap; { if (eap->size == 0x1) kgerror(ILL_SIZE); } PRIVATE void notimmed(eap) register struct ea_s *eap; { if (eap->indcount == 0x0 && eap->base == NOREG) kgerror(ILL_IMM_MODE); } PRIVATE void notindirect(eap) register struct ea_s *eap; { if (eap->indcount != 0x0) kgerror(ILL_IND); } PRIVATE void notsegorspecreg(eap) register struct ea_s *eap; { if (regsegword[eap->base] >= SEGMOV) kgerror(ILLREG); } PRIVATE void yesimmed(eap) register struct ea_s *eap; { if (eap->indcount == 0x1) eap->indcount = 0x0; if (eap->indcount != 0x0 || eap->base != NOREG) kgerror(IMM_REQ); } PRIVATE void yes_samesize() { if (target.size == 0x0) target.size = source.size; else if (source.size != 0x0 && target.size != source.size) kgerror(MISMATCHED_SIZE); } #endif /* I80386 */ #ifdef MC6809 /* 6809 opcode constants */ /* bits for indexed addressing */ #define INDIRECTBIT 0x10 #define INDEXBIT 0x80 /* except 5 bit offset */ #define PCRELBIT 0x04 /* PC relative (in certain cases) */ #define RRBITS 0x60 /* register select bits */ PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */ { 0x60 | INDEXBIT, /* S */ 0x40 | INDEXBIT, /* U */ 0x00 | INDEXBIT, /* X */ 0x20 | INDEXBIT, /* Y */ PCRELBIT | INDEXBIT, /* PC */ }; PRIVATE opcode_t pushpull[] = /* push/pull codes */ { 0x40, /* S */ 0x40, /* U */ 0x10, /* X */ 0x20, /* Y */ 0x80, /* PC */ 0x02, /* A */ 0x04, /* B */ 0x01, /* CC */ 0x08, /* DP */ 0x06, /* D */ }; PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */ { 0x40, /* S */ 0x30, /* U */ 0x10, /* X */ 0x20, /* Y */ 0x50, /* PC */ 0x80, /* A */ 0x90, /* B */ 0xA0, /* CC */ 0xB0, /* DP */ 0x00, /* D */ }; PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */ { 0x04, /* S */ 0x03, /* U */ 0x01, /* X */ 0x02, /* Y */ 0x05, /* PC */ 0x08, /* A */ 0x09, /* B */ 0x0A, /* CC */ 0x0B, /* DP */ 0x00, /* D */ }; FORWARD void checkpostinc P((void)); FORWARD void doaltind P((void)); FORWARD void do1altind P((void)); FORWARD void fixupind P((void)); FORWARD void getindexnopost P((void)); FORWARD void inderror P((char * err_str)); FORWARD reg_pt indreg P((reg_pt maxindex)); FORWARD void predec1 P((void)); FORWARD void sustack P((reg_pt stackreg)); PRIVATE void checkpostinc() { if (sym == ADDOP) { if (postb & INDIRECTBIT) inderror(ILLMOD); /* single-inc indirect illegal */ else { lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */ getsym(); } } else if (sym == POSTINCOP) { postb |= 0x1; getsym(); } else postb |= 0x4; fixupind(); } /* common code for all-mode ops, alterable-mode ops, indexed ops */ PRIVATE void doaltind() { mcount += 0x2; if (sym == LBRACKET) { postb = INDIRECTBIT; getsym(); do1altind(); if (sym != RBRACKET) error(RBEXP); } else do1altind(); } PRIVATE void do1altind() { bool_t byteflag; /* set if direct or short indexed adr forced */ char *oldlineptr; char *oldsymname; reg_pt reg; bool_t wordflag; /* set if extended or long indexed adr forced*/ if ((reg = regchk()) != NOREG) { switch (reg) { case AREG: postb |= 0x86; break; case BREG: postb |= 0x85; break; case DREG: postb |= 0x8B; break; default: if (indreg(MAXINDREG) != NOREG) checkpostinc(); return; } getsym(); if (sym != COMMA) inderror(COMEXP); else getindexnopost(); return; } else if (sym == SUBOP) /* could be -R or - in expression */ { oldlineptr = lineptr; /* save state */ oldsymname = symname; getsym(); reg = regchk(); lineptr = oldlineptr; symname = oldsymname; if (reg != NOREG) { predec1(); /* it's -R */ return; } sym = SUBOP; } else if (sym == COMMA) { postb |= INDEXBIT; getsym(); if (sym == SUBOP) { predec1(); return; } else if (sym != PREDECOP) { if (indreg(MAXINDREG) != NOREG) checkpostinc(); return; } } if (sym == PREDECOP) { postb |= 0x83; getindexnopost(); return; } /* should have expression */ wordflag = byteflag = FALSE; if (sym == LESSTHAN) { /* context-sensitive, LESSTHAN means byte-sized here */ byteflag = TRUE; getsym(); } else if (sym == GREATERTHAN) { /* context-sensitive, GREATERTHAN means word-sized here */ wordflag = TRUE; getsym(); } expres(); if (sym == COMMA) { /* offset from register */ getsym(); if ((reg = indreg(PCREG)) == NOREG) return; postb |= 0x8; /* default 8 bit offset */ if (reg == PCREG) { reldata(); if (!(lastexp.data & (RELBIT | UNDBIT))) { lastexp.offset = lastexp.offset - lc; if (page != 0x0) lastexp.offset -= 0x4; /* extra for instruction */ else lastexp.offset -= 0x3; /* 3 byte instruction assuming 8 bit offset */ } } if (byteflag) { if (!(lastexp.data & (RELBIT | UNDBIT)) && !is8bitsignedoffset(lastexp.offset)) error(ABOUNDS); /* forced short form is impossible */ ++mcount; } else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) || !is8bitsignedoffset(lastexp.offset)) { /* 16 bit offset */ if (postb & PCRELBIT && !(lastexp.data & RELBIT)) --lastexp.offset; /* instruction 1 longer than already allowed */ postb |= 0x1; mcount += 0x2; } else if (!(postb & PCRELBIT) && (offset_t) (lastexp.offset + 0x10) < 0x20 && !(postb & INDIRECTBIT && lastexp.offset != 0x0)) { /* 5 bit offset */ postb &= RRBITS | INDIRECTBIT; if (lastexp.offset == 0x0) postb |= 0x84; /* index with zero offset */ else postb |= (lastexp.offset & 0x1F); } else /* 8 bit offset */ ++mcount; fixupind(); } else if (postb & INDIRECTBIT) { /* extended indirect */ postb = 0x9F; mcount += 0x2; fixupind(); } else if (postb & INDEXBIT) inderror(ILLMOD); /* e.g. LEAX $10 */ else { if (byteflag || (!wordflag && !(lastexp.data & (FORBIT | RELBIT)) && (lastexp.offset >> 0x8) == dirpag)) { /* direct addressing */ if (opcode >= 0x80) opcode |= 0x10; } else /* extended addressing */ { if (opcode < 0x80) opcode |= 0x70; else opcode |= 0x30; ++mcount; if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) && !(lastexp.data & IMPBIT) && lastexp.offset + (0x81 - 0x3) < 0x101) /* JSR or JMP could be done with BSR or BRA */ warning(SHORTB); } } } PRIVATE void fixupind() { if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */ { if (opcode < 0x80) opcode |= 0x60; else opcode |= 0x20; } } PRIVATE void getindexnopost() { getsym(); if (indreg(MAXINDREG) != NOREG) fixupind(); } PRIVATE void inderror(err_str) char * err_str; { error(err_str); if (postb & INDIRECTBIT) sym = RBRACKET; /* fake right bracket to kill further errors */ fixupind(); } /* check current symbol is an index register (possibly excepting PC) */ /* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */ /* otherwise generate error, return FALSE */ PRIVATE reg_pt indreg(maxindex) reg_pt maxindex; { reg_pt reg; if ((reg = regchk()) == NOREG) inderror(IREGEXP); else if (reg > maxindex) { inderror(ILLREG); reg = NOREG; } else { postb |= rrindex[reg]; getsym(); } return reg; } /* all-mode ops */ PUBLIC void mall() { if (sym == IMMEDIATE) mimmed(); else malter(); } /* alterable mode ops */ PUBLIC void malter() { postb = 0x0; /* not yet indexed or indirect */ doaltind(); } /* indexed mode ops */ PUBLIC void mindex() { postb = INDEXBIT; /* indexed but not yet indirect */ doaltind(); } /* immediate ops */ PUBLIC void mimmed() { opcode_t nybble; mcount += 0x2; if (sym != IMMEDIATE) error(ILLMOD); else { if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 || nybble == 0xC || nybble >= 0xE)) ++mcount; /* magic for long immediate */ symexpres(); if (pass2 && mcount <= 0x2) { chkabs(); checkdatabounds(); } } } /* long branches */ PUBLIC void mlong() { mcount += 0x3; /* may be 0x0 or 0x1 here */ expres(); segadj(); if (pass2) { reldata(); if (!(lastexp.data & (RELBIT | UNDBIT))) { lastexp.offset = lastexp.offset - lc - lcjump; if ( last_pass<2 && !(lastexp.data & IMPBIT) && lastexp.offset + 0x81 < 0x101) warning(SHORTB); /* -0x81 to 0x7F, warning */ } } } /* PSHS and PULS */ PUBLIC void msstak() { sustack(SREG); } /* TFR and EXG */ PUBLIC void mswap() { reg_pt reg; mcount = 0x2; if ((reg = regchk()) == NOREG) error(REGEXP); else { postb = tfrexg1[reg]; getsym(); if (sym != COMMA) error(COMEXP); else { getsym(); if ((reg = regchk()) == NOREG) error(REGEXP); else if ((postb |= tfrexg2[reg]) & 0x88 && (postb & 0x88) != 0x88) error(ILLREG); /* registers not of same size */ } } } /* PSHU and PULU */ PUBLIC void mustak() { sustack(UREG); } PRIVATE void predec1() { if (postb & INDIRECTBIT) inderror(ILLMOD); /* single-dec indirect illegal */ else { postb |= 0x82; getindexnopost(); } } /* common routine for PSHS/PULS/PSHU/PULU */ PRIVATE void sustack(stackreg) reg_pt stackreg; { reg_pt reg; mcount = 0x2; while ((reg = regchk()) != NOREG) { if (reg == stackreg) { error(ILLREG); /* cannot stack self */ break; } postb |= pushpull[reg]; getsym(); if (sym != COMMA) break; getsym(); } } #endif /* MC6809 */ /* routines common to all processors */ PUBLIC void getcomma() { if (sym != COMMA) error(COMEXP); else getsym(); } /* inherent ops */ /* for I80386 */ /* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */ /* INVD, */ /* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */ /* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */ PUBLIC void minher() { ++mcount; } /* short branches */ PUBLIC void mshort() { nonimpexpres(); mshort2(); } PRIVATE void mshort2() { mcount += 0x2; if (pass2) { reldata(); if (lastexp.data & RELBIT) showrelbad(); else if (!(lastexp.data & UNDBIT)) { lastexp.offset = lastexp.offset - lc - mcount; if (!is8bitsignedoffset(lastexp.offset)) error(ABOUNDS); } } } /* check if current symbol is a register, return register number or NOREG */ PRIVATE reg_pt regchk() { register struct sym_s *symptr; if (sym == IDENT) { if ((symptr = gsymptr)->type & MNREGBIT) { if (symptr->data & REGBIT) { int regno = symptr->value_reg_or_op.reg; #ifdef I80386 if (regno == ST0REG && !fpreg_allowed) error(FP_REG_NOT_ALLOWED); /* Check cpu */ needcpu((regno==FSREG||regno==GSREG)?3:0); needcpu((regno>=EAXREG && regno<=ESPREG)?3:0); needcpu((regno>=CR0REG && regno<=TR7REG)?3:0); #endif return regno; } } else if( last_pass == 1 ) if (!(symptr->type & (LABIT | MACBIT | VARBIT))) symptr->data |= FORBIT; /* show seen in advance */ } return NOREG; } /* convert lastexp.data for PC relative */ PRIVATE void reldata() { if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM)) { if ((lastexp.data ^ lcdata) & RELBIT) showrelbad(); /* rel - abs is weird, abs - rel is bad */ else { pcrflag = OBJ_R_MASK; lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT; /* segment is that of lastexp.data */ } } else /* same file, segment and relocation */ lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM); } PRIVATE void segadj() { if ((lastexp.data & UNDBIT) && textseg >= 0 ) { lastexp.sym->data &= ~SEGM; lastexp.sym->data |= (lcdata & SEGM); } } dev86-0.16.17/as/genlist.c0000644000000000000000000002351007315174137015005 0ustar rootroot00000000000000/* genlist.c - generate listing and error reports for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "address.h" #include "flag.h" #include "file.h" #include "globvar.h" #include "macro.h" #include "scan.h" #include "source.h" #define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1) /* length of formatted code listing */ #define MAXERR 6 /* maximum errors listed per line */ struct error_s /* to record error info */ { char * err_str; unsigned char position; }; /* code listing format */ struct code_listing_s { union linum_macro_u { char linum[LINUM_LEN]; struct { char pad[1]; char mark[1]; char level[1]; } macro; } linum_or_macro; char padlinum[1]; char lc[4]; char padlc[1]; #ifdef I80386 char lprefix[2]; char aprefix[2]; char oprefix[2]; char sprefix[2]; #endif char page[2]; char opcode[2]; char postb[2]; #ifdef I80386 char sib[2]; #endif char padopcode[1]; #if SIZEOF_OFFSET_T > 2 char displ4[2]; char displ3[2]; #endif char displ2[2]; char displ1[2]; char reldispl[1]; char paddispl[1]; #ifdef I80386 char imm4[2]; char imm3[2]; char imm2[2]; char imm1[2]; char relimm[1]; char padimm[1]; #endif char nullterm; }; PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */ PRIVATE unsigned char errcount; /* # errors in line */ PRIVATE bool_t erroverflow; /* set if too many errors on line */ FORWARD char *build_1hex_number P((opcode_pt num, char *where)); FORWARD void list1 P((fd_t fd)); FORWARD void listcode P((void)); FORWARD void listerrors P((void)); FORWARD void paderrorline P((unsigned nspaces)); /* format 1 byte number as 2 hex digits, return ptr to end */ PRIVATE char *build_1hex_number(num, where) opcode_pt num; register char *where; { where[0] = hexdigit[((unsigned) num % 256) / 16]; where[1] = hexdigit[(unsigned) num % 16]; return where + 2; } /* format 2 byte number as 4 hex digits, return ptr to end */ PUBLIC char *build_2hex_number(num, where) unsigned num; char *where; { return build_1hex_number((opcode_pt) num, build_1hex_number((opcode_pt) (num / 256), where)); } /* format 2 byte number as decimal with given width (pad with leading '0's) */ /* return ptr to end */ PUBLIC char *build_number(num, width, where) unsigned num; unsigned width; register char *where; { static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,}; unsigned char digit; unsigned char power; register unsigned power_of_10; power = 5; /* actually 1 more than power */ do { for (digit = '0', power_of_10 = (powers_of_10 - 1)[power]; num >= power_of_10; num -= power_of_10) ++digit; if (power <= width) *where++ = digit; } while (--power != 0); return where; } /* record number and position of error (or error buffer overflow) */ PUBLIC void warning(err_str) char * err_str; { if (!as_warn.current) return; ++totwarn; --toterr; error(err_str); } PUBLIC void error(err_str) char * err_str; { register struct error_s *errptr; register struct error_s *errptrlow; unsigned char position; if (errcount >= MAXERR) erroverflow = TRUE; else { position = symname - linebuf; for (errptr = errbuf + errcount; errptr > errbuf && errptr->position > position; errptr = errptrlow) { errptrlow = errptr - 1; errptr->err_str = errptrlow->err_str; errptr->position = errptrlow->position; } errptr->err_str = err_str; errptr->position = position; ++errcount; ++toterr; } } /* list 1 line to list file if any errors or flags permit */ /* list line to console as well if any errors and list file is not console */ PUBLIC void listline() { if (!listpre && lineptr != 0) { if (errcount || (list.current && (!macflag || mcount != 0)) || (macflag && maclist.current) || list_force ) list1(lstfil); if (errcount) { if (lstfil != STDOUT) list1(STDOUT); errcount = 0; erroverflow = FALSE; } } } /* list 1 line unconditionally */ PRIVATE void list1(fd) fd_t fd; { outfd = fd; listcode(); write(outfd, linebuf, (unsigned) (lineptr - linebuf)); writenl(); if (errcount != 0) listerrors(); listpre = TRUE; list_force=FALSE; } /* list object code for 1 line */ PRIVATE void listcode() { unsigned char count; struct code_listing_s *listptr; unsigned numlength; char *numptr; listptr = (struct code_listing_s *) temp_buf(); memset((char *) listptr, ' ', sizeof *listptr); listptr->nullterm = 0; if (macflag) { listptr->linum_or_macro.macro.mark[0] = '+'; listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1); } else { numlength = LINUM_LEN; numptr = listptr->linum_or_macro.linum; if (infiln != infil0) { *numptr++ = infiln - infil0 + ('a' - 1); numlength = LINUM_LEN - 1; } build_number(linum, numlength, numptr); } if ((count = mcount) != 0 || popflags & POPLC) build_2hex_number((u16_T) lc, listptr->lc); if (popflags & POPLO) { #if SIZEOF_OFFSET_T > 2 if (popflags & POPLONG) build_2hex_number((u16_T) (lastexp.offset / (offset_t) 0x10000L), listptr->displ4); #endif if (popflags & POPHI) build_2hex_number((u16_T) lastexp.offset, listptr->displ2); else build_1hex_number((opcode_pt) /* XXX */(u16_T) lastexp.offset, listptr->displ1); if (lastexp.data & RELBIT) listptr->reldispl[0] = '>'; } else if (count != 0) { #ifdef I80386 if (aprefix != 0) { --count; build_1hex_number(aprefix, listptr->aprefix); } if (oprefix != 0) { --count; build_1hex_number(oprefix, listptr->oprefix); } if (sprefix != 0) { --count; build_1hex_number(sprefix, listptr->sprefix); } #endif if (page != 0) { build_1hex_number(page, listptr->page); --count; } build_1hex_number(opcode, listptr->opcode); --count; if (postb != 0) { --count; build_1hex_number(postb, #ifdef MC6809 count == 0 ? listptr->displ1 : #endif listptr->postb); } #ifdef I80386 if (sib != NO_SIB) { --count; build_1hex_number(sib, listptr->sib); } #endif if (count > 0) { build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1); if (lastexp.data & RELBIT) listptr->reldispl[0] = '>'; } if (count > 1) build_1hex_number((opcode_pt) (lastexp.offset >> 0x8), listptr->displ2); #if SIZEOF_OFFSET_T > 2 if (count > 2) { build_1hex_number((opcode_pt) (lastexp.offset >> 0x10), listptr->displ3); build_1hex_number((opcode_pt) (lastexp.offset >> 0x18), listptr->displ4); } #endif #ifdef I80386 if (immcount > 0) { build_1hex_number((opcode_pt) immadr.offset, listptr->imm1); if (immadr.data & RELBIT) listptr->relimm[0] = '>'; } if (immcount > 1) build_1hex_number((opcode_pt) (immadr.offset >> 0x8), listptr->imm2); if (immcount > 2) { build_1hex_number((opcode_pt) (immadr.offset >> 0x10), listptr->imm3); build_1hex_number((opcode_pt) (immadr.offset >> 0x18), listptr->imm4); } #endif } writes((char *) listptr); } /* list errors, assuming some */ PRIVATE void listerrors() { unsigned char column; unsigned char errcol; /* column # in error line */ unsigned char errcolw; /* working column in error line */ char *errmsg; struct error_s *errptr; char *linep; unsigned char remaining; #ifdef I80386 paderrorline(1); #else paderrorline(CODE_LIST_LENGTH - LINUM_LEN); #endif remaining = errcount; column = 0; /* column to match with error column */ errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */ errptr = errbuf; linep = linebuf; do { #ifdef I80386 if(errcol != CODE_LIST_LENGTH) { writenl(); paderrorline(1); } writes(errmsg = errptr->err_str); errcol = strlen(errmsg)+LINUM_LEN+1; column = 0; linep = linebuf; errcolw = CODE_LIST_LENGTH; while (errcolw > errcol) { writec('.'); ++errcol; } #endif while (errptr && errptr->position < 132 && column < errptr->position) { ++column; if (*linep++ == '\t') /* next tab (standard tabs only) */ errcolw = (errcolw + 8) & 0xf8; else ++errcolw; while (errcolw > errcol) { #ifdef I80386 writec('.'); #else writec(' '); #endif ++errcol; } } #ifdef I80386 writec('^'); ++errcol; #else if (errcolw < errcol) /* position under error on new line */ { writenl(); paderrorline((unsigned) errcolw - LINUM_LEN); } writec('^'); writes(errmsg = errptr->err_str); errcol += strlen(errmsg); #endif ++errptr; } while (--remaining != 0); writenl(); if (erroverflow) { #ifdef I80386 paderrorline(1); #else paderrorline(CODE_LIST_LENGTH - LINUM_LEN); #endif writesn(FURTHER); } } /* pad out error line to begin under 1st char of source listing */ PRIVATE void paderrorline(nspaces) unsigned nspaces; { int nstars = LINUM_LEN; while (nstars-- != 0) writec('*'); /* stars under line number */ while (nspaces-- != 0) writec(' '); /* spaces out to error position */ } /* write 1 character */ PUBLIC void writec(ch) char ch; { write(outfd, &ch, 1); } /* write newline */ PUBLIC void writenl() { writes(SOS_EOLSTR); } /* write 1 offset_t, order to suit target */ PUBLIC void writeoff(offset) offset_t offset; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 2 u4c4(buf, offset); #else u2c2(buf, offset); #endif write(outfd, buf, sizeof buf); } /* write string */ PUBLIC void writes(s) char *s; { write(outfd, s, strlen(s)); } /* write string followed by newline */ PUBLIC void writesn(s) char *s; { writes(s); writenl(); } /* write 1 word, order to suit target */ PUBLIC void writew(word) unsigned word; { char buf[2]; u2c2(buf, (u16_T) word); write(outfd, buf, sizeof buf); } dev86-0.16.17/as/macro.h0000644000000000000000000000066704552506762014461 0ustar rootroot00000000000000/* macro.h - global variables for macro expansion for assembler */ EXTERN bool_t macflag; /* inside macro flag */ EXTERN bool_t macload; /* loading macro flag */ EXTERN unsigned macnum; /* macro call counter */ EXTERN unsigned char maclevel; /* nesting level */ EXTERN struct schain_s *macpar; /* parameter save buffer */ EXTERN struct schain_s *macptop; /* top of param buffer (+1) */ EXTERN struct macro_s *macstak; /* stack ptr */ dev86-0.16.17/as/scan.h0000644000000000000000000000100507315174244014263 0ustar rootroot00000000000000/* scan.h - global variables for scanner for assembler */ #define EOLCHAR '\n' EXTERN struct sym_s *gsymptr; /* global symbol ptr */ EXTERN char lindirect; /* left symbol for indirect addressing */ EXTERN char *lineptr; /* current line position */ EXTERN offset_t number; /* constant number */ EXTERN char * rindexp; /* error code for missing rindirect */ EXTERN char rindirect; /* right symbol for indirect addressing */ EXTERN char sym; /* current symbol */ EXTERN char *symname; /* current symbol name */ dev86-0.16.17/as/globvar.h0000644000000000000000000000742007315174613015002 0ustar rootroot00000000000000/* globvar.h - global variables for assembler */ /* global control and bookkeeping */ EXTERN bool_t binaryc; /* current binary code flag */ EXTERN bool_t binaryg; /* global binary code flag */ EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */ EXTERN bool_t binmbuf_set; /* set to 1 when binmbuf set by org */ EXTERN unsigned char dirpag; /* direct page */ EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */ EXTERN bool_t jumps_long; /* make all jumps long */ EXTERN unsigned char mapnum; /* global map number */ EXTERN bool_t objectc; /* current object code flag */ EXTERN bool_t objectg; /* global object code flag */ EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */ EXTERN offset_t progent; /* program entry point */ EXTERN bool_t symgen; /* generate symbol table flag */ EXTERN unsigned toterr; /* total errors */ EXTERN unsigned totwarn; /* total warnings */ EXTERN bool_t list_force; /* Force line to be listed - no error */ /* bookeeping for current line */ EXTERN char *linebuf; /* buffer */ /* for symbol table routines */ EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */ EXTERN struct sym_s **spt; /* symbol pointer table */ EXTERN struct sym_s **spt_top; /* top of symbol ptr table */ /* for translator */ EXTERN struct sym_s *label; /* non-null if valid label starts line */ EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/ EXTERN unsigned char popflags; /* pseudo-op flags */ /* for BLOCK stack */ EXTERN struct block_s *blockstak; /* stack ptr */ EXTERN unsigned char blocklevel; /* nesting level */ /* for IF stack */ EXTERN struct if_s *ifstak; /* stack ptr */ EXTERN unsigned char iflevel; /* nesting level */ EXTERN bool_t ifflag; /* set if assembling */ /* location counters for various segments */ EXTERN offset_t lc; /* location counter */ EXTERN unsigned char lcdata; /* shows how lc is bound */ /* FORBIT is set if lc is forward referenced */ /* RELBIT is is if lc is relocat. (not ASEG) */ EXTERN offset_t lcjump; /* lc jump between lines */ EXTERN offset_t oldlabel; /* Used for checking for moving labels */ #ifdef LOW_BYTE #define mcount (((unsigned char *) &lcjump)[LOW_BYTE]) /* low byte of lcjump */ #else #define mcount lcjump /* I think this is just a speed hack */ #endif EXTERN struct lc_s *lcptr; /* top of current spot in lctab */ EXTERN struct lc_s *lctab; /* start of lctab */ EXTERN struct lc_s *lctabtop; /* top of lctab */ /* for code generator */ EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */ EXTERN opcode_t page; EXTERN opcode_t opcode; EXTERN opcode_t postb; /* postbyte, 0 if none */ EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */ EXTERN int last_pass; /* Pass number of last pass */ EXTERN int dirty_pass; /* Set if this pass had a label movement */ EXTERN int textseg; /* Text segment id */ #ifdef I80386 EXTERN opcode_t aprefix; /* address size prefix or 0 */ EXTERN bool_t asld_compatible; /* asld compatibility flag */ EXTERN opsize_t defsize; /* current default size */ EXTERN opsize_t idefsize; /* initial default size */ EXTERN opcode_t oprefix; /* operand size prefix or 0 */ EXTERN opcode_t sprefix; /* segment prefix or 0 */ EXTERN opcode_t sib; /* scale-index-base byte */ EXTERN int cpuid; /* Assembler instruction limit flag */ EXTERN int origcpuid; /* Assembler instruction limit flag */ #endif /* miscellaneous */ extern char hexdigit[]; /* cpuid functions */ #ifdef I80386 #ifndef __AS386_16__ #define iscpu(x) (cpuid>=(x)) #define needcpu(x) do{ if(cpuid<(x)) {warning(CPUCLASH); cpuid|=0x10;} }while(0) #define setcpu(x) (cpuid=(x)) #define cpuwarn() (cpuid&=0xF) #endif #endif #ifndef setcpu #define needcpu(x) #define setcpu(x) #define cpuwarn() #endif dev86-0.16.17/as/proto.h0000644000000000000000000001222207315312147014501 0ustar rootroot00000000000000/* extern functions */ /* as.c */ int main P((int argc, char **argv)); void as_abort P((char *message)); void finishup P((void)); void initp1p2 P((void)); void line_zero P((void)); /* assemble.c */ void assemble P((void)); /* express.c */ void absexpres P((void)); void chkabs P((void)); void nonimpexpres P((void)); void showrelbad P((void)); void symabsexpres P((void)); void symexpres P((void)); void expres P((void)); void factor P((void)); void scompare P((void)); /* genbin.c */ void binheader P((void)); void bintrailer P((void)); void genbin P((void)); void initbin P((void)); void putbin P((int ch)); /* genlist.c */ char *build_2hex_number P((unsigned num, char *where)); char *build_number P((unsigned num, unsigned width, char *where)); void warning P((char * errorstr)); void error P((char * errorstr)); void listline P((void)); void writec P((int ch)); void writenl P((void)); void writeoff P((offset_t offset)); void writes P((char *s)); void writesn P((char *s)); void writew P((unsigned word)); /* genobj.c */ void accumulate_rmb P((offset_t offset)); void flushobj P((void)); void genobj P((void)); void initobj P((void)); void objheader P((void)); void objtrailer P((void)); void putabs P((opcode_pt ch)); void putobj P((opcode_pt ch)); /* gensym.c */ void gensym P((void)); /* macro.c */ void entermac P((struct sym_s *symptr)); void pmacro P((void)); /* mops.c */ #ifdef I80386 void mbcc P((void)); void mbswap P((void)); void mcall P((void)); void mcalli P((void)); void mdivmul P((void)); void menter P((void)); void mEwGw P((void)); void mExGx P((void)); void mf_inher P((void)); void mf_m P((void)); void mf_m2 P((void)); void mf_m2_ax P((void)); void mf_m2_m4 P((void)); void mf_m2_m4_m8 P((void)); void mf_m4_m8_optst P((void)); void mf_m4_m8_st P((void)); void mf_m4_m8_stst P((void)); void mf_m4_m8_m10_st P((void)); void mf_m10 P((void)); void mf_optst P((void)); void mf_st P((void)); void mf_stst P((void)); void mf_w_inher P((void)); void mf_w_m P((void)); void mf_w_m2 P((void)); void mf_w_m2_ax P((void)); void mgroup1 P((void)); void mgroup2 P((void)); void mgroup6 P((void)); void mgroup7 P((void)); void mgroup8 P((void)); void mGvEv P((void)); void mGvMa P((void)); void mGvMp P((void)); void mimul P((void)); void min P((void)); void mincdec P((void)); void minher P((void)); void minher16 P((void)); void minher32 P((void)); void minhera P((void)); void mint P((void)); void mjcc P((void)); void mjcxz P((void)); void mlea P((void)); void mmov P((void)); void mmovx P((void)); void mnegnot P((void)); void mout P((void)); void mpushpop P((void)); void mret P((void)); void mseg P((void)); void msetcc P((void)); void mshdouble P((void)); void mtest P((void)); void mxchg P((void)); #endif /* I80386 */ #ifdef MC6809 void mall P((void)); void malter P((void)); void mimmed P((void)); void mindex P((void)); void minher P((void)); void mlong P((void)); void msstak P((void)); void mswap P((void)); void mustak P((void)); #endif /* MC6809 */ void getcomma P((void)); void mshort P((void)); /* pops.c */ bool_pt checksegrel P((struct sym_s *symptr)); void checkdatabounds P((void)); void datatoobig P((void)); void fatalerror P((char * errorstr)); void labelerror P((char * errorstr)); void palign P((void)); void pasciz P((void)); void pblkw P((void)); void pblock P((void)); void pbss P((void)); void pcomm P((void)); void pcomm1 P((void)); void pdata P((void)); void pelse P((void)); void pelseif P((void)); void pelsifc P((void)); void pendb P((void)); void pendif P((void)); void penter P((void)); void pentry P((void)); void pequ P((void)); void peven P((void)); void pexport P((void)); void pfail P((void)); void pfcb P((void)); void pfcc P((void)); void pfdb P((void)); #if SIZEOF_OFFSET_T > 2 void pfqb P((void)); #endif void pglobl P((void)); void pident P((void)); void pif P((void)); void pifc P((void)); void pimport P((void)); void plcomm P((void)); void plcomm1 P((void)); void plist P((void)); void pnolist P((void)); void ploc P((void)); void pmaclist P((void)); void pmap P((void)); void porg P((void)); void prmb P((void)); void psect P((void)); void pset P((void)); void psetdp P((void)); void ptext P((void)); void puse16 P((void)); void puse32 P((void)); void pwarn P((void)); void showlabel P((void)); /* readsrc.c */ void initsource P((void)); fd_t open_input P((char *name)); void pget P((void)); void pproceof P((void)); void readline P((void)); void skipline P((void)); /* scan.c */ void context_hexconst P((void)); void getsym P((void)); void getsym_nolookup P((void)); void initscan P((void)); /* table.c */ void inst_keywords P((void)); struct sym_s *lookup P((void)); void statistics P((void)); /* type.c */ u2_pt c2u2 P((char *buf)); u4_t c4u4 P((char *buf)); u2_pt cnu2 P((char *buf, unsigned count)); u4_t cnu4 P((char *buf, unsigned count)); void u2c2 P((char *buf, u16_pt offset)); void u4c4 P((char *buf, u32_T offset)); void u2cn P((char *buf, u16_pt offset, unsigned count)); void u4cn P((char *buf, u32_T offset, unsigned count)); bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); /* alloc.c */ void * asalloc P((unsigned int size)); void * asrealloc P((void * oldptr, unsigned int size)); void * temp_buf P((void)); void init_heap P((void)); dev86-0.16.17/as/address.h0000644000000000000000000000150304470126734014767 0ustar rootroot00000000000000/* address.h - global variables involving addresses for assembler */ EXTERN struct address_s lastexp;/* last expression parsed */ EXTERN union { char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */ /* data is absolute in 1 char pieces */ /* limited by FCC\t"" etc on line */ struct address_s fdbuf[(LINLEN - 4) / 2]; /* buffer for fdb data */ /* data can be of any 2-byte adr type */ /* limited by FDB\t and commas on line */ #if SIZEOF_OFFSET_T > 2 struct address_s fqbuf[(LINLEN - 4) / 4]; /* buffer for fqb data */ /* data can be of any 4-byte adr type */ /* limited by FQB\t and commas on line */ #endif } databuf; EXTERN bool_t fcflag; EXTERN bool_t fdflag; #if SIZEOF_OFFSET_T > 2 EXTERN bool_t fqflag; #endif EXTERN struct address_s immadr; EXTERN smallcount_t immcount; dev86-0.16.17/as/bin/0000755000000000000000000000000006565147600013744 5ustar rootroot00000000000000dev86-0.16.17/as/bin/inout.bin0000644000000000000000000000006605060271416015566 0ustar rootroot00000000000000,íììfífííä äfå fåå åïîîfïfïïæ æfç fçeç çÿdev86-0.16.17/as/bin/group1.bin0000644000000000000000000000016305060271413015640 0ustar rootroot00000000000000if4xV4€ÃfÃ4ÃxV4g€g€Gg€gf4gxV4g€gfƒýgƒýÙfÙÙggfgggfgÙ Ù8ÙÙ(ÙÙ0Ùÿdev86-0.16.17/as/bin/calljmp.bin0000644000000000000000000000022205061127502016041 0ustar rootroot00000000000000ˆš è|fÿÐfÿÓfÿÑfÿÒfÿÔfÿÕfÿÖfÿ×gÿgÿgfÿèUfÿÐfÿÓfÿÑfÿÒfÿÔfÿÕfÿÖfÿ×fÿê ë3ÿàÿãÿáÿâÿäÿåÿæÿçÿ'ÿ'ÿ'ëfÿàfÿãfÿáfÿâfÿäfÿåfÿæfÿçfÿ'ÿdev86-0.16.17/as/bin/each.bin0000644000000000000000000000122105061123311015311 0ustar rootroot00000000000000‡7Õ Ô ?fµfµf#µcµfbµf¼µf½µËf£µf»µf³µf«µÿµf˜˜øüúõf;µ¦f§§f§µf™™'/ÿ µ÷4µÈô÷<µ÷,µä ÿµlfmmÍ Î<µfÏÏuÿ$µŸfµfµÉµµfŵfĵf´µfµµf²µµ4µð¬f­­âfµµf‹µf‹µ"À¤f¥¥f¾µf¶µ÷$µ÷µ÷µf µæ nfooµfaafÿ4µf``fœœÑµÑµÑµÑ µóóóòòÃËžÑ$µÑ<µÑ$µÑ,µfµ®f¯¯•µµ µf¤µf¬µµ$µùýûªf«« µf+µf…µ$µ,µ› fÁµf‡µ×f3µÿdev86-0.16.17/as/bin/xchg.bin0000644000000000000000000000035205060271421015353 0ustar rootroot00000000000000àff“f‘f’f”f•f–f—ff“f‘f’f”f•f–f—“‘’”•–—“‘’”•–—†À†à†Ø†ø†Ë†ë†Ó†óg†g†'g†g†?g†g†/g†g†7g†g†'g†g†?g†g†/g†g†7gf‡gf‡gf‡gf‡gf‡'gf‡/gf‡7gf‡?gf‡gf‡gf‡gf‡gf‡'gf‡/gf‡7gf‡?g‡g‡g‡g‡g‡'g‡/g‡7g‡?f‡f‡f‡ f‡f‡#f‡+f‡3f‡;ÿdev86-0.16.17/as/bin/shdouble.bin0000644000000000000000000000007505060271420016230 0ustar rootroot000000000000003f¤Øf¤Ë¤òf¥Ù¤Ögf¤g¤gf¥g¥f¬Ëf­Ùÿdev86-0.16.17/as/bin/fadd.bin0000644000000000000000000000113505060271413015321 0ustar rootroot00000000000000SfUf‰åg‹Fg‹Vg‹^ g‹Nè£O‰Sf]Ãñ€UWV‰Ï‰Öæÿÿÿçÿÿÿ9þw r9Øs‡Ê‡þ“æÿÿçÿÿÎÏÁéÁê‰Íf)Ñf÷Ùfƒù7s2f1Õfåu*€ù s*­Ý­ûÓïØþ)Ûf‰Ñfáÿ÷Æ té{ëbéÀé‹é¬÷½ÿtòfƒïf÷ßfQf‰ù¥Æ¥è¥ÝÓãfYf)ùr;ý€w r…Ûu¨tƒÀƒÖ)í)Û÷Æ ufâf ÊÁâæÿÿ ò^_]Ã)Ò‰Ð^_]ÃÑîÑØÑÝÑÛfAfùu¬ºàÿ)À^_]Àé ­Ý­ûÓïøƒÖ‡Ýé=ÿÿÿ¤Æ¤è¤ÝÁã€ér±éJÿÿÿ)í€ù s­Ý­ûÓï÷ÝØþ)Ûf‰Ñfáÿé&ÿÿÿ€é ­Ý­ûÓï÷Û÷݃ÛøƒÞ‡Ýf‰Ñfáÿéÿÿÿé]ÿÿÿëþéVÿÿÿUWV‰Ö‰ÏÁêÁéf‰Õf1ÍfåfâÿtÕfáÿtÎfÑférËfùÿwÂæÿÿçÿÿÎÏfQfU‰Á÷ã‰Õ“÷æPR‰ð÷ç‰Ö‘÷çÅXЃÖZÕȃÖfZfYfƒÁ épþÿÿÿdev86-0.16.17/as/bin/imul.bin0000644000000000000000000000016705060271414015376 0ustar rootroot00000000000000möëö.f÷ëf÷.÷ë÷.f¯Ãf¯¯Ã¯fkÃfkkÃkgf¯g¯fkÀkÀfiÃ,fi,iÃà“ià“gf¯,¯à“fiÀ,iÀà“ÿdev86-0.16.17/as/bin/seg.bin0000644000000000000000000000002005060271417015175 0ustar rootroot00000000000000.>&de6ÿdev86-0.16.17/as/bin/f.bin0000644000000000000000000000026505060271413014653 0ustar rootroot00000000000000«ÜØØÁÜÁÜ3Ø3ØñÞÁß#ß3ØÜØÑØÑÝÁÝáÝáÞÚßÛß+ÙÝÛ+ÙÁÙ+Ù;Ù#Ý3Ù3Ý#Ý;ßàÙÝÝÑ›Ù;›Ý;›ßà›Ý3›Ù3ÙÐÙàÙáÙäÙåÙèÙéÙêÙëÙìÙíÙîÙðÙñÙòÙóÙôÙõÙöÙ÷ÙøÙùÙúÙûÙüÙýÙþÙÿÚé›ÛàÛà›ÛáÛá›ÛâÛâ›ÛãÛãÛäÞÙÿdev86-0.16.17/as/bin/farcall.bin0000644000000000000000000000005105060271413016023 0ustar rootroot00000000000000šgÿgÿêÿ.gÿ.ÿdev86-0.16.17/as/bin/group7.bin0000644000000000000000000000006505060271414015650 0ustar rootroot00000000000000+gggg?gF ðg70ãÿdev86-0.16.17/as/bin/pushpop.bin0000644000000000000000000000020005060271417016115 0ustar rootroot00000000000000vjgÿ7fjÿfPfSfQfRfTfUfVfWffff f¨fh4fh4gfÿ7PSQRTUVWhxV4hxV4gÿ7gfXf[fYfZf\f]f^f_fff¡f©fgfX[YZ\]^_gÿdev86-0.16.17/as/bin/shift.bin0000644000000000000000000000042405060271420015536 0ustar rootroot00000000000000 ÒÐÒÔÒÓÒ×ÒÑÒÕÒÒÒÖgÓgÒfÓÐfÓÓfÓÑfÓÒfÓÔfÓÕfÓÖfÓ×gfÓÓÐÓÓÓÑÓÒÓÔÓÕÓÖÓ×gÓÐÐÐÔÐÓÐ×ÐÑÐÕÐÒÐÖgÑgÐfÑÐfÑÓfÑÑfÑÒfÑÔfÑÕfÑÖfÑ×gfÑÑÐÑÓÑÑÑÒÑÔÑÕÑÖÑ×gÑÀÐÀÔÀÓÀ×ÀÑÀÕÀÒÀÖgÁgÀÀÐfÁÐfÁÓfÁÑfÁÒfÁÔfÁÕfÁÖfÁ×gfÁÁÐÁÓÁÑÁÒÁÔÁÕÁÖÁ×gÁfÁØfÁÀfÁÈfÁàfÁøfÁàfÁèÿdev86-0.16.17/as/bin/movspec.bin0000644000000000000000000000125205060271416016102 0ustar rootroot00000000000000  À Ð Ø!À!È!Ð!Ø!ð!ø$Ø$à$è$ð$ø"À"Ð"Ø#À#È#Ð#Ø#ð#ø&Ø&à&è&ð&ø Ã Ó Û!Ã!Ë!Ó!Û!ó!û$Û$ã$ë$ó$û"Ã"Ó"Û#Ã#Ë#Ó#Û#ó#û&Û&ã&ë&ó&û Á Ñ Ù!Á!É!Ñ!Ù!ñ!ù$Ù$á$é$ñ$ù"Á"Ñ"Ù#Á#É#Ñ#Ù#ñ#ù&Ù&á&é&ñ&ù Â Ò Ú!Â!Ê!Ò!Ú!ò!ú$Ú$â$ê$ò$ú"Â"Ò"Ú#Â#Ê#Ò#Ú#ò#ú&Ú&â&ê&ò&ú Æ Ö Þ!Æ!Î!Ö!Þ!ö!þ$Þ$æ$î$ö$þ"Æ"Ö"Þ#Æ#Î#Ö#Þ#ö#þ&Þ&æ&î&ö&þ Ç × ß!Ç!Ï!×!ß!÷!ÿ$ß$ç$ï$÷$ÿ"Ç"×"ß#Ç#Ï#×#ß#÷#ÿ&ß&ç&ï&÷&ÿ Ä Ô Ü!Ä!Ì!Ô!Ü!ô!ü$Ü$ä$ì$ô$ü"Ä"Ô"Ü#Ä#Ì#Ô#Ü#ô#ü&Ü&ä&ì&ô&ü Å Õ Ý!Å!Í!Õ!Ý!õ!ý$Ý$å$í$õ$ý"Å"Õ"Ý#Å#Í#Õ#Ý#õ#ý&Ý&å&í&õ&ýÿdev86-0.16.17/as/bin/ea.bin0000644000000000000000000000067105060271412015013 0ustar rootroot00000000000000¯gf‹gf‹gf‹gf‹gf‹gf‹gf¡4gf‹gf‹@gf‹Agf‹Bgf‹Cgf‹Dgf‹Egf‹Fgf‹Ggf‹€4gf‹4gf‹‚4gf‹ƒ4gf‹„4gf‹…4gf‹†4gf‹‡4ˆÀˆàˆØˆøˆÈˆèˆÐˆðf‰Àf‰Èf‰Ðf‰Øf‰àf‰èf‰ðf‰øf‹f‹f‹f‹f¡xV4f‹f‹f‹@f‹Af‹Bf‹Cf‹Ef‹Ff‹Gf‹€xV4f‹xV4f‹‚xV4f‹ƒxV4f‹…xV4f‹†xV4f‹‡xV4‰À‰È‰Ð‰Ø‰à‰è‰ð‰øf‹pf‹qf‹rf‹sf‹tf‹uxV4f‹vf‹wf‹Dpf‹Dqf‹Drf‹Dsf‹Dtf‹D$f‹Duf‹Dvf‹Dwf‹„pxV4f‹„qxV4f‹„rxV4f‹„sxV4f‹„txV4f‹„$xV4f‹„uxV4f‹„vxV4f‹„wxV4ÿdev86-0.16.17/as/bin/group6.bin0000644000000000000000000000004605060271413015645 0ustar rootroot00000000000000ÐgÛgF ág,ÿdev86-0.16.17/as/bin/inher.bin0000644000000000000000000000020105060271416015524 0ustar rootroot00000000000000w7?øüúõ¦'/ôÎlŸÉð¬¤nóóòž®ùýûª›˜™f˜f™§f§mfmÏfÏ­f­¥f¥ofoafaf`f`œfœ¯f¯««××f˜f™˜™f§§fmmfÏÏf­­f¥¥foofaaff``fœœf¯¯f«f«××ÿdev86-0.16.17/as/bin/incdec.bin0000644000000000000000000000016405060271416015654 0ustar rootroot00000000000000jþÀþÄþÃþÇþÁþÅþÂþÆgÿgþf@fCfAfBfDfEfFfGgfÿ@CABDEFGgÿþÈþÌþËþÏþÉþÍþÊþÎgÿgþfHfKfIfJfLfMfNfOgfÿHKIJLMNOgÿÿdev86-0.16.17/as/readsrc.c0000644000000000000000000002532210065347101014753 0ustar rootroot00000000000000/* readsrc.c - read source files for assembler */ #include "syshead.h" #include "const.h" #include "type.h" #include "flag.h" #include "file.h" #include "globvar.h" #include "macro.h" #include "scan.h" #undef EXTERN #define EXTERN #include "source.h" /* * Ok, lots of hack & slash here. * 1) Added BIG buffer to load entire _primary_ file into memory. * 2) This means the primary file can be standard input. * 3) Fixed so 'get/include' processing now works. * 4) Altered for a 'normal' style buffer otherwise (MINIBUF) * 5) Have the option of completely unbuffered if you need the last Kb. * * RDB. */ #ifndef __AS386_16__ #ifndef BIGBUFFER #define BIGBUFFER 1 /* For most machines we have the memory */ #endif #endif #ifdef MSDOS #define off_t long /* Not a typedef! */ #endif #ifndef MINIBUF #define MINIBUF 1 /* Add in a reasonable buffer */ #endif struct get_s /* to record included files */ { fd_t fd; unsigned line; off_t position; }; PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */ PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */ PRIVATE struct get_s *getstak; /* ptr */ #if BIGBUFFER == 1 PRIVATE char *mem_start = 0, *mem_end; #endif PRIVATE char hid_linebuf[LINLEN]; /* line buffer */ PRIVATE char *eol_ptr; PRIVATE char *maclinebuf; PRIVATE char *maclineptr; #if MINIBUF == 1 PRIVATE void inp_seek P((int fd, long posn)); PRIVATE long inp_tell P((int fd)); PRIVATE int inp_line P((int fd, char * buf, int size)); #endif FORWARD void clearsource P((void)); FORWARD void line_too_long P((void)); PRIVATE void clearsource() { } PRIVATE void line_too_long() { symname = linebuf + (LINLEN - 1); /* spot for the error */ error(LINLONG); /* so error is shown in column LINLEN - 1 */ } /* initialise private variables */ PUBLIC void initsource() { filnamptr = hid_filnambuf; getstak = hid_getstak; clearsource(); /* sentinel to invoke blank skipping */ } PUBLIC fd_t open_input(name) char *name; { fd_t fd; #if BIGBUFFER == 1 off_t filelength = -1; if( mem_start == 0 && strcmp(name, "-") == 0 ) fd = 0; else #endif #ifdef O_BINARY if ((unsigned) (fd = open(name, O_RDONLY|O_BINARY)) > 255) as_abort("error opening input file"); #else if ((unsigned) (fd = open(name, O_RDONLY)) > 255) as_abort("error opening input file"); #endif #if BIGBUFFER == 1 if( mem_start == 0 ) { size_t memsize = 0; int cc; if(fd) { struct stat st; if( fstat(fd, &st) >= 0 ) filelength = st.st_size; if( filelength > (((unsigned)-1)>>1)-3 ) { mem_end = mem_start = "\n\n"; goto cant_do_this; } } if (filelength > 0) { if( (mem_start = malloc(filelength+4)) == 0 ) { mem_end = mem_start = "\n\n"; goto cant_do_this; } memsize = filelength; filelength = read(fd, mem_start, filelength); } else filelength = 0; for(;;) { if( filelength >= memsize ) { if (memsize > 16000) mem_start = asrealloc(mem_start, (memsize+=16384)+4); else mem_start = asrealloc(mem_start, (memsize+=memsize+32)+4); } cc = read(fd, mem_start+filelength, (size_t)(memsize-filelength)); if( cc <= 0 ) break; filelength+=cc; } *(mem_end=mem_start+filelength) = '\n'; mem_end[1] = '\0'; infiln = infil0 = 0; /* Assemble from memory */ if(fd) close(fd); fd = -1; } cant_do_this: #endif clearsource(); return fd; } /* handle GET pseudo_op stack state of current file, open new file and reset global state vars file must be seekable for the buffer discard/restore method to work */ PUBLIC void pget() { if (infiln >= MAXGET) error(GETOV); else { char save; skipline(); listline(); getstak->fd = infil; getstak->line = linum; if (infiln != 0) #if MINIBUF == 1 getstak->position = inp_tell(infil); #else getstak->position = lseek(infil, 0L, 1); #endif else getstak->position = (off_t)eol_ptr; ++getstak; ++infiln; linum = 0; for(lineptr=symname; *lineptr != EOLCHAR; lineptr++) if( *lineptr <= ' ' ) break; save = *lineptr; *lineptr = '\0'; infil = open_input(symname); *lineptr = save; getsym(); } } /* process end of file */ /* close file, unstack old file if current one is included */ /* otherwise switch pass 0 to pass 1 or exit on pass 2 */ /* end of file may be from phyical end of file or an END statement */ PUBLIC void pproceof() { if (infiln != 0) close(infil); if (infiln == infil0) /* all conditionals must be closed before end of main file (not GETs) */ { if (blocklevel != 0) error(EOFBLOCK); if (iflevel != 0) error(EOFIF); if (pass && (lcdata & UNDBIT)) error(EOFLC); lcptr->data = lcdata; lcptr->lc = lc; } /* macros must be closed before end of all files */ if (macload) error(EOFMAC); if (linebuf != lineptr) listline(); /* last line or line after last if error */ if (infiln != infil0) { --getstak; infil = getstak->fd; linum = getstak->line; if (--infiln == 0) eol_ptr = (void*)getstak->position; else #if MINIBUF == 1 inp_seek(infil, getstak->position); #else lseek(infil, getstak->position, 0); #endif } else if (pass!=last_pass) { pass++; if( last_pass>1 && last_pass<30 && dirty_pass && pass==last_pass ) last_pass++; if( pass==last_pass ) objheader(); /* while pass 1 data all valid */ binmbuf = 0; /* reset zero variables */ maclevel = iflevel = blocklevel = totwarn = toterr = linum = macnum = 0; initp1p2(); /* reset other varaiables */ if(pass==last_pass) binaryc = binaryg; #ifdef I80386 defsize = idefsize; cpuid = origcpuid; #endif if(pass==last_pass) { list.current = list.global; maclist.current = maclist.global; as_warn.current = TRUE; if (as_warn.semaphore < 0) as_warn.current = FALSE; } if (infiln != 0) infil = open_input(filnamptr); else eol_ptr=0; if(pass==last_pass) binheader(); line_zero(); } else finishup(); } /* read 1 line of source. Source line ends with '\n', line returned is null terminated without '\n'. Control characters other than blank, tab and newline are discarded. Long lines (length > LINLEN) are truncated, and an error is generated. On EOF, calls pproceof(), and gets next line unless loading a macro. This is where macro lines are recursively expanded. */ PUBLIC void readline() { int cc = 0; listpre = FALSE; /* not listed yet */ if (maclevel != 0) { register char *bufptr; /* hold *bufptr in a reg char variable */ register char *reglineptr; /* if possible (not done here) */ char *oldbufptr; struct schain_s *parameters; char paramnum; unsigned int remaining; /* space remaining in line + 2 */ /* value 0 not used except for temp predec */ /* value 1 means error already gen */ /* values 1 and 2 mean no space */ for (; maclevel != 0; macpar = macstak->parameters, ++macstak, --maclevel) if (*(bufptr = macstak->text) != ETB) /* nonempty macro, process it and return without continuing the for loop */ { if (!macflag) { maclinebuf = linebuf; maclineptr = lineptr; macflag = TRUE; } remaining = LINLEN + 2; lineptr = linebuf = reglineptr = hid_linebuf; while (*bufptr++ != EOLCHAR) { if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9') { parameters = macstak->parameters; for (paramnum = *bufptr++; paramnum-- != '0';) if ((parameters = parameters->next) == NUL_PTR) break; if (parameters != NUL_PTR) { for (oldbufptr = bufptr, bufptr = parameters->string; *bufptr++ != 0;) { if (--remaining <= 1) { if (remaining != 0) line_too_long(); remaining = 1; break; /* forget rest, param on 1 line */ } *reglineptr++ = bufptr[-1]; } bufptr = oldbufptr; } } else { if (--remaining <= 1) { if (remaining != 0) line_too_long(); remaining = 1; } else *reglineptr++ = bufptr[-1]; } } macstak->text = bufptr; #if 0 *reglineptr = 0; printf("MLINE:%s.\n", lineptr); #endif *reglineptr = EOLCHAR; return; } } if (macflag) { linebuf = maclinebuf; lineptr = maclineptr; macflag = FALSE; } /* End of macro expansion processing */ again: /* On EOF for main or included files */ ++linum; #if BIGBUFFER == 1 if( infiln == 0 ) { if( eol_ptr == 0 ) eol_ptr = mem_start-1; else *eol_ptr = '\n'; linebuf = lineptr = eol_ptr + 1; cc = (mem_end - linebuf); /* memchr not strchr 'cause some implementations of strchr are like: memchr(x,y,strlen(x)); this is _BAD_ with BIGBUFFER */ if((eol_ptr = memchr(linebuf, '\n', cc)) == 0 && cc > 0) cc = -1; } else #endif { lineptr = linebuf = hid_linebuf; *(hid_linebuf+sizeof(hid_linebuf)-2) = '\0'; /* Term */ #if MINIBUF == 1 cc = inp_line(infil, linebuf, sizeof(hid_linebuf)-2); if( cc >= 0 ) eol_ptr = linebuf+cc-1; #else cc = read(infil, linebuf, sizeof(hid_linebuf)-2); if( cc > 0 ) { eol_ptr = memchr(linebuf, '\n', cc); if( eol_ptr == 0 ) eol_ptr = hid_linebuf+sizeof(hid_linebuf)-2; else lseek(infil, (long)(eol_ptr+1-hid_linebuf)-cc, 1); } #endif } if( cc <= 0 ) { if( cc < 0 ) as_abort("error reading input"); clearsource(); pproceof(); listpre = FALSE; if (macload) { symname = lineptr; return; /* macro not allowed across eof */ } goto again; } #if 0 *eol_ptr = 0; printf("LINE:%s.\n", lineptr); #endif *eol_ptr = EOLCHAR; } PUBLIC void skipline() { if(macflag) lineptr = strchr(hid_linebuf, EOLCHAR); else lineptr = eol_ptr; } #if MINIBUF == 1 PRIVATE char input_buf[1024]; /* input buffer */ PRIVATE int in_start=0, in_end=0; PRIVATE long ftpos = 0; PRIVATE int lastfd = -1; PRIVATE int inp_line(fd, buf, size) int fd; char * buf; int size; { int offt = 0; if( fd!=lastfd ) inp_seek(-1, 0L); for(;;) { if(in_start >= in_end) { lastfd = -1; ftpos = lseek(fd, 0L, 1); in_start = 0; in_end = read(fd, input_buf, sizeof(input_buf)); if( in_end <=0 ) return in_end; lastfd = fd; } if( (buf[offt++] = input_buf[in_start++]) == '\n' || offt >= size ) break; } return offt; } PRIVATE long inp_tell(fd) int fd; { if( fd != lastfd ) return lseek(fd, 0L, 1); else return ftpos + in_start; } PRIVATE void inp_seek(fd, posn) int fd; long posn; { if( lastfd != -1 ) lseek(lastfd, ftpos+in_start, 0); lastfd = -1; in_end = 0; if( fd >= 0 ) lseek(fd, posn, 0); } #endif dev86-0.16.17/bcc/0000755000000000000000000000000010174732447013320 5ustar rootroot00000000000000dev86-0.16.17/bcc/align.h0000644000000000000000000000063506456134232014563 0ustar rootroot00000000000000/* align.h - memory alignment requirements for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifndef S_ALIGNMENT # define align(x) (x) #else # if defined(__STDC__) && defined(_POSIX_SOURCE) # define align(x) (((ssize_t) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1)) # else # define align(x) ((char *) (x) + (- (char) (x) & (S_ALIGNMENT-1))) # endif #endif extern uoffset_T alignmask; /* general alignment mask */ dev86-0.16.17/bcc/type.h0000644000000000000000000000502607517066051014453 0ustar rootroot00000000000000/* type.h - types for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* A type is essentially a "constructor", a size, and a list of pointers leading to a scalar type. The type constructors are codes for the scalar types and (), [], *, struct and union. The scalar types are char, short, int, long, float and double. The type lists are triply linked. Part of the type structure might look like int (int) = func <-------> int (int ()) | = --> ptr <--> int (int *) (the exact structure depends on the order of declarations). This layout results from the pre-declared (int) and (int ()) followed by a declaration using (int *). The sideways link (from func to ptr here) allows all types leading to a given type to be found. This allows different declarations of (int *) to be recognised as the same. Type equivalence is equality of type pointers. */ /* flags for scalar types up to 3 of the flags may be set (none for constructed types) the 2nd and third flags can only be UNSIGNED or DLONG UNSIGNED only applies to integral types DLONG only applies to long and unsigned long types and says that these are actually longer than an int */ #define CHAR 0x01 #define SHORT 0x02 #define INT 0x04 #define LONG 0x08 #define FLOAT 0x10 #define DOUBLE 0x20 #define UNSIGNED 0x40 #define DLONG 0x80 #define ISCALAR (CHAR | SHORT | INT | LONG) #define RSCALAR (FLOAT | DOUBLE) /* flags for type constructor at most 1 of the flags may be set (none for scalar types) flags are used for fast testing for array/pointer */ #define ARRAY 1 #define FUNCTION 2 #define POINTER 4 #define STRUCTU 8 #define VOID 0x10 /* type sizes */ /* default sizes and long and float sizes are hard-coded into type data */ extern uoffset_T ctypesize; extern uoffset_T dtypesize; extern uoffset_T ftypesize; extern uoffset_T itypesize; extern uoffset_T ptypesize; extern uoffset_T stypesize; /* basic scalar types */ EXTERN struct typestruct *dtype; EXTERN struct typestruct *fltype; EXTERN struct typestruct *itype; EXTERN struct typestruct *ltype; EXTERN struct typestruct *sctype; EXTERN struct typestruct *stype; EXTERN struct typestruct *uctype; EXTERN struct typestruct *uitype; EXTERN struct typestruct *ultype; EXTERN struct typestruct *ustype; EXTERN struct typestruct *vtype; /* working type */ EXTERN struct typestruct *ctype; /* constructed types */ EXTERN struct typestruct *fitype; EXTERN struct typestruct *pctype; /* return type of current function */ EXTERN struct typestruct *returntype; dev86-0.16.17/bcc/hashcmd.c0000644000000000000000000000701210065227165015066 0ustar rootroot00000000000000 /* decode remaining preprocessor lines, minimal version. */ /* Copyright (C) GPL V2, derived from preproc.c by RDB. */ #include "bcc.h" #include "input.h" #include "os.h" #include "output.h" #include "parse.h" #include "sc.h" #include "scan.h" #include "table.h" #include "type.h" #ifndef BUILTIN_CPP FORWARD void control P((void)); FORWARD void asmcontrol P((void)); FORWARD void warningcntl P((void)); FORWARD void errorcntl P((void)); /* docontrol() - process control statement, #line and #asm only. */ PUBLIC void docontrol() { control(); skipline(); return; } /* control() - select and switch to control statement */ PRIVATE void control() { char sname[NAMESIZE + 1]; sym_t ctlcase; struct symstruct *symptr; if (ctext && asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } sname[0] = '#'; /* prepare for bad control */ sname[1] = 0; if (blanksident()) strcat(sname, gsname); if (sname[1] == 0 && ch == EOL) return; if (SYMOFCHAR(ch) == INTCONST) { linecontol(); return; } if ((symptr = findlorg(sname)) == NULL) { error(" bad control"); return; } ctlcase = symptr->offset.offsym; switch (ctlcase) { case ASMCNTL: if (asmmode) error(" bad control"); else asmcontrol(); break; case ENDASMCNTL: if (!asmmode) error(" bad control"); asmmode = FALSE; break; case LINECNTL: { linecontol(); break; } case WARNINGCNTL: warningcntl(); break; case ERRORCNTL: errorcntl(); break; default: error(" bad control"); break; } } /* asmcontrol() - process #asm */ PRIVATE void asmcontrol() { #ifdef ASM_BARE char treasure; /* to save at least one leading blank */ #endif asmmode = TRUE; if (expect_statement) return; outnstr("!BCC_ASM"); dumplocs(); #ifndef ASM_BARE cppscan(1); #else while (TRUE) { skipline(); skipeol(); if (eofile) { eofin("#asm"); break; } if (SYMOFCHAR(ch) == SPECIALCHAR) specialchar(); treasure = 0; if (SYMOFCHAR(ch) == WHITESPACE) treasure = ch; blanks(); if (ch == '#') { if (ctext) { register char *lptr; comment(); if (treasure != 0) outbyte(treasure); lptr = lineptr; while (*lptr++ != EOL) /* XXX - handle COEOL too */ outbyte(ch); outnl(); } gch1(); docontrol(); if (!asmmode) break; } else { if (treasure != 0) outbyte(treasure); while (ch != EOL) /* XXX - handle COEOL too */ { outbyte(ch); gch1(); } outnl(); } } #endif outnstr("!BCC_ENDASM"); } /* warningcntl() - process #warning */ PRIVATE void warningcntl() { char estr[256], *ep = estr; *ep++ = '%'; *ep++ = 'w'; while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; error(estr); } /* errorcntl() - process #error */ PRIVATE void errorcntl() { char estr[256], *ep = estr; while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; error(estr); } /* skipline() - skip rest of line */ PUBLIC void skipline() { while (TRUE) { blanks(); if (ch == EOL) return; if (ch == '\\') { gch1(); if (ch == EOL) /* XXX - I think blanks() eats \EOL */ return; gch1(); /* XXX - escape() better? */ } else if (ch == '"' || ch == '\'') { stringorcharconst(); charptr = constant.value.s; } else gch1(); } } #endif dev86-0.16.17/bcc/table.h0000644000000000000000000000373505301213542014552 0ustar rootroot00000000000000/* table.h - table handler for bcc */ /* Copyright (C) 1992 Bruce Evans */ EXTERN char *charptr; /* next free spot in catchall table */ EXTERN char *chartop; /* spot after last in table */ EXTERN char *char1top; /* last character spot in table */ EXTERN char *char3top; /* third last character spot in table */ EXTERN struct symstruct *exprptr; /* next entry in expression symbol table */ EXTERN struct symstruct *locptr; /* next entry in local symbol table */ extern struct symstruct locsyms[]; /* local symbol table */ #define TS1 #ifdef TS uvalue_t ts_n_newtypelist; uvalue_t ts_s_newtypelist; uvalue_t ts_n_filename_term; uvalue_t ts_s_filename_term; uvalue_t ts_n_filename; uvalue_t ts_s_filename; uvalue_t ts_s_filename_tot; uvalue_t ts_n_pathname; uvalue_t ts_s_pathname; uvalue_t ts_s_pathname_tot; uvalue_t ts_n_inputbuf; uvalue_t ts_s_inputbuf; uvalue_t ts_s_inputbuf_tot; uvalue_t ts_n_includelist; uvalue_t ts_s_includelist; uvalue_t ts_s_outputbuf; uvalue_t ts_n_macstring_ident; uvalue_t ts_n_macstring_ordinary; uvalue_t ts_n_macstring_param; uvalue_t ts_n_macstring_quoted; uvalue_t ts_n_macstring_term; uvalue_t ts_s_macstring; uvalue_t ts_n_defines; uvalue_t ts_s_defines; uvalue_t ts_n_macparam; uvalue_t ts_s_macparam; uvalue_t ts_s_macparam_tot; uvalue_t ts_n_macparam_string_ordinary; uvalue_t ts_n_macparam_string_quoted; uvalue_t ts_n_macparam_string_term; uvalue_t ts_s_macparam_string; uvalue_t ts_s_macparam_string_tot; uvalue_t ts_s_macparam_string_alloced; uvalue_t ts_s_macparam_string_alloced_tot; uvalue_t ts_s_fakeline; uvalue_t ts_s_fakeline_tot; uvalue_t ts_n_string; uvalue_t ts_n_case; uvalue_t ts_n_case_realloc; uvalue_t ts_s_case; uvalue_t ts_s_case_tot; uvalue_t ts_n_structname; uvalue_t ts_s_structname; uvalue_t ts_n_type; uvalue_t ts_s_type; uvalue_t ts_n_global; uvalue_t ts_size_global; uvalue_t ts_n_holdstr; uvalue_t ts_size_holdstr; uvalue_t ts_n_growobj; uvalue_t ts_size_growobj_wasted; uvalue_t ts_n_growheap; uvalue_t ts_s_growheap; #endif dev86-0.16.17/bcc/hardop.c0000644000000000000000000002512310057425211014730 0ustar rootroot00000000000000/* hardop.c - hardware operations for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "condcode.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" FORWARD void sub1 P((struct symstruct *source, struct symstruct *target)); PUBLIC void add(source, target) struct symstruct *source; struct symstruct *target; { scalar_t sscalar; if (source->indcount == 0 && source->storage != CONSTANT && (target->indcount != 0 || target->storage & ALLDATREGS)) swapsym(target, source); if ((sscalar = source->type->scalar) & DLONG) { longop(ADDOP, source, target); return; } if (sscalar & RSCALAR) { floatop(ADDOP, source, target); return; } if (source->storage == CONSTANT) { extend(target); if (target->indcount != 0 || target->storage & reguse) loadany(target); target->offset.offi += (offset_T) source->offset.offv; } else if (source->indcount == 0) { /* target is also direct */ sscalar |= target->type->scalar; /* remember if unsigned/long */ target->type = pctype; /* fake to use indexadr() */ indexadr(source, target); } else { /* source is indirect and not DREG */ extend(target); load(target, DREG); outadd(); movereg(source, DREG); if (source->type->scalar & CHAR) adc0(); } target->type = iscalartotype(target->type->scalar | sscalar); } PUBLIC void incdec(op, source) op_pt op; struct symstruct *source; { offset_T bump; bool_t postflag; store_t regmark; struct symstruct *target; struct symstruct targ; #ifdef MC6809 store_pt targreg; #endif *(target = &targ) = *source; bump = 1; if (targ.type->constructor & POINTER) bump = targ.type->nexttype->typesize; if (op == PREDECOP || op == POSTDECOP) bump = -bump; postflag = FALSE; if (op == POSTDECOP || op == POSTINCOP) postflag = TRUE; reguse |= targ.storage; if (targ.type->scalar & DLONG) /* cannot be direct */ { if (postflag) { regmark = reguse; if (((reguse |= OPREG) & allindregs) == allindregs) { saveopreg(); load(source, OPREG); pushreg(source->storage); restoreopreg(); } else { loadany(source); reguse = regmark | source->storage; saveopreg(); } } else saveopreg(); pointat(target); switch (op) { case PREDECOP: case POSTDECOP: call("ldec"); break; case PREINCOP: case POSTINCOP: call("linc"); break; } outlongendian(); restoreopreg(); if (postflag && source->storage == OPREG) poplist(OPREG); return; } if (targ.type->scalar & RSCALAR) { saveopreg(); pointat(target); switch (op) { case PREDECOP: call("Fpredec"); break; case PREINCOP: call("Fpreinc"); break; case POSTDECOP: call("Fpostdec"); break; case POSTINCOP: call("Fpostinc"); break; } outntypechar(targ.type); restoreopreg(); if (postflag) { justpushed(source); source->type = targ.type; } return; } loadany(source); #ifdef MC6809 if (postflag && targ.flags != REGVAR && !(source->storage & ALLDATREGS) && ((reguse |= source->storage) & allindregs) != allindregs) { targreg = getindexreg(); outlea(); outregname(targreg); outtab(); outshex(bump); outncregname(source->storage); } else { addconst(bump, targreg = source->storage); if (postflag) source->offset.offi = -bump; } storereg(targreg, target); target->storage = targreg; target->offset.offi = 0; #else addconst(bump, source->storage); if (postflag) source->offset.offi = -bump; storereg(source->storage, target); target->storage = source->storage; target->offset.offi = 0; #endif } PUBLIC void neg(target) struct symstruct *target; { scalar_t scalar; struct symstruct *source; if ((scalar = target->type->scalar) & DLONG) long1op(NEGOP, target); else if (scalar & RSCALAR) float1op(NEGOP, target); else { if (scalar & SHORT) extend(target); if (!(target->storage & ALLDATREGS)) { /* load 0, subtract is shorter than load, negate */ /* if no hardware integer negate; about the same if there is */ sub1(target, source = constsym((value_t) 0)); *target = *source; } else { load(target, DREG); negreg(target->storage); target->storage = DREG; } target->type = iscalartotype(scalar); } } PUBLIC void not(target) struct symstruct *target; { if (target->type->scalar & DLONG) long1op(NOTOP, target); else { extend(target); load(target, DREG); comDreg(); } } /* 1-byte ops like AND acting on integers (not both constant) */ PUBLIC void op1(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { char *opstr; #ifdef OP1 # if MAXINDIRECT > 1 indn_t indcount; # endif #endif bool_t resultchar; scalar_t resultscalar; scalar_t sscalar; scalar_t tscalar; if ((sscalar = source->type->scalar) & DLONG) { longop(op, source, target); return; } /* Emergency fix. The types of constants should be reduced here and in * other low-level routines anyway, and not in exptree.c and table.c, * and for the 80386 and maybe the 8086 they would be better not * reduced. */ if (source->storage == CONSTANT && ischarconst(source->offset.offv)) { if (sscalar & UNSIGNED) source->type = uctype; else source->type = ctype; sscalar = source->type->scalar; } tscalar = target->type->scalar; if (target->storage == CONSTANT && ischarconst(target->offset.offv)) { if (sscalar & UNSIGNED) target->type = uctype; else target->type = ctype; tscalar = target->type->scalar; } resultscalar = sscalar | tscalar; if (op != ANDOP) resultchar = sscalar & tscalar & CHAR; else if ((resultchar = (sscalar | tscalar) & CHAR) != 0 && source->storage == CONSTANT) { source->offset.offv &= CHMASKTO; if (sscalar & UNSIGNED) source->type = uctype; else source->type = ctype; sscalar = source->type->scalar; } if (target->indcount != 0 && ((tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) || (source->indcount == 0 && source->storage != CONSTANT))) { swapsym(target, source); sscalar = tscalar; tscalar = target->type->scalar; } if (source->indcount == 0 && source->storage != CONSTANT) { loadpres(source, target); push(source); } #if MAXINDIRECT > 1 else if (source->indcount >= MAXINDIRECT && !(sscalar & CHAR)) { address(source); if (!(target->storage & ALLDATREGS)) preserve(target); load(source, getindexreg()); indirec(source); } #endif if (!(tscalar & CHAR) && op == ANDOP && sscalar & CHAR && target->indcount == 1) cast(ctype, target); if (!(target->storage & ALLDATREGS) || target->indcount != 0) pres2(target, source); load(target, DREG); opstr = opstring(op); if (source->storage == CONSTANT && op == ANDOP) andconst((offset_T) source->offset.offv); #ifdef OP1 else if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) outload(); else outop2str(opstr); #else /* OP1 */ else { if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP) extend(target); outop2str(opstr); } #endif /* OP1 */ if (source->storage == CONSTANT) { if (op != ANDOP) { #ifdef OP1 if (!(sscalar & CHAR)) { outhiaccum(); outncimmadr((offset_T) ((uoffset_T) source->offset.offv >> (INT16BITSTO - CHBITSTO))); outop2str(opstr); } outregname(BREG); outncimmadr((offset_T) source->offset.offv & CHMASKTO); #else /* OP1 */ if (!(sscalar & CHAR)) { outregname(DREG); bumplc(); } else outregname(BREG); # ifdef I80386 if (i386_32 && !(sscalar & CHAR)) bumplc2(); # endif outncimmadr((offset_T) source->offset.offv); #endif /* OP1 */ } } else if (sscalar & CHAR) { outregname(BREG); outopsep(); outadr(source); } else { #ifdef MC6809 source->type = ctype; /* fool outadr to avoid ,S++ */ #endif #ifdef OP1 if (!(tscalar & CHAR) || op != ANDOP) { outhiaccum(); # if MAXINDIRECT > 1 indcount = source->indcount; # endif outopsep(); # if INT_BIG_ENDIAN == 0 ++source->offset.offi; # endif outadr(source); # if INT_BIG_ENDIAN == 0 --source->offset.offi; # endif # if MAXINDIRECT > 1 source->indcount = indcount; # else source->indcount = 1; # endif outop2str(opstr); } outregname(BREG); outopsep(); # if INT_BIG_ENDIAN ++source->offset.offi; # endif outadr(source); } #else /* OP1 */ if (!(tscalar & CHAR) || op != ANDOP) outregname(DREG); else outregname(BREG); outopsep(); outadr(source); } #endif /* OP1 */ if (resultchar) { target->storage = BREG; if (resultscalar & UNSIGNED) target->type = uctype; else target->type = ctype; } else { target->storage = DREG; target->type = iscalartotype(resultscalar); } } PUBLIC void ptrsub(source, target) struct symstruct *source; struct symstruct *target; { label_no exitlab; uoffset_T factor; label_no usignlab; if (source->indcount == 0 && source->storage != CONSTANT) { loadpres(source, target); push(source); } if (target->indcount == 0) { pres2(target, source); load(target, DREG); } factor = target->type->nexttype->typesize; source->type = target->type = itype; sub1(source, target); if (factor != 1) { pushlist(CCREG); sbranch(HS, usignlab = getlabel()); /* HS == no carry */ negDreg(); outnlabel(usignlab); target->type = uitype; softop(DIVOP, constsym((value_t) factor), target); target->type = itype; poplist(CCREG); sbranch(HS, exitlab = getlabel()); negDreg(); outnlabel(exitlab); } } PUBLIC void sub(source, target) struct symstruct *source; struct symstruct *target; { scalar_t sscalar; if ((sscalar = source->type->scalar) & DLONG) { longop(SUBOP, source, target); return; } if (sscalar & RSCALAR) { floatop(SUBOP, source, target); return; } if (source->storage == CONSTANT) { extend(target); if (target->indcount != 0 || target->storage & reguse) loadany(target); target->offset.offi -= (offset_T) source->offset.offv; } else sub1(source, target); target->type = iscalartotype(target->type->scalar | sscalar); } PRIVATE void sub1(source, target) struct symstruct *source; struct symstruct *target; { if (source->storage == CONSTANT) source->type = itype; else if (source->indcount == 0) { loadpres(source, target); push(source); } extend(target); load(target, DREG); outsub(); movereg(source, DREG); if (source->type->scalar & CHAR) sbc0(); } dev86-0.16.17/bcc/express.c0000644000000000000000000002351706456134232015161 0ustar rootroot00000000000000/* express.c - expression parsing routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "table.h" /* just for charptr for string constant */ #include "type.h" PRIVATE unsigned insizeof; /* nest level for getsizeof */ /* used to avoid aborting undefined idents */ /* to 0 when they appear in a cpp expression */ /* under sizeof */ /* names of expression functions are related to the 15 precedence levels */ /* on p49 of K & R */ FORWARD struct nodestruct *cast_exp P((void)); FORWARD struct nodestruct *exp2 P((void)); FORWARD struct nodestruct *exp3to12 P((fastin_pt lprecedence)); FORWARD struct nodestruct *listargs P((void)); FORWARD struct nodestruct *postfix_exp P((bool_pt seenlp)); FORWARD struct nodestruct *primary_exp P((void)); FORWARD struct nodestruct *unary_exp P((void)); PRIVATE struct nodestruct *cast_exp() { struct nodestruct *nodeptr; scalar_t scalar; struct typestruct *vartype; if (sym != LPAREN) return unary_exp(); nextsym(); if ((vartype = typename()) == NULL) return postfix_exp(TRUE); rparen(); scalar = (nodeptr = cast_exp())->nodetype->scalar; if (vartype->scalar & INT && scalar & (CHAR | SHORT | INT) && !((vartype->scalar ^ scalar) & UNSIGNED)) { nodeptr->flags &= ~LVALUE; return nodeptr; /* skip casts that are default promotions */ } return castnode(vartype, nodeptr); } PUBLIC struct nodestruct *assignment_exp() { struct nodestruct *lhs; op_pt op; lhs = exp2(); if (sym >= ASSIGNOP && sym <= SUBABOP) /* assign-op syms in order! */ { op = sym; nextsym(); lhs = node(op, lhs, assignment_exp()); } return lhs; } PUBLIC struct nodestruct *expression() { struct nodestruct *lhs; lhs = assignment_exp(); while (sym == COMMA) { nextsym(); lhs = node(COMMAOP, lhs, assignment_exp()); } return lhs; } PRIVATE struct nodestruct *exp2() { struct nodestruct *lhs; struct nodestruct *rhs; lhs = exp3to12(0); if (sym == CONDOP) { nextsym(); rhs = expression(); colon(); lhs = node(CONDOP, lhs, node(COLONOP, rhs, exp2())); } return lhs; } PRIVATE struct nodestruct *exp3to12(lprecedence) fastin_pt lprecedence; { struct nodestruct *lhs; op_pt op; fastin_t rprecedence; lhs = cast_exp(); while (TRUE) { rprecedence = 0; switch (sym) { case LOGOROP: if ((fastin_t) lprecedence <= 1) rprecedence = 2; break; case LOGANDOP: if ((fastin_t) lprecedence <= 3) rprecedence = 4; break; case OROP: if ((fastin_t) lprecedence <= 5) rprecedence = 6; break; case EOROP: if ((fastin_t) lprecedence <= 7) rprecedence = 8; break; case AMPERSAND: if ((fastin_t) lprecedence <= 9) { sym = ANDOP; rprecedence = 10; } break; case EQOP: case NEOP: if ((fastin_t) lprecedence <= 11) rprecedence = 12; break; case GEOP: case GTOP: case LEOP: case LTOP: if ((fastin_t) lprecedence <= 13) rprecedence = 14; break; case SLOP: case SROP: if ((fastin_t) lprecedence <= 15) rprecedence = 16; break; case HYPHEN: if ((fastin_t) lprecedence <= 17) { sym = SUBOP; rprecedence = 18; } break; case ADDOP: if ((fastin_t) lprecedence <= 17) rprecedence = 18; break; case STAR: if ((fastin_t) lprecedence <= 19) { sym = MULOP; rprecedence = 20; } break; case DIVOP: case MODOP: if ((fastin_t) lprecedence <= 19) rprecedence = 20; break; } if (rprecedence == 0) break; op = sym; nextsym(); lhs = node(op, lhs, exp3to12(rprecedence)); } return lhs; } PRIVATE struct nodestruct *listargs() { struct nodestruct *parent; struct nodestruct *nextright; if (sym == RPAREN) { nextsym(); return NULLNODE; } parent = node(arg1op, assignment_exp(), NULLNODE); nextright = parent; while (sym == COMMA) { nextsym(); nextright = nextright->right = node(LISTOP, assignment_exp(), NULLNODE); } rparen(); return parent; } PRIVATE struct nodestruct *postfix_exp(seenlp) bool_pt seenlp; { struct nodestruct *nodeptr; struct symstruct *symptr; if (seenlp) { nodeptr = expression(); rparen(); } else nodeptr = primary_exp(); while (TRUE) { switch (sym) { case DECSYM: nextsym(); nodeptr = node(POSTDECOP, nodeptr, NULLNODE); continue; case INCSYM: nextsym(); nodeptr = node(POSTINCOP, nodeptr, NULLNODE); continue; case LBRACKET: nextsym(); nodeptr = node(INDIRECTOP, node(ADDOP, nodeptr, expression()), NULLNODE); rbracket(); continue; case LPAREN: nextsym(); nodeptr = node(FUNCOP, nodeptr, listargs()); { register struct nodestruct *np; for (np = nodeptr->right; np != NULL; np = np->right) { if (np->nodetype->scalar & RSCALAR) { np = nodeptr->left.nodeptr; if (np->tag != LEAF) printf_fp = TRUE; else { unsigned len; register char *name; name = np->left.symptr->name.namep; if ((len = strlen(name)) >= 6 && strcmp(name + len - 6, "printf") == 0) printf_fp = TRUE; } break; } } for (np = nodeptr->right; np != NULL; np = np->right) { if (np->nodetype->constructor & POINTER && np->nodetype->nexttype->scalar & RSCALAR) { np = nodeptr->left.nodeptr; if (np->tag != LEAF) scanf_fp = TRUE; else { unsigned len; register char *name; name = np->left.symptr->name.namep; if ((len = strlen(name)) >= 5 && strcmp(name + len - 5, "scanf") == 0) scanf_fp = TRUE; } break; } } } continue; case STRUCPTROP: nodeptr = node(INDIRECTOP, nodeptr, NULLNODE); case STRUCELTOP: nextsym(); gs2name[0] = nodeptr->nodetype->structkey[0]; gs2name[1] = nodeptr->nodetype->structkey[1]; if ((gsymptr = findlorg(gs2name)) == NULL) { error("undefined structure element"); gsymptr = addglb(gs2name, itype); } symptr = exprsym(gsymptr); nextsym(); nodeptr = node(STRUCELTOP, nodeptr, leafnode(symptr)); continue; default: return nodeptr; } } } PRIVATE struct nodestruct *primary_exp() { bool_t isdefined; struct nodestruct *nodeptr; uoffset_T stringlen; struct symstruct *symptr; struct symstruct *symptr1; bool_t waslparen; switch (sym) { case IDENT: if (incppexpr && !insizeof) { cpp_ident: nextsym(); return leafnode(constsym((value_t) 0)); } if ((symptr = gsymptr) != NULL) nextsym(); else { symptr = addglb(gsname, fitype); nextsym(); if (sym != LPAREN) { error2error(symptr->name.namea, " undeclared"); symptr->indcount = 1; symptr->type = itype; } } symptr1 = exprsym(symptr); if (symptr->flags & STATIC && symptr->level != GLBLEVEL) { symptr1->flags |= LABELLED; symptr1->offset.offi = 0; symptr1->name.label = symptr->offset.offlabel; } nodeptr = leafnode(symptr1); if (!(nodeptr->nodetype->constructor & (ARRAY | FUNCTION | VOID))) nodeptr->flags = LVALUE; return nodeptr; case TYPEDEFNAME: if (incppexpr && !insizeof) goto cpp_ident; /* else fall through */ default: error("bad expression"); constant.value.v = 0; constant.type = itype; case CHARCONST: case INTCONST: /* this includes enumeration-constants */ symptr = constsym(constant.value.v); symptr->type = constant.type; if (!(ltype->scalar & LONG)) { if (symptr->type == ltype) symptr->type = itype; else if (symptr->type == ultype) symptr->type = uitype; } nextsym(); return leafnode(symptr); case DEFINEDSYM: waslparen = isdefined = FALSE; if (!blanksident()) { nextsym(); if (sym != LPAREN) lparen(); else waslparen = TRUE; } if (waslparen && !blanksident()) needvarname(); else { if ((symptr = findlorg(gsname)) != NULL && symptr->flags == DEFINITION) isdefined = TRUE; nextsym(); } if (waslparen) rparen(); return leafnode(constsym((value_t) isdefined)); case FLOATCONST: symptr = constsym((value_t) 0); symptr->type = constant.type; symptr->offset.offd = qmalloc(sizeof *symptr->offset.offd); *symptr->offset.offd = constant.value.d; nextsym(); return leafnode(symptr); case LPAREN: nextsym(); nodeptr = expression(); rparen(); return nodeptr; case STRINGCONST: symptr = constsym((value_t) 0); symptr->storage = GLOBAL; symptr->flags = LABELLED | STRING; /* string length before defstr() or prefix() updates charptr */ stringlen = charptr - constant.value.s + 1; symptr->name.label = defstr(constant.value.s, charptr, FALSE); symptr->type = prefix(ARRAY, stringlen, ctype); nextsym(); return leafnode(symptr); } } PRIVATE struct nodestruct *unary_exp() { value_t size; struct typestruct *vartype; switch (sym) { case ADDOP: nextsym(); return cast_exp(); case AMPERSAND: nextsym(); return node(ADDRESSOP, cast_exp(), NULLNODE); /* maybe unary_exp */ case DECSYM: nextsym(); return node(PREDECOP, unary_exp(), NULLNODE); case HYPHEN: nextsym(); return node(NEGOP, cast_exp(), NULLNODE); case INCSYM: nextsym(); return node(PREINCOP, unary_exp(), NULLNODE); case LOGNOTOP: nextsym(); return node(LOGNOTOP, cast_exp(), NULLNODE); case NOTOP: nextsym(); return node(NOTOP, cast_exp(), NULLNODE); case SIZEOFSYM: nextsym(); ++insizeof; if (sym != LPAREN) size = unary_exp()->nodetype->typesize; else { nextsym(); if ((vartype = typename()) != NULL) { rparen(); size = vartype->typesize; } else size = postfix_exp(TRUE)->nodetype->typesize; } --insizeof; return leafnode(constsym(size)); case STAR: nextsym(); return node(INDIRECTOP, cast_exp(), NULLNODE); /* maybe unary_exp */ } return postfix_exp(FALSE); } dev86-0.16.17/bcc/condcode.h0000644000000000000000000000036005301213541015227 0ustar rootroot00000000000000/* condcode.h - condition codes for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define EQ 0 #define NE 1 #define RA 2 #define RN 3 #define LT 4 #define GE 5 #define LE 6 #define GT 7 #define LO 8 #define HS 9 #define LS 10 #define HI 11 dev86-0.16.17/bcc/debug.c0000644000000000000000000001320210065310700014527 0ustar rootroot00000000000000/* * debug.c: a generic debugging facility for unix programs. * * The calling program is required to call debug_setlevel(lvl) to set * which messages will be displayed. The level is a two part value * where the least significant (decimal) digit is a level as described * below. The most significant digits are a class code. For a message * to be displayed the class code must either be zero or match the * class code of the debug(...) message. * * The 'debug(lvl, fmt, ...)' function displays debugging messages * complete with source and line number. The function can be used * as a normal one in if() smt else smt constructs. It returns the * actual number of bytes printed so it's return value can be used * inside an if(debug(...)) to enable more debugging code. This code * will be removed by the compiler (as dead code) if debugging is * not enabled. * * The level on the debug() statment also consists of a level and class * code where the class code must be zero or match the setlevel's class * code for the message to be displayed. * * Level 0 * Always displayed if the debugging is enabled. * You probably shouldn't use this. * * Level 1 * Important state changes and errors that cause a significant change * in program flow. * * Level 2 * Rare things that cause a minor program flow adjustment. * * Level 3 * Errors and useful messages that are slightly too verbose or common * for 0-2 or don't quite fit in the classifications. * * Level 4 * All remote responses or major results. (Trace results) * * Level 5 * All remote commands or major tasks. (Trace jobs) * * Level 6 * General information that will not be too verbose but is normally a * little less important. (Trace state) * * Level 7 * Similar to level 3 but verbose or not as useful. * * Level 8 * Very verbose information that'll probably be useful sometime. * * Level 9 * Anything and everything else, debugs that probably won't be useful * ever again. (unclassified) * * Notes: * If the programmer doesn't set the debug level this is not an important * debug message or is only important right now. * => default debug level == 9 * * If something fits in one of the lower levels but is very verbose * it should nevertheless be moved upto level 3 or levels 7-9. * (Possibly leaving a single line 'oops' at the lower level) * * The general idea is that debug levels 0-3 should not scroll too fast * to read and nothing below level 7 should be much more verbose than * levels 4 or 5. * ***************************************************************************** * * 2004-06-20: Added __STDC__ to debug.h so it can be called from non-ansi * compiler. This file still needs ansi or unproto. * * 2004-06-20: Added check of DEBUG environment variable if setlevel isn't * called before a debug(). * * 2004-06-20: Added #define VARARG_MACROS so the preprocessor can remove * all the debugging 'stuff'. * */ #include #include #include #include "debug.h" #define USE_DBPRINTF #ifndef DEBUG static char ident[] = "$Id: debug.c: (c) 1995-2004 Robert de Bath. Debugging disabled. $"; #else static char ident[] = "$Id: debug.c: (c) 1995-2004 Robert de Bath. Debugging enabled. $"; static char * db_file = 0; static int db_lineno = 0; static int disp_state = 0; static int disp_pos(void); static void debug_envvar(void); int debug_level = -1; void debug_do_setlevel(char * fname, int lineno, int level) { if(level || !debug_level) debug_level = level; debug_pos(fname, lineno); debug_msg(1, "Debug level now %d", level); debug_level = level; } int debug_pos(char * file, int lineno) { db_file = file; db_lineno = lineno; disp_state |= 1; return disp_pos(); } int debug_msg(int level, char * fmt, ...) { va_list ap; int rv = 0; int disp = 0; if (debug_level == -1) debug_envvar(); if (level == -1) { level = 0; disp_state |= 1; db_lineno = -1; } disp_state |= 2; if (level>9 || debug_level>9) { disp = (level%10 <= debug_level%10); if (disp && level>9 && debug_level>9 && level/10 != debug_level/10) disp = 0; } else disp = (level <= debug_level); if (disp) { disp_state |= 4; va_start(ap, fmt); #ifdef USE_DBPRINTF rv = vdbprintf(fmt, ap); #else rv = vfprintf(stderr, fmt, ap); #endif va_end(ap); } return rv + disp_pos(); } int disp_pos() { int rv = 0; if (disp_state == 7 && db_lineno != -1) #ifdef USE_DBPRINTF rv = dbprintf(" at %s:%d\n", db_file, db_lineno); #else rv = fprintf(stderr, " at %s:%d\n", db_file, db_lineno); #endif if ((disp_state&3) == 3) { db_file = 0; db_lineno = disp_state = 0; } return rv; } /* If setlevel isn't called check the environment */ static void debug_envvar(void) { char * p = getenv("DEBUG"); if (!p || !*p) debug_level = 0; else debug_level = atoi(p); if (debug_level) #ifdef USE_DBPRINTF dbprintf("Debug level now %d from environment.\n", debug_level); #else fprintf(stderr, "Debug level now %d from environment.\n", debug_level); #endif } #endif #ifndef VARARG_MACROS /* * This function should never be called. * * If ident sees the message in a binary then your compiler is wasting * space by allocating it for unused strings. * * We know GNU-C is ok, but it complains. */ int debug_never(int level, char * name, ...) { #ifndef __GNUC__ 1?0:debug_never(0, "$Warning: Debugging strings exist in non-debug binary $"); #endif return 0; } #endif dev86-0.16.17/bcc/os.h0000644000000000000000000000231506127507561014113 0ustar rootroot00000000000000/* os.h - source/target operating system dependencies for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* must have unix-near-compatible creat, open, read, write and close source O/S's supported: default: *IX special: EDOS (#define SOS_EDOS if required) MSDOS (#define SOS_MSDOS) target O/S's supported: default: *IX MSDOS special: EDOS (#define TOS_EDOS) */ /* defaults */ #define CREATPERMS 0666 /* permissions for creat */ #define EOL 10 /* source newline */ #define EOLTO 10 /* target newline */ #define DIRCHAR '/' #define DIRSTRING "/" #define isabspath(fnameptr, tempcptr) \ ((*(tempcptr) = *(fnameptr)) == DIRCHAR) /* special */ #ifdef SOS_EDOS # undef DEFAULT_INCLUDE_DIR # define DEFAULT_INCLUDE_DIR "3" # undef DIRCHAR # define DIRCHAR ':' # undef DIRSTRING # define DIRSTRING ":" # define AS09 # undef EOL # define EOL 13 # undef isabspath # define isabspath(fnameptr, tempcptr) \ ((*(tempcptr) = *(fnameptr)) >= '0' && *(tempcptr) <= '9' && \ (fnameptr)[1] == DIRCHAR) #endif #ifdef TOS_EDOS # undef EOLTO # define EOLTO 13 #endif /* don't let names dealt with here affect anything outside this file */ #undef SOS_EDOS #undef SOS_MSDOS dev86-0.16.17/bcc/6809/0000755000000000000000000000000006177771600013730 5ustar rootroot00000000000000dev86-0.16.17/bcc/6809/const.h0000644000000000000000000000270305301213702015207 0ustar rootroot00000000000000/* const.h - constants for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* switches for code generation */ #define DEBUG /* generate compiler-debugging code */ /*#define I8088*/ /* target processor is Intel 8088 thru 80386 */ #define MC6809 /* target processor is Motorola 6809 */ #define SELFTYPECHECK /* check calculated type = runtime type */ #ifdef I8088 # define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */ # define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */ # define HOLDSTRINGS /* hold strings for dumping at end * since assembler has only 1 data seg */ #endif #ifdef MC6809 # define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */ # define OP1 /* logical operators only use 1 byte */ # define POSINDEPENDENT /* position indep code can (also) be gen */ #endif /* switches for source and target operating system dependencies */ /*#define SOS_EDOS*/ /* source O/S is EDOS */ /*#define SOS_MSDOS*/ /* source O/S is MSDOS */ #define TOS_EDOS /* target O/S is EDOS */ /* switches for source machine dependencies */ #ifndef SOS_EDOS # define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */ #endif #ifndef SOS_MSDOS /* need portable alignment for large model */ # define UNPORTABLE_ALIGNMENT #endif /* local style */ #define FALSE 0 #ifndef NULL #define NULL 0 #endif #define TRUE 1 #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC dev86-0.16.17/bcc/byteord.h0000644000000000000000000000054106324133567015141 0ustar rootroot00000000000000/* byteord.h - byte order dependencies for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef I8088 # define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 1 /* longs are back to front for Xenix */ #endif #ifdef MC6809 # define INT_BIG_ENDIAN 1 /* byte order in words is high-low */ # define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */ #endif dev86-0.16.17/bcc/floatop.c0000644000000000000000000001127207517066030015126 0ustar rootroot00000000000000/* floatop.c - software operations on floats and doubles for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "type.h" /*----------------------------------------------------------------------------- f_indirect(target leaf) make the float or double target indirect if it is not already return nonzero iff the result is a temp double on the base of the stack -----------------------------------------------------------------------------*/ PUBLIC bool_pt f_indirect(target) struct symstruct *target; { if (target->indcount == 0) { if (target->storage == CONSTANT) { #ifdef I80386 if (i386_32) { if (target->type->scalar & FLOAT) { float val; val = *target->offset.offd; push(constsym(((value_t *) &val)[0])); } else { push(constsym(((value_t *) target->offset.offd)[1])); push(constsym(((value_t *) target->offset.offd)[0])); } } else #endif { if (target->type->scalar & FLOAT) { float val = *target->offset.offd; push(constsym( ((unsigned short*) &val)[1] )); push(constsym( ((unsigned short*) &val)[0] )); } else { push(constsym(((unsigned short*) target->offset.offd)[3])); push(constsym(((unsigned short*) target->offset.offd)[2])); push(constsym(((unsigned short*) target->offset.offd)[1])); push(constsym(((unsigned short*) target->offset.offd)[0])); } } } else if (target->type->scalar & FLOAT) pushlist(target->storage); /* XXX - floatregs */ else pushlist(doubleregs); onstack(target); } return target->flags == TEMP && target->type->scalar & DOUBLE && target->offset.offi == sp; } /*----------------------------------------------------------------------------- float1op(operation code, source leaf) handles all flop unary operations except inc/dec result is double on stack (or in condition codes for EQOP) -----------------------------------------------------------------------------*/ PUBLIC void float1op(op, source) op_pt op; struct symstruct *source; { saveopreg(); pointat(source); if ((op_t) op == NEGOP) call("Fneg"); else /* op == EQOP */ call("Ftst"); outntypechar(source->type); if ((op_t) op != EQOP) justpushed(source); restoreopreg(); } /*----------------------------------------------------------------------------- floatop(operation code, source leaf, target leaf) handles all flop binary operations result is double on stack (or in condition codes for EQOP) ----------------------------------------------------------------------------*/ PUBLIC void floatop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_t regmark; bool_t sflag; regmark = reguse; saveopreg(); (void) f_indirect(source); if (!(reguse & OPREG) && (source->storage == OPREG)) { reguse |= source->storage; saveopreg(); } fpush(target); sflag = TRUE; if (source->flags != TEMP || source->offset.offi != sp + dtypesize) { sflag = FALSE; if (source->storage == OPREG) restoreopreg(); pointat(source); } switch ((op_t) op) { case ADDOP: call("Fadd"); break; case DIVOP: call("Fdiv"); break; case EQOP: call("Fcomp"); sp += dtypesize; /* target is popped */ break; /* target symbol now invalid but is not used */ case MULOP: call("Fmul"); break; case SUBOP: call("Fsub"); break; } if (sflag) { outnl(); sp += dtypesize; /* source is popped */ } else outntypechar(source->type); onstack(target); reguse = regmark; /* early so opreg is not reloaded if source */ restoreopreg(); } /*----------------------------------------------------------------------------- fpush(source leaf of scalar type) converts source to double and pushes it to stack OPREG must be free -----------------------------------------------------------------------------*/ PUBLIC void fpush(source) struct symstruct *source; { scalar_t scalar; if ((scalar = source->type->scalar) & RSCALAR) { if (f_indirect(source)) return; pointat(source); } else if (scalar & DLONG) load(source, OPREG); else load(source, DREG); call("Fpush"); if (scalar & UNSIGNED) outbyte('u'); outntypechar(source->type); justpushed(source); } /*----------------------------------------------------------------------------- justpushed(target leaf) records that target has just been pushed to a double on the stack -----------------------------------------------------------------------------*/ PUBLIC void justpushed(target) struct symstruct *target; { sp -= dtypesize; onstack(target); target->type = dtype; } dev86-0.16.17/bcc/preserve.c0000644000000000000000000001140110057375631015312 0ustar rootroot00000000000000/* preserve.c - preserve opererands or registers in use for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "reg.h" #include "type.h" #include "scan.h" /* change stack ptr without changing condition codes */ PUBLIC void changesp(newsp, absflag) offset_T newsp; bool_pt absflag; { if (newsp != sp || ((bool_t) absflag && switchnow != NULL)) { #ifdef FRAMEPOINTER if (newsp != framep || (!(bool_t) absflag && switchnow != NULL)) { int off; outleasp(); if (!(bool_t) absflag && switchnow != NULL) outswoffset(off = newsp); else outoffset(off = newsp - framep); #ifndef NO_DEL_PUSH if (optimise && !callersaves && off < 0) { outstr("+"); outstr(funcname); outstr(".off"); } #endif outindframereg(); outnl(); } else regtransfer(FRAMEREG, STACKREG); sp = newsp; if (framep == 0) bugerror("no frame pointer"); #else # ifdef I8088 outleasp(); outoffset(newsp - sp); outindstackreg(); outnl(); # else modstk(newsp); /* this should preserve CC */ # endif #endif /* FRAMEPOINTER */ } } /* load source to any while preserving target */ PUBLIC void loadpres(source, target) struct symstruct *source; struct symstruct *target; { store_t regmark; if (target->storage & ALLDATREGS) { if (source->type->scalar & CHAR) { push(target); load(source, DREG); } else load(source, getindexreg()); } else { regmark = reguse; reguse |= target->storage; loadany(source); reguse = regmark; } } /* change stack ptr */ PUBLIC void modstk(newsp) offset_T newsp; { if (newsp != sp) { #ifdef FRAMEPOINTER if (newsp != framep || framep == 0 || switchnow != NULL) addconst(newsp - sp, STACKREG); else regtransfer(FRAMEREG, STACKREG); #else # ifdef I8088 addconst(newsp - sp, STACKREG); # else outleasp(); outoffset(newsp - sp); outncspregname(); # endif #endif sp = newsp; } } /* preserve target without changing source */ PUBLIC void pres2(source, target) struct symstruct *source; struct symstruct *target; { if (target->storage & allregs) { if (target->storage & (allregs - allindregs) /* XXX */ || (target->indcount == 0 && target->type->scalar & (DLONG | RSCALAR))) push(target); /* XXX - perhaps not float */ else if (((target->storage | reguse) & allindregs) == allindregs) { loadpres(target, source); push(target); } else reguse |= target->storage; } } /* preserve source */ PUBLIC void preserve(source) struct symstruct *source; { if (source->storage & allregs) { if (source->storage & (allregs - allindregs) /* XXX */ || ((source->storage | reguse) & allindregs) == allindregs) push(source); else reguse |= source->storage; } } /* preserve lvalue target without changing source or target */ PUBLIC store_pt preslval(source, target) struct symstruct *source; struct symstruct *target; { store_pt regpushed; if (target->indcount == 0) reguse &= ~target->storage; else reguse = (target->storage | reguse) & allindregs; if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR)) || reguse != allindregs) return 0; /* XXX - perhaps not float */ reguse = source->storage | target->storage; /* free one other than s/t */ pushreg(regpushed = getindexreg()); reguse = ~(store_t) regpushed & allindregs; return regpushed; } PUBLIC void recovlist(reglist) store_pt reglist; { poplist(reglist); reguse |= (store_t) reglist; } #ifdef I8088 PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5}; /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */ /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */ #endif #ifdef MC6809 PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2}; /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */ #endif PUBLIC void savereturn(savelist, saveoffset) store_pt savelist; offset_T saveoffset; { store_t reg; smalin_t *regoffptr; offset_T spoffset; if (savelist == 0) return; #ifdef MC6809 /* must check this */ if (savelist == XREG || savelist == INDREG1) saveoffset -= accregsize; /* patch for DREG/YREG not saved */ #endif for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1) if (reg & savelist) { outstore(); spoffset = saveoffset + *regoffptr * maxregsize; #ifdef I8088 # ifdef FRAMEPOINTER if (switchnow != NULL) outswoffset(spoffset); else outoffset(spoffset - framep); outindframereg(); # else outoffset(spoffset - sp); outindstackreg(); # endif outncregname(reg); #endif #ifdef MC6809 if (reg == YREG) bumplc(); outregname(reg); outtab(); outoffset(spoffset - sp); outncspregname(); #endif } } dev86-0.16.17/bcc/sysproto.h0000644000000000000000000000166006324132476015374 0ustar rootroot00000000000000 /* library - fcntl.h */ int creat P((const char *_path, int _mode)); int open P((const char *_path, int _oflag, ...)); /* library - stdlib.h */ double atof P((const char *_str)); void exit P((int _status)); /* library - string.h */ void *memcpy P((void *_t, const void *_s, unsigned _length)); void *memset P((void *_s, int _c, unsigned _nbytes)); char *strcat P((char *_target, const char *_source)); char *strchr P((const char *_s, int _ch)); int strcmp P((const char *_s1, const char *_s2)); char *strcpy P((char *_target, const char *_source)); unsigned strlen P((const char *_s)); char *strncpy P((char *_target, const char *_source, unsigned _maxlength)); char *strrchr P((const char *_s, int _ch)); /* library - unistd.h */ int close P((int _fd)); int isatty P((int _fd)); long lseek P((int _fd, long _offset, int _whence)); int read P((int _fd, char *_buf, unsigned _nbytes)); int write P((int _fd, char *_buf, unsigned _nbytes)); dev86-0.16.17/bcc/input.c0000644000000000000000000004453610065325211014621 0ustar rootroot00000000000000/* input.c - input for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define ARBITRARY_BACKSLASH_NEWLINES_NOT #define INSERT_BACKSLASH_NEWLINES_NOT #include "bcc.h" #include "gencode.h" #include "output.h" #include "os.h" #include "sc.h" #include "scan.h" #include "table.h" #undef EXTERN #define EXTERN #include "input.h" #define INBUFSIZE 2048 #define NO_EOFHACK struct fbufstruct /* file buffer structure */ { struct fcbstruct fcb; /* status after opening an include sub-file */ char *fname; /* file name */ bool_t fname_malloced; /* nonzero if fname was malloced */ char pushback[3]; /* allows pushback to 2 before start of fbuf * XXX 3 chars before? * XXX should do everything in fbuf */ char fbuf[INBUFSIZE + 1]; /* buffer to read into */ }; #ifdef BUILTIN_CPP struct inclist /* list of include file directories */ { char *incdirname; struct inclist *incnext; }; PRIVATE char filemacro[] = "__FILE__"; PRIVATE struct inclist incabsolute; /* dummy list for absolute names */ /* depends on zero (NULL) init */ PRIVATE struct inclist incfirst; /* begin include searches here for "" */ /* at next in list for <> */ /* -I directories are put in list */ /* between first and last */ PRIVATE struct inclist inclast = { #ifdef DEFAULT_INCLUDE_DIR DEFAULT_INCLUDE_DIR, #endif NULL, }; PRIVATE fastin_t inclevel; /* nest level of include files */ /* depends on zero init */ #endif PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */ /* its fcb only to date in includes */ /* depends on zero (NULL) init */ PRIVATE bool_t suppress_line_numbers; #ifdef ARBITRARY_BACKSLASH_NEWLINES FORWARD void backslash P((void)); #endif #ifdef BUILTIN_CPP FORWARD void definefile P((char *fname)); FORWARD void leaveinclude P((void)); #endif FORWARD void inputinit P((char *fname, fd_t fd)); FORWARD void usage P((void)); #ifdef ARBITRARY_BACKSLASH_NEWLINES PRIVATE void backslash() { static unsigned nbackslash; if (nbackslash != 0) --nbackslash; more: ++nbackslash; while (*(lineptr + 1) == '\\') { ++nbackslash; ++lineptr; } if (*(lineptr + 1) != EOL) { if (--nbackslash != 0) *--lineptr = '\\'; /* force look at current backslash again */ return; } ch = *++lineptr; more1: if (!eofile && lineptr >= input.limit) skipeol(); if (ch == EOL) { --nbackslash; if (eofile) eofin("backslash-newline"); else { skipeol(); if (ch == EOL && !eofile && lineptr >= input.limit) skipeol(); #ifdef COEOL /* XXX - this should go through specialchar() */ if (ch == COEOL) { ch = *++lineptr; if (ch == EOL && !eofile && lineptr >= input.limit) skipeol(); } #endif } if (ch == '\\') goto more; if (nbackslash != 0 && ch == EOL && !eofile) goto more1; if (nbackslash != 0) { ch = *--lineptr = '\\'; if (--nbackslash != 0) ch = *--lineptr = '\\'; } return; } if (ch == '\\') goto more; if (ch == EOL && !eofile) goto more1; ch = *--lineptr = '\\'; /* pushback */ if (--nbackslash != 0) ch = *--lineptr = '\\'; } #endif PUBLIC void closein() { #ifdef FAKE_INBUFSIZE_1 fclose(input.fp); #else close(input.fd); #endif #ifdef BUILTIN_CPP while (inclevel != 0) leaveinclude(); #endif } #ifdef BUILTIN_CPP PRIVATE void definefile(fname) char *fname; { char *def; def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1); strcpy(def, filemacro); strcat(def, "=\""); strcat(def, fname); strcat(def, "\""); definestring(def); ourfree(def); } #endif PUBLIC void errorloc() { register struct fbufstruct *infbuf; if ((infbuf = inputbuf) == NULL) return; outstr(infbuf->fname); outbyte(':'); if (eofile) outstr("eof"); else { outudec(input.linenumber); outbyte('.'); #ifdef BUILTIN_CPP if (maclevel == 0) outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset); else { outudec((unsigned) (savedlineptr() - inputbuf->fbuf) - input.lineoffset); outstr(" (macro level "); outudec((unsigned) maclevel); outbyte(')'); } #else outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset); #endif } infbuf->fcb.includer = input.includer; while ((infbuf = infbuf->fcb.includer) != NULL) { outstr(" (from "); outstr(infbuf->fname); outbyte(':'); outudec(infbuf->fcb.linenumber); outbyte(')'); } outstr(": "); } /* gch1() - get next char, advance ptr (only works on current line) */ PUBLIC void gch1() { if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR) return; specialchar(); } #ifdef BUILTIN_CPP /* process #include */ PUBLIC void include() { char *dirnameptr; char *dirnamend; unsigned dirnamelen; fd_t fd; char *fnameptr; char *fullnameptr; struct inclist *incptr; char terminator; while (blanksident()) { if ((gsymptr = findlorg(gsname)) == NULL || gsymptr->flags != DEFINITION) break; entermac(); } if ((terminator = ch) == '<') terminator = '>'; else if (terminator != '"') { error("bad file name"); return; } gch1(); fnameptr = charptr; while (TRUE) { if (ch == EOL) /* no escapes in file names */ break; if (ch == terminator) { gch1(); blanks(); break; } if (charptr >= chartop) fnameptr = growobject(fnameptr, 1); #ifdef TS ++ts_n_filename; ++ts_s_filename; ++ts_s_filename_tot; #endif *charptr++ = ch; gch1(); } if (charptr >= chartop) fnameptr = growobject(fnameptr, 1); #ifdef TS ++ts_n_filename_term; ++ts_s_filename_term; ++ts_s_filename_tot; #endif *charptr++ = 0; dirnamend = NULL; if (isabspath(fnameptr, &ch)) incptr = &incabsolute; else { incptr = &incfirst; if (terminator == '>') incptr = incptr->incnext; else { dirnameptr = inputbuf->fname; if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL) incptr->incdirname = NULL; else { *dirnamend = 0; incptr->incdirname = dirnameptr; } } } do { if (incptr->incdirname == NULL) { fullnameptr = ourmalloc(strlen(fnameptr) + 1); #ifdef TS ++ts_n_pathname; ts_s_pathname += strlen(fnameptr) + 1; ts_s_pathname_tot += strlen(fnameptr) + 1; #endif strcpy(fullnameptr, fnameptr); } else { dirnamelen = strlen(incptr->incdirname); fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr) + 2); /* 2 extra for null and maybe DIRCHAR */ #ifdef TS ++ts_n_pathname; ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2; ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2; #endif dirnameptr = fullnameptr + dirnamelen; strcpy(fullnameptr, incptr->incdirname); if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR) strcat(fullnameptr, DIRSTRING); strcat(fullnameptr, fnameptr); if (dirnamend != NULL) { *dirnamend = DIRCHAR; dirnamend = NULL; } } fd = open(fullnameptr, 0); if (fd >= 0) { #ifdef TS ts_s_filename_tot -= charptr - fnameptr; #endif charptr = fnameptr; input.lineptr = lineptr; inputbuf->fcb = input; ++inclevel; /* XXX - will run out of memory before overflow */ inputinit(fullnameptr, fd); inputbuf->fname_malloced = TRUE; return; } #ifdef TS ts_s_pathname_tot -= strlen(fullnameptr) + 1; #endif ourfree(fullnameptr); } while ((incptr = incptr->incnext) != NULL); fullnameptr = ourmalloc(strlen(fnameptr) + 40); strcpy(fullnameptr, "cannot find include file "); strcat(fullnameptr, fnameptr); error(fullnameptr); ourfree(fullnameptr); #ifdef TS ts_s_filename_tot -= charptr - fnameptr; #endif charptr = fnameptr; } #endif /* initialise current input file */ PRIVATE void inputinit(fname, fd) char *fname; fd_t fd; { register struct fbufstruct *newinputbuf; /* don't allocate after saying input.includer = inputbuf (to save a reg) * or an error in the alloc would cycle trying to print the include list */ newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf); #ifdef TS ++ts_n_inputbuf; ts_s_inputbuf += sizeof *inputbuf; ts_s_inputbuf_tot += sizeof *inputbuf; #endif input.fd = fd; #ifdef FAKE_INBUFSIZE_1 input.fp = fdopen(fd, "r"); #endif input.linenumber = 0; input.lineoffset = 0; input.includer = inputbuf; inputbuf = newinputbuf; newinputbuf->fname = fname; newinputbuf->fname_malloced = FALSE; #ifdef BUILTIN_CPP undefinestring(filemacro); definefile(fname); if (orig_cppmode && !suppress_line_numbers) outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1"); #endif *(input.limit = newinputbuf->fbuf) = EOL; /* dummy line so processing can start with skipline() */ ch = *(lineptr = newinputbuf->fbuf - 1) = EOL; } PUBLIC void linecontol() { char linename[256]; char * ptr; int i=0; blanks(); input.linenumber = atoi(lineptr)-1; while( SYMOFCHAR(ch) == INTCONST ) gch1(); blanks(); if( ch != '"' ) return; for(ptr=lineptr+1; *ptr && *ptr != EOL && *ptr != '"' && ifname_malloced) { #ifdef TS ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; #endif ourfree(inputbuf->fname); } inputbuf->fname_malloced = TRUE; ptr = ourmalloc(strlen(linename)+1); strcpy(ptr, linename); inputbuf->fname = ptr; ptr=lineptr; #ifdef BUILTIN_CPP undefinestring(filemacro); definefile(inputbuf->fname); #endif ch = *(lineptr = ptr); } #ifdef BUILTIN_CPP /* switch from include file to file which included it */ PRIVATE void leaveinclude() { --inclevel; if (inputbuf->fname_malloced) { #ifdef TS ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; #endif ourfree(inputbuf->fname); } #ifdef TS ts_s_inputbuf_tot -= sizeof *inputbuf; #endif ourfree((char *) inputbuf); #ifndef NO_EOFHACK if(input.fd>=0) #endif close(input.fd); #ifdef FAKE_INBUFSIZE_1 fclose(input.fp); #endif inputbuf = input.includer; input = inputbuf->fcb; undefinestring(filemacro); definefile(inputbuf->fname); ch = *(lineptr = input.lineptr); skipline(); if (orig_cppmode && !suppress_line_numbers) outcpplinenumber(input.linenumber, inputbuf->fname, " 2"); } #endif /* open input and output files and get options */ PUBLIC void openio(argc, argv) int argc; char *argv[]; { register char *arg; int argn; fd_t fd; char *fname; #ifdef BUILTIN_CPP struct inclist *incnew; struct inclist *incptr; #endif bool_t flag[128]; #if 0 lineptr = "\n"; /* empty line in case error message */ #endif fd = 0; /* standard input */ memset(flag, 0, sizeof flag); #ifdef I80386 flag['3'] = sizeof (int) >= 4; #endif fname = "stdin"; #ifdef BUILTIN_CPP (incptr = &incfirst)->incnext = &inclast; #endif initout(); for (argn = 1; argn < argc; ++argn) { arg = argv[argn]; if (*arg != '-') { if (fd != 0) fatalerror("more than one input file"); fname = arg; if ((fd = open(arg, 0)) < 0) fatalerror("cannot open input"); } else switch (arg[1]) { #ifdef I8088 case '0': /* generate 16-bit code */ #endif #ifdef I80386 case '3': /* generate 32-bit code */ #endif case 'c': /* caller saves */ #ifdef DBNODE case 'd': /* print debugging information in asm output */ #endif #ifdef BUILTIN_CPP case 'E': /* acting as cpp */ #endif case 'f': /* pass first argument in register */ #ifdef DYNAMIC_LONG_ORDER case 'l': /* long big-endian */ #endif case 'P': /* if acting as cpp, suppress line numbers */ #ifdef POSINDEPENDENT case 'p': /* generate almost-position-independent code */ #endif case 't': /* print source code in asm output */ case 'w': /* watch location counter */ case 'O': /* Optimisation. */ if (arg[2] == 0) flag[(int)arg[1]] = TRUE; else if (arg[2] == '-' && arg[3] == 0) flag[(int)arg[1]] = FALSE; else usage(); if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ flag['3'] = TRUE + FALSE - flag['0']; break; #ifdef BUILTIN_CPP case 'D': definestring(arg + 2); break; case 'I': (incnew = (struct inclist *) ourmalloc(sizeof *incnew)) ->incdirname = arg + 2; #ifdef TS ++ts_n_includelist; ts_s_includelist += sizeof *incnew; #endif incnew->incnext = incptr->incnext; incptr = incptr->incnext = incnew; break; case 'U': undefinestring(arg + 2); break; #endif case 'o': if (arg[2] != 0 || ++argn >= argc) usage(); openout(argv[argn]); break; default: usage(); break; } } #ifdef BUILTIN_CPP #ifdef I8088 #ifdef I80386 if (flag['3']) { i386_32 = TRUE; definestring("__AS386_32__"); definestring("__i386__"); } else #endif { definestring("__AS386_16__"); definestring("__8086__"); } #endif #ifdef MC6809 definestring("__AS09__"); #endif if (flag['c']) { callersaves = TRUE; definestring("__CALLER_SAVES__"); } #ifdef DBNODE dbnodeon = flag['d']; #endif orig_cppmode = cppmode = flag['E']; if (flag['f']) { arg1inreg = TRUE; #ifdef I8088 definestring("__FIRST_ARG_IN_AX__"); #endif #ifdef MC6808 definestring("__FIRST_ARG_IN_X__"); #endif } arg1op = arg1inreg ? ROOTLISTOP : LISTOP; #ifdef DYNAMIC_LONG_ORDER if (flag['l']) { long_big_endian = TRUE; definestring("__LONG_BIG_ENDIAN__"); } #endif suppress_line_numbers = flag['P']; #ifdef POSINDEPENDENT if (flag['p']) { posindependent = TRUE; definestring("__POS_INDEPENDENT__"); } #endif if (flag['O']) { optimise = TRUE; definestring("__OPTIMISED__"); } #ifdef NOFLOAT definestring("__HAS_NO_FLOATS__"); #endif #else /* !BUILTIN_CPP */ #ifdef I80386 if (flag['3']) i386_32 = TRUE; #endif if (flag['c']) callersaves = TRUE; #ifdef DBNODE dbnodeon = flag['d']; #endif if (flag['f']) arg1inreg = TRUE; arg1op = arg1inreg ? ROOTLISTOP : LISTOP; #ifdef DYNAMIC_LONG_ORDER if (flag['l']) long_big_endian = TRUE; #endif suppress_line_numbers = flag['P']; #ifdef POSINDEPENDENT if (flag['p']) posindependent = TRUE; #endif if (flag['O']) optimise = TRUE; #endif ctext = flag['t']; #ifdef DBNODE if (ctext) dbnodeon = 1; #endif watchlc = flag['w']; setoutbufs(); inputinit(fname, fd); } /* advance over EOL sentinel to new line */ PUBLIC void skipeol() { #ifdef FAKE_INBUFSIZE_1 static int ich; #endif #ifdef INSERT_BACKSLASH_NEWLINES static int bs_state; static bool_t skip_printing_nl; #endif int nread; debug(7, "skipeol %s:%d", inputbuf->fname, input.linenumber); if (eofile) return; if (lineptr < input.limit) { ++input.linenumber; ch = *++lineptr; if (ctext && !asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } #ifdef BUILTIN_CPP #ifndef ASM_BARE if (!virtual_nl && (orig_cppmode || asmmode)) #else if (orig_cppmode && !asmmode) #endif #ifdef INSERT_BACKSLASH_NEWLINES if (!skip_printing_nl) #endif outbyte('\n'); #else /* !BUILTIN_CPP */ if (asmmode) #ifdef INSERT_BACKSLASH_NEWLINES if (!skip_printing_nl) #endif outbyte('\n'); #endif #ifdef INSERT_BACKSLASH_NEWLINES if (bs_state == 1 && *(lineptr - 1) == EOL) #endif input.lineoffset = (int) (lineptr - inputbuf->fbuf); return; } input.lineoffset -= (int) (lineptr - inputbuf->fbuf); #ifdef FAKE_INBUFSIZE_1 lineptr = inputbuf->fbuf; #ifdef INSERT_BACKSLASH_NEWLINES switch (bs_state) { case0: case 0: bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1; skip_printing_nl = FALSE; break; case 1: if (ich == '\\') goto case0; /* avoid chance of splitting \EOL */ ich = '\\'; nread = 1; bs_state = 2; ++input.lineoffset; break; case 2: ich = EOL; nread = 1; bs_state = 0; skip_printing_nl = TRUE; ++input.lineoffset; --input.linenumber; break; } #else nread = (ich = getc(input.fp)) == EOF ? 0 : 1; #endif *lineptr = ich; #else #ifndef NO_EOFHACK if(input.fd<0) nread=0; else { #endif nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE); #ifndef NO_EOFHACK #ifdef BUILTIN_CPP if( nread == 0 && inclevel > 0 ) { close(input.fd); input.fd = -1; memcpy(inputbuf->fbuf, "\n", 1); nread = 1; } #endif } #endif #endif if (nread < 0) fatalerror("input error"); *(input.limit = lineptr + nread) = EOL; ch = *lineptr; if (nread == 0) { #ifdef BUILTIN_CPP if (inclevel == 0) { eofile = TRUE; checknotinif(); } else { leaveinclude(); skipeol(); } #else eofile = TRUE; #endif return; } if (ctext && !asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } } PUBLIC void specialchar() { #ifdef BUILTIN_CPP if (maclevel != 0) { if (ch == EOL) /* it might also be backslash or COEOL */ leavemac(); if (ch != EOL) return; } #endif more: #ifdef ARBITRARY_BACKSLASH_NEWLINES if (ch == '\\') backslash(); #endif if (!eofile && lineptr >= input.limit) { skipeol(); #ifdef ARBITRARY_BACKSLASH_NEWLINES if (ch == '\\') backslash(); #endif } #ifndef ARBITRARY_BACKSLASH_NEWLINES if (ch == '\\') { if (*(lineptr + 1) == EOL) { if (lineptr + 1 >= input.limit) { ++lineptr; skipeol(); ch = *--lineptr = '\\'; /* pushback */ } if (*(lineptr + 1) == EOL) { if (eofile) eofin("backslash-newline"); else { ++lineptr; skipeol(); if (SYMOFCHAR(ch) == SPECIALCHAR) { #ifdef COEOL if (ch != COEOL || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) #endif goto more; } } } } #endif } #ifdef COEOL if (ch == EOL && !eofile) { if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit) { ++lineptr; skipeol(); /* refill buffer */ ch = *--lineptr = EOL; /* pushback */ } if (*(lineptr + 1) == COEOL) *++lineptr = EOL; /* discard COEOL */ } #endif } PRIVATE void usage() { fatalerror( #ifdef BUILTIN_CPP # ifdef MC6809 "usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]" # else # ifdef I80386 "usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]" # else "usage: cc1 [-cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]" # endif # endif #else # ifdef I80386 "usage: cc1 [-03cdfltw[-]] [-o outfile] [infile]" # else "usage: cc1 [-cdfltw[-]] [-o outfile] [infile]" # endif #endif ); } dev86-0.16.17/bcc/dbnode.c0000644000000000000000000000745610065301037014715 0ustar rootroot00000000000000/* dbnode.c - print debug messages for operators for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #ifdef DBNODE #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "type.h" PRIVATE char *opname[LASTOP - FIRSTOP + 1] = /* operator names */ { /* order must agree with op.h */ "cond?", "or", "eor", "and", "gt", "lt", "add", "div", "mod", "lognot", "not", "strucelt", "strucptr", "eq", "addab", "andab", "divab", "eorab", "modab", "mulab", "orab", "slab", "srab", "subab", "comma", "cond:", "logor", "logand", "logeq", "ne", "ge", "le", "sl", "sr", "sub", "mul", "address", "cast", "indirect", "neg", "predec", "preinc", "postdec", "postinc", "func", "list", "rootlist", "leaf", "ptraddab", "ptradd", "ptrsub", }; FORWARD void outindchars P((int byte, indn_pt count)); PUBLIC void dbitem(item) struct symstruct *item; { dbtype(item->type); if (item->storage == NOSTORAGE) { outbyte(' '); outstr(item->name.namep + 2); outstr(" (offset "); outshex(item->offset.offi); outbyte(')'); return; } if (item->storage == LOCAL) { outbyte(' '); if (item->flags == TEMP) outstr("(temp)"); else outstr(item->name.namep); } outstr(" = "); outindchars('[', item->indcount); switch (item->storage) { case CONSTANT: outstr("const "); if (item->type->scalar & RSCALAR) outstr("(whatever)"); else if (item->type->scalar & UNSIGNED) outuvalue((uvalue_t) item->offset.offv); else outvalue(item->offset.offv); break; case BREG: case DREG: case INDREG0: case INDREG1: case INDREG2: #ifdef DATREG1 case DATREG1: #endif #ifdef DATREG2 case DATREG2: #endif outregname(item->storage); if (item->level == OFFKLUDGELEVEL) { outplus(); if (item->flags & LABELLED) outlabel(item->name.label); else outccname(item->name.namep); } break; case LOCAL: outbyte('S'); if (sp <= 0) outplus(); outshex(-sp); break; case GLOBAL: if (item->flags & LABELLED) outlabel(item->name.label); else outstr(item->name.namep); break; default: outstr("bad storage ("); outhex((uoffset_T) item->storage); outbyte(')'); outstr(" offset "); } if (item->storage != CONSTANT) { if (item->offset.offi >= 0) outplus(); outshex(item->offset.offi); } outindchars(']', item->indcount); } PUBLIC void dbtype(type) struct typestruct *type; { for ( ; type != NULL; type = type->nexttype) { outbyte(' '); switch (type->constructor) { case ARRAY: outbyte('['); outhex(type->typesize / type->nexttype->typesize); outbyte(']'); break; case FUNCTION: outstr("()"); break; case POINTER: outbyte('*'); break; case STRUCTU: outstr("struct "); default: if (type->scalar & UNSIGNED) outstr("unsigned "); outstr(type->tname); break; } } } PUBLIC void dbnode(exp) /* sub-nodes must be leaves */ struct nodestruct *exp; { if (!dbnodeon) return; outstr("! Debug: "); if (exp->tag < FIRSTOP && exp->tag > LASTOP) outstr("unknown op"); else outstr(opname[exp->tag - FIRSTOP]); if (exp->right != NULL && exp->tag != FUNCOP && exp->tag != LISTOP && exp->tag != ROOTLISTOP) { dbitem(exp->right->left.symptr); outstr(" to"); } dbitem(exp->left.nodeptr->left.symptr); outstr(" (used reg = "); if (reguse & INDREG0) outregname(INDREG0); if (reguse & INDREG1) outregname(INDREG1); if (reguse & INDREG2) outregname(INDREG2); outnstr(")"); } PUBLIC void dbnodeswap() { if (dbnodeon) outnstr("! Debug: expression subtree swapping"); } PRIVATE void outindchars(byte, count) int byte; indn_pt count; { while (count--) outbyte(byte); } #endif /* DBNODE */ dev86-0.16.17/bcc/Makefile0000644000000000000000000000256610065343051014755 0ustar rootroot00000000000000# # bcc Makefile # $Id$ # PREFIX=/usr CFLAGS =-O LDFLAGS =-s BINDIR =$(PREFIX)/bin LIBDIR =$(PREFIX)/lib/bcc BCCDEFS =-DLOCALPREFIX=$(PREFIX) -DBINDIR=$(BINDIR) -DDEFARCH=0 BCFLAGS=$(ANSI) $(CFLAGS) $(LDFLAGS) OBJS = bcc-cc1.o codefrag.o dbnode.o declare.o express.o exptree.o floatop.o \ function.o gencode.o genloads.o glogcode.o hardop.o input.o label.o \ loadexp.o longop.o output.o preproc.o preserve.o scan.o softop.o \ state.o table.o type.o assign.o hashcmd.o debug.o dbprintf.o all: bcc-cc1 bcc install: all install -d $(BINDIR) install -m 755 bcc $(BINDIR)/bcc install -d $(LIBDIR) install -m 755 bcc-cc1 $(LIBDIR)/bcc-cc1 bcc: bcc.c $(CC) $(BCFLAGS) $(BCCDEFS) bcc.c -o $@ ncc: bcc.c $(CC) $(BCFLAGS) -DLOCALPREFIX= -DDEFARCH=0 bcc.c -o $@ bcc09: bcc.c $(CC) $(BCFLAGS) -DMC6809 $(BCCDEFS) bcc.c -o $@ ccc: bcc.c $(CC) $(BCFLAGS) -DCCC $(BCCDEFS) bcc.c -o $@ bcc-cc1: $(OBJS) $(CC) $(BCCARCH) $(LDFLAGS) $(OBJS) -o bcc-cc1 debug.o: debug.c debug.h $(CC) $(ANSI) $(BCCARCH) $(CFLAGS) -c debug.c dbprintf.o: dbprintf.c $(CC) $(ANSI) $(BCCARCH) $(CFLAGS) -c dbprintf.c clean realclean: rm -f bcc bcc-cc1 ncc bcc09 ccc bcc.o $(OBJS) $(OBJS): bcc.h align.h const.h types.h \ byteord.h condcode.h gencode.h \ input.h label.h os.h output.h \ parse.h proto.h reg.h sc.h scan.h \ sizes.h table.h type.h .c.o: $(CC) $(BCCARCH) $(CFLAGS) -c $< dev86-0.16.17/bcc/bcc.c0000644000000000000000000007556110166345063014224 0ustar rootroot00000000000000/* * bcc.c Version 2001.1 * Complete rewrite because the old one was just too confusing! * * There are no significant compile time options (MC6809 and CCC * just change defaults) but you should set LOCALPREFIX. * * Personality flags are: * * -Mn Normal ELKS * -Md MSDOS * -Ms PC Standalone. * -Ml i386 Linux * -M8 CvW's c386 * -M9 MC6809 with bcc * -M0 A framework for the -B option. */ #include #ifdef __STDC__ #include #ifndef MSDOS #include #endif #else #include #endif #include #include #include #include #include #ifndef MSDOS #include #include #endif #include "version.h" #ifdef MSDOS #define LOCALPREFIX /linux86 #define EXESUF ".exe" #define R_OK 4 /* Test for read permission. */ #define W_OK 2 /* Test for write permission. */ #define X_OK 1 /* Test for execute permission. */ #define F_OK 0 /* Test for existence. */ #define DEFARCH 0 /* Default to 8086 code */ #include "version.h" #else #define EXESUF #endif #define AS "as" EXESUF #define LD "ld" EXESUF #define CPP "cpp" EXESUF #define CC1 "cc1" EXESUF #define OPT "opt" EXESUF #define CC1C386 "c386" EXESUF #define AS09 "as09" EXESUF #define LD09 "ld09" EXESUF #define CPPBCC "bcc-cpp" EXESUF #define CC1BCC "bcc-cc1" EXESUF #define AS86 "as86" EXESUF #define LD86 "ld86" EXESUF #define GCC "gcc" #define UNPROTO "unproto" EXESUF #define OPTIM "copt" EXESUF #if __STDC__ == 1 #define P(x) x #define HASHIT(x) #x #define QUOT(x) HASHIT(x) #else #define P(x) () /* Well you find something that works! */ #define QUOT(x) "x" #endif struct command { char * cmd; char * altcmd; char * fullpath; int numargs; int maxargs; char ** arglist; } command = { 0,0,0,0,0,0 }; struct file_list { struct file_list * next; char * file; char * oldfile; char * name; int filetype; /* Char, notional extention of file. */ } * files; struct opt_list { struct opt_list * next; char * opt; int opttype; /* Where the option should go */ } * options; int opt_v, opt_V, opt_e, opt_x, opt_I, opt_L, opt_W, opt_i, opt_O, opt_M, opt_f; #ifdef DEFARCH int opt_arch = (DEFARCH != 0); #else int opt_arch = sizeof (char *) >= 4; #endif int do_preproc = 1; /* c -> i */ int do_unproto = 0; /* i -> i */ int do_compile = 1; /* i -> s */ int do_optim = 0; /* s -> s */ int do_as = 1; /* s -> o */ int do_link = 1; /* o -> done */ char * executable_name = 0; int file_count = 0; int dyn_count = 0; int error_count = 0; char * progname = "C"; #ifdef MSDOS char * tmpdir = ""; #else char * tmpdir = "/tmp/"; #endif int main P((int argc, char **argv)); void getargs P((int argc, char **argv)); void add_prefix P((char * path)); void build_prefix P((char * path1, char * path2, char * path3)); void run_aspreproc P((struct file_list * file)); void run_preproc P((struct file_list * file)); void run_unproto P((struct file_list * file)); void run_compile P((struct file_list * file)); void run_optim P((struct file_list * file)); void run_as P((struct file_list * file)); void run_link P((void)); void command_reset P((void)); void command_opt P((char * option)); void command_arch P((void)); void command_opts P((int opykey)); void newfilename P((struct file_list * file, int last_stage, int new_extn, int use_o)); void run_unlink P((void)); void validate_link_opts P((void)); void append_file P((char * filename, int ftype)); void append_option P((char * option, int otype)); void prepend_option P((char * option, int otype)); char * build_libpath P((char * opt, char * str, char * suffix)); void * xalloc P((int size)); void Usage P((void)); void fatal P((char * why)); char * copystr P((char * str)); char * catstr P((char * str, char * str2)); void reset_prefix_path P((void)); void run_command P((struct file_list * file)); char * prefix_path = ""; #ifdef LOCALPREFIX char * localprefix = QUOT(LOCALPREFIX); #else char * localprefix = "/"; #endif /* These paths are NATIVE install paths, change others below */ char * default_include = "/usr/include"; char * optim_rules = "/lib"; #ifdef LIBDIR char * default_libdir = QUOT(LIBDIR); #else char * default_libdir = "/lib"; #endif char * libdir_suffix = ""; char devnull[] = "/dev/null"; char * exec_prefixs[16] = { 0 /* Last chance is contents of $PATH */ }; char * libc = "-lc"; int main(argc, argv) int argc; char ** argv; { struct file_list * next_file; char * temp; progname = argv[0]; if ((temp = getenv("BCC_PREFIX")) != 0 ) localprefix = copystr(temp); getargs(argc, argv); validate_link_opts(); reset_prefix_path(); if (!*localprefix || !localprefix[1]) { if (*localprefix == '/') { /* Paths for full NATIVE install "-M/" */ build_prefix(default_libdir, libdir_suffix, ""); build_prefix(default_libdir, "", ""); default_include = build_libpath("-I", "/usr/include", ""); default_libdir = build_libpath("-L", default_libdir, libdir_suffix); optim_rules = build_libpath("-d", optim_rules, libdir_suffix); #if 0 } else if (*localprefix == '+') { /* Paths for a special */ #endif } else { /* Relative paths to a build dir "-M-" */ build_prefix("/lib", libdir_suffix, ""); build_prefix("/lib", "", ""); default_include = build_libpath("-I", "/include", ""); default_libdir = build_libpath("-L", "/lib", libdir_suffix); optim_rules = build_libpath("-d", "/lib", libdir_suffix); } } else { /* Relative paths to normal PREFIX directory */ default_include = build_libpath("-I", "/lib/bcc/include", ""); default_libdir = build_libpath("-L", "/lib/bcc", libdir_suffix); optim_rules = build_libpath("-d", "/lib/bcc", libdir_suffix); build_prefix("/lib/bcc", libdir_suffix, ""); build_prefix("/lib/bcc", "", ""); } build_prefix("/bin", "", ""); #ifdef BINDIR add_prefix(QUOT(BINDIR) "/"); #endif if (opt_v>1) { command.cmd = ""; command_reset(); } for(next_file = files; next_file && !error_count; next_file = next_file->next) { if (next_file->filetype == 'o') continue; if (opt_V) fprintf(stderr, "%s:\n", next_file->file); /* Assembler that's not to be optimised. */ if (do_preproc && next_file->filetype == 'x') run_aspreproc(next_file); if (do_preproc && next_file->filetype == 'S') run_aspreproc(next_file); if (do_as && next_file->filetype == 's') run_as(next_file); /* C source */ if (do_preproc && next_file->filetype == 'c') run_preproc(next_file); if (do_unproto && do_compile && next_file->filetype == 'i') run_unproto(next_file); if (do_compile && next_file->filetype == 'i') run_compile(next_file); if (do_optim && next_file->filetype == 's') run_optim(next_file); if (do_as && next_file->filetype == 's') run_as(next_file); } if (do_link && !error_count) run_link(); run_unlink(); exit(error_count>0); } char * copystr(str) char * str; { return strcpy(xalloc(strlen(str)+1), str); } char * catstr(str, str2) char * str, * str2; { return strcat(strcpy(xalloc(strlen(str)+strlen(str2)+1), str), str2); } void run_aspreproc(file) struct file_list * file; { static char cc1bcc[] = CC1BCC; if (opt_arch<5) { if (opt_e) command.cmd = cc1bcc; else { command.cmd = CPPBCC; command.altcmd = cc1bcc; } } else command.cmd = CPP; command_reset(); newfilename(file, (!do_as && !do_optim), (do_compile?'s':'i'), (opt_arch<5)); if (opt_arch<5 && command.cmd == cc1bcc) command_opt("-E"); else if (opt_arch<5 && do_unproto) command_opt("-A"); command_opts('p'); command_opt("-D__ASSEMBLER__"); command_arch(); run_command(file); } void run_preproc(file) struct file_list * file; { int last_stage = 0; int combined_cpp; static char cc1bcc[] = CC1BCC; if (opt_arch<5) { if (opt_e) command.cmd = cc1bcc; else { command.cmd = CPPBCC; command.altcmd = cc1bcc; } } else command.cmd = CPP; command_reset(); combined_cpp = (command.cmd == cc1bcc && opt_arch != 3 && opt_e < 2 && !do_unproto && do_compile); if (combined_cpp && !do_optim && !do_as ) last_stage =1; if (!combined_cpp && !do_compile ) last_stage =1; newfilename(file, last_stage, (combined_cpp?'s':'i'), (opt_arch<5)); if (!combined_cpp && opt_arch<5) { if (command.cmd == cc1bcc) command_opt("-E"); else if (do_unproto) command_opt("-A"); } command_opts('p'); command_opts('C'); if (combined_cpp) { if (opt_arch<5 && !do_as) command_opt("-t"); command_opts('c'); } if (!opt_I) command_opt(default_include); command_arch(); run_command(file); } void run_unproto(file) struct file_list * file; { command.cmd = UNPROTO; command_reset(); newfilename(file, !do_compile, 'i', 0); command_opts('u'); run_command(file); } void run_compile(file) struct file_list * file; { if (opt_arch == 3) command.cmd = CC1C386; else if (opt_arch<5) command.cmd = CC1BCC; else command.cmd = CC1; command_reset(); newfilename(file, !(do_optim || do_as), 's', (opt_arch != 3 && opt_arch<5)); if (opt_arch<5 && !do_as) command_opt("-t"); command_opts('c'); command_opts('C'); command_arch(); run_command(file); } void run_optim(file) struct file_list * file; { char buf[32]; if (opt_arch<5) command.cmd = OPTIM; else command.cmd = OPT; command_reset(); newfilename(file, !do_as, 's', 1); command_opt("-c!"); if (opt_O && opt_arch == 0) { sprintf(buf, "-huse16 %c86", opt_O); command_opt(buf); } command_opt(optim_rules); command_opt("rules.start"); command_opts('o'); if (opt_O) { if (opt_arch == 0) sprintf(buf, "rules.%c86", opt_O); else sprintf(buf, "rules.lv_%c", opt_O); command_opt(buf); } switch(opt_arch) { case 0: command_opt("rules.86"); break; case 1: case 2: command_opt("rules.i386"); break; case 4: command_opt("rules.6809"); break; default:command_opt("rules.mid"); break; } command_opt("rules.end"); run_command(file); } void run_as(file) struct file_list * file; { char * buf; switch(opt_arch) { case 0: case 1: case 2: command.cmd = AS86; break; case 4: command.cmd = AS09; break; default: command.cmd = AS; break; } command_reset(); newfilename(file, (!do_link && opt_arch!=2), 'o', 1); if (opt_arch==3) command_opt("-j"); if (opt_arch<5) command_opt("-u"); command_opts('a'); if (opt_W) command_opt("-w-"); else command_opt("-w"); command_arch(); command_opt("-n"); buf = catstr(file->name, ".s"); command_opt(buf); free(buf); run_command(file); if (opt_arch == 2) { command.cmd = LD86; command_reset(); command_opt("-r"); command_opt("-N"); newfilename(file, !do_link, 'o', 1); run_command(file); } } void run_link() { struct file_list * next_file; switch(opt_arch) { case 0: case 1: command.cmd = LD86; break; case 2: command.cmd = GCC; break; case 4: command.cmd = LD09; break; default: command.cmd = LD; break; } command_reset(); if (executable_name) { command_opt("-o"); command_opt(executable_name); } if (opt_arch < 2) command_opt("-y"); command_opts('l'); if (opt_arch != 2) { if (opt_arch == 0 && !opt_i) command_opt("-i"); if (!opt_L) command_opt(default_libdir); command_arch(); if (!opt_x) command_opt("-C0"); } /* Current Debian compilers only work in with this: */ else command_opt("--static"); for(next_file = files; next_file; next_file = next_file->next) command_opt(next_file->file); if (opt_arch != 2) command_opt(libc); run_command(0); } void validate_link_opt(char * option) { int err = 0; if (option[0] != '-') return; switch(option[1]) { default: err = 1; break; case '0': /* use 16-bit libraries */ case '3': /* use 32-bit libraries */ case 'M': /* print symbols linked */ case 'i': /* separate I & D output */ case 'm': /* print modules linked */ case 's': /* strip symbols */ case 't': /* trace modules linked */ case 'z': /* unmapped zero page */ case 'N': /* Native format a.out */ case 'd': /* Make a headerless outfile */ case 'c': /* Write header in CP/M-86 format */ case 'y': /* Use a newer symbol table */ if (option[2] != 0 && option[2] != '-') err = 1; break; case 'C': /* startfile name */ case 'L': /* library path */ case 'O': /* library file name */ case 'T': /* text base address */ case 'D': /* data base address */ case 'H': /* heap top address */ case 'l': /* library name */ case 'o': /* output file name */ break; } if (err) { if (do_link) fprintf(stderr, "warning: unknown option %s passed to linker.\n", option); else fprintf(stderr, "warning: option %s not recognised.\n", option); } else if (!do_link) fprintf(stderr, "warning: linker option %s unused.\n", option); } void validate_link_opts() { struct opt_list * ol; struct file_list * next_file; if (opt_arch>1) return; /* Only check ld86 options */ for(ol=options; ol; ol=ol->next) if (ol->opttype == 'l') validate_link_opt(ol->opt); for(next_file = files; next_file; next_file = next_file->next) validate_link_opt(next_file->file); if (!do_link) { if (opt_i) fprintf(stderr, "warning: linker option -i unused.\n"); if (opt_x) fprintf(stderr, "warning: linker option -x unused.\n"); if (opt_L) fprintf(stderr, "warning: linker option -L unused.\n"); } } void command_reset() { #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif char buf[MAXPATHLEN]; char ** prefix; char * saved_cmd; if (command.arglist) { int i; for(i=0; inext) if (ol->opttype == optkey) command_opt(ol->opt); } void newfilename(file, last_stage, new_extn, use_o) struct file_list * file; int last_stage; int new_extn; int use_o; { file->filetype = new_extn; if (file->oldfile) free(file->oldfile); file->oldfile = file->file; file->file = 0; if (last_stage) { if (executable_name) file->file = copystr(executable_name); else { char buf[4]; buf[0] = '.'; buf[1] = file->filetype; buf[2] = 0; file->file = catstr(file->name, buf); } } else { char buf[16]; #ifdef MSDOS sprintf(buf, "$$%05d$", dyn_count++); #else sprintf(buf, "$$%04d%05d", dyn_count++, getpid()); #endif file->file = catstr(tmpdir, buf); } command_opt(file->oldfile); /* *.i files go to the stdout */ if (last_stage && file->filetype == 'i') return; if (use_o) command_opt("-o"); command_opt(file->file); } void run_unlink() { int i; for(i=0; i1) fprintf(stderr, "rm %s\n", p); if (opt_v>2) continue; if (unlink(p) < 0) { if (error_count==0 || opt_v>1) fprintf(stderr, "Error unlinking %s\n", p); error_count++; } free(p); } } void getargs(argc, argv) int argc; char ** argv; { int ar; char * pflag = 0; int control_count = 0; int exe_count = 0; for(ar=1; ar= '1' && opt_arg[0] <= '9' )) opt_O = opt_arg[0]; else if (opt_arg[0] == '-') append_option(opt_arg, 'o'); else { char * p = xalloc(strlen(opt_arg)+8); strcpy(p, "rules."); strcat(p, opt_arg); append_option(p, 'o'); free(p); } break; case 'o': exe_count++; executable_name = opt_arg; break; case 'B': add_prefix(opt_arg); break; case 'I': case 'D': case 'U': append_option(argv[ar], 'p'); break; case 'T': tmpdir = catstr(opt_arg, "/"); break; case 'M': if (opt_arg[0] == '/') { localprefix = copystr(opt_arg); break; } if (opt_arg[1]) Usage(); if (opt_arg[0] == '-') { localprefix = ""; break; } opt_M = *opt_arg; break; default: pflag = argv[ar]+1; used_arg = 0; break; } /* Singleton flags */ if(pflag) switch(opt = *pflag++) { case 'P': append_option("-P", 'p'); /*FALLTHROUGH*/ case 'E': control_count++; do_compile = do_link = do_as = 0; break; case 'S': control_count++; do_as = do_link = 0; break; case 'c': control_count++; do_link = 0; break; case 'O': do_optim=1; break; case 'G': opt_M = 'g'; break; case 'v': opt_v++; break; case 'V': opt_V++; break; case 'e': opt_e++; break; case 'x': opt_x++; break; case 'I': opt_I++; break; case 'L': opt_L++; break; case 'i': opt_i++; break; case 'f': opt_f++; break; case 'W': opt_W++; break; case '0': opt_arch=0; break; case '3': opt_arch=1; break; case 'w': /*IGNORED*/ break; case 'g': /*IGNORED*/ break; case 'p': /*IGNORED*/ break; default: if (pflag == argv[ar]+2) { /* Special; unknown options saved as flags for the linker */ append_file(argv[ar], 'o'); pflag = 0; } else Usage(); } if (!pflag || !*pflag) { ar++; pflag = 0; } if (used_arg && inc_ar) ar++; if (used_arg && inc_ar==2) fatal("Last option requires an argument"); } if (control_count>1) fatal("only one option from -E -P -S -c allowed"); if (exe_count>1) fatal("only one -o option allowed"); if (file_count==0) Usage(); if (exe_count && file_count != 1 && !do_link) fatal("only one input file for each non-linked output"); add_prefix(getenv("BCC_EXEC_PREFIX")); #ifdef MC6809 if (opt_M==0) opt_M = '9'; #endif #ifdef CCC if (opt_M==0) opt_M = '8'; #endif #ifdef MSDOS if (opt_M==0) opt_M = 'd'; #endif #ifdef __CYGWIN__ if (opt_M==0) opt_M = 'd'; #endif if (opt_M==0) opt_M = (opt_arch==1 ?'l':'n'); switch(opt_M) { case 'n': /* Normal Elks */ prepend_option("-D__unix__", 'p'); prepend_option("-D__ELKS__", 'p'); libc="-lc"; break; case 'f': /* Fast Call Elks */ prepend_option("-D__unix__", 'p'); prepend_option("-D__ELKS__", 'p'); append_option("-c", 'C'); append_option("-f", 'C'); libc="-lc_f"; break; case 'c': /* Caller saves Elks */ prepend_option("-D__unix__", 'p'); prepend_option("-D__ELKS__", 'p'); append_option("-c", 'C'); libc="-lc"; break; case 's': /* Standalone 8086 */ prepend_option("-D__STANDALONE__", 'p'); libc="-lc_s"; break; case 'd': /* DOS COM file */ prepend_option("-D__MSDOS__", 'p'); if (do_link) { libc="-ldos"; append_option("-d", 'l'); append_option("-T100", 'l'); } break; case 'l': /* 386 Linux a.out */ opt_arch=1; prepend_option("-D__unix__", 'p'); prepend_option("-D__linux__", 'p'); if (do_link) { libc="-lc"; append_option("-N", 'l'); } break; case 'g': /* 386 Linux object using gcc as linker */ opt_arch = 2; prepend_option("-D__unix__", 'p'); prepend_option("-D__linux__", 'p'); /* This is a more traditional libc, it also gives a 20k executable * for hello world vs. 400k with glibc2 and --static. * NB: DLL libc no longer seems to work. */ add_prefix("/usr/bin/i386-uclibc-"); break; case '8': /* Use 'c386' program as compiler */ opt_arch = 3; prepend_option("-D__unix__", 'p'); prepend_option("-D__c386__", 'p'); break; case '9': /* 6809 compiler */ opt_arch = 4; prepend_option("-D__6809__", 'p'); break; case '0': /* Plain old Unix V7 style */ opt_arch = 5; opt_I = 1; opt_L = 1; opt_x = 1; append_option("/lib/crt0.o", 'l'); break; default: fatal("Unknown model specifier for -M valid are: n,f,c,s,d,l,g,8,9,0"); } if (do_optim) { append_option("-O", 'C'); append_option("-O", 'a'); } if (opt_arch == 0) { if (opt_f) { /* append_option("--enable-floats", 'c'); */ libc = catstr(libc, "+f"); } else append_option("-D__HAS_NO_FLOATS__", 'p'); } if (opt_arch == 1) libdir_suffix = "/i386"; if (opt_arch == 4) libdir_suffix = "/m09"; #ifdef VERSION { char verbuf[64]; sprintf(verbuf, "-D__BCC_VERSION__=0x%02x%02x%02xL", VER_MAJ, VER_MIN, VER_PAT); append_option(verbuf, 'p'); } #endif } void build_prefix(path1, path2, path3) char * path1, * path2, * path3; { char * newstr; int l; newstr = xalloc(strlen(path1)+strlen(path2)+strlen(path3) + strlen(prefix_path)+2); strcpy(newstr, prefix_path); strcat(newstr, path1); strcat(newstr, path2); strcat(newstr, path3); l = strlen(newstr); if (l>1 && newstr[l-1] != '/') strcat(newstr, "/"); add_prefix(newstr); } void add_prefix(path) char * path; { char ** p; if (!path || !*path) return; for( p=exec_prefixs; pfile = copystr(filename); name = copystr(filename); s = strrchr(name, '.'); if (ftype) { newfile->name = copystr(name); newfile->filetype = ftype; } else if (s && s == name + strlen(name) - 2) { newfile->filetype = s[1]; *s = 0; newfile->name = copystr(name); } else newfile->name = copystr(name); free(name); if (newfile->filetype == 0) newfile->filetype = 'o'; /* Objects */ if (files==0) files = newfile; else { struct file_list * fptr; for(fptr=files; fptr->next; fptr=fptr->next); fptr->next = newfile; } } void append_option (option, otype) char * option; int otype; { struct opt_list * newopt = xalloc(sizeof(struct opt_list)); newopt->opt = copystr(option); newopt->opttype = otype; if (options==0) options = newopt; else { struct opt_list * optr; for(optr=options; optr->next; optr=optr->next); optr->next = newopt; } } void prepend_option (option, otype) char * option; int otype; { struct opt_list * newopt = xalloc(sizeof(struct opt_list)); newopt->opt = copystr(option); newopt->opttype = otype; newopt->next = options; options = newopt; } char * build_libpath(opt, str, suffix) char * opt, * str, * suffix; { char * newstr; newstr = xalloc(strlen(opt)+strlen(str)+strlen(prefix_path)+strlen(suffix)+1); strcpy(newstr, opt); strcat(newstr, prefix_path); strcat(newstr, str); strcat(newstr, suffix); return newstr; } void * xalloc (size) int size; { void * p = malloc(size); if (!p) fatal("Out of memory"); memset(p, '\0', size); return p; } void Usage() { #ifdef VERSION #ifdef __AS386_16__ if (opt_v) fprintf(stderr, "%s: version %s (16bit)\n", progname, VERSION); #else if (opt_v) fprintf(stderr, "%s: version %s\n", progname, VERSION); #endif #endif fprintf(stderr, "Usage: %s [-ansi] [-options] [-o output] file [files].\n", progname); exit(1); } void fatal(str) char * str; { fprintf(stderr, "%s: Fatal error: %s.\n", progname, str); exit(1); } #ifdef MSDOS void reset_prefix_path() { char *ptr, *temp; if (*localprefix && localprefix[1]) { prefix_path = localprefix; return; } temp = copystr(progname); if( (ptr = strrchr(temp, '\\')) != 0 && temp2) return; } #ifdef MSDOS status = spawnv(0, command.fullpath, command.arglist); if (status<0) { fprintf(stderr, "Unable to execute %s\n", command.fullpath); } #else oqsig = signal(SIGQUIT, SIG_IGN); oisig = signal(SIGINT, SIG_IGN); otsig = signal(SIGTERM, SIG_IGN); ocsig = signal(SIGCHLD, SIG_DFL); switch(fork()) { case -1: fatal("Forking failure"); case 0: (void) signal(SIGQUIT, SIG_DFL); (void) signal(SIGINT, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); (void) signal(SIGCHLD, SIG_DFL); #ifdef __BCC__ execve(command.fullpath, command.arglist, minienviron); #else if (command.fullpath[0] =='/') execv(command.fullpath, command.arglist); else execvp(command.fullpath, command.arglist); #endif fprintf(stderr, "Unable to execute %s.\n", command.fullpath); exit(1); default: wait(&status); if (status&0xFF) { fprintf(stderr, "%s: killed by signal %d\n", command.fullpath, (status&0xFF)); } } (void) signal(SIGQUIT, oqsig); (void) signal(SIGINT, oisig); (void) signal(SIGTERM, otsig); (void) signal(SIGCHLD, ocsig); #endif if (status) { if (file) file->filetype = '~'; error_count++; } } dev86-0.16.17/bcc/longop.c0000644000000000000000000000771310057677567015005 0ustar rootroot00000000000000/* longop.c - software operations on longs for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "reg.h" #include "scan.h" #include "type.h" /*----------------------------------------------------------------------------- longop(operation code, source leaf, target leaf) handles all binary operations on longs source and target must already have been converted to long, (except source is int for shifts) and not more than singly indirect hence they must be direct (in an index reg paired with DREG), or singly indirect (local, global, or from an index reg) -----------------------------------------------------------------------------*/ PUBLIC void longop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_pt reglist; store_t regmark; bool_t shiftflag; scalar_t scalar; offset_T spmark; pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG)); reguse &= ~reglist; spmark = sp; shiftflag = FALSE; scalar = target->type->scalar; if ((op_t) op == SLOP || (op_t) op == SROP) shiftflag = TRUE; else scalar |= source->type->scalar; if ((source->indcount == 0 && !shiftflag) || source->type->scalar & CHAR || source->storage & (BREG | DREG | OPREG | OPWORKREG)) { pres2(source, target); push(source); } if (!shiftflag) address(source); load(target, OPREG); if (source->storage == CONSTANT && shiftflag) { if (scalar & UNSIGNED) target->type = ultype; if ((op_t) op == SLOP) source->offset.offv = lslconst(source->offset.offv, target->storage); else source->offset.offv = lsrconst(source->offset.offv, target->storage, scalar & UNSIGNED); if (source->offset.offv == 0) goto shiftdone; } #ifdef I8088 /* This is ugly! But it works. I should be able to stop it being used * by removing the char demotion. */ if (source->type->scalar & CHAR && !(source->storage & (BREG|DREG|DATREG1B))) { load(source, DATREG1B); outop2str("xor\tch,ch"); outnl(); source->storage = DATREG1; } #endif load(source, OPWORKREG); switch ((op_t) op) { case ADDOP: call("ladd"); break; case ANDOP: call("land"); break; case DIVOP: call("ldiv"); break; case EOROP: call("leor"); break; case EQOP: call("lcmp"); break; case MODOP: call("lmod"); break; case MULOP: call("lmul"); break; case OROP: call("lor"); break; case SLOP: call("lsl"); break; case SROP: call("lsr"); break; case SUBOP: call("lsub"); break; } if (scalar & UNSIGNED) { outbyte('u'); target->type = ultype; } outlongendian(); shiftdone: if ((reguse = regmark) & OPREG && op != EQOP) load(target, getindexreg()); if (reglist) { #ifdef I8088 if (op == EQOP) changesp(spmark, FALSE); else #endif modstk(spmark); poplist(reglist); } } /*----------------------------------------------------------------------------- long1op(operation code, target leaf) handles all unary operations on longs except inc/dec target must be not more than singly indirect hence it must be direct (in an index reg paired with DREG), or singly indirect (local, global, or from an index reg) -----------------------------------------------------------------------------*/ PUBLIC void long1op(op, target) op_pt op; struct symstruct *target; { pushlist(reguse & OPREG); load(target, OPREG); if (op == NOTOP) call("lcom"); else if (op == NEGOP) call("lneg"); else call("ltst"); outlongendian(); if (reguse & OPREG) { if (op != EQOP) load(target, getindexreg()); poplist(reguse & OPREG); } } PUBLIC void outlongendian() { #ifdef MC6809 outbyte('_'); #endif #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN outnbyte('b'); #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 outnbyte('l'); #endif } dev86-0.16.17/bcc/sizes.h0000644000000000000000000000363310057542327014627 0ustar rootroot00000000000000/* sizes.h - target scalar type sizes for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* the compiler is not very portable in this area it only directly supports I8088-I80386 and MC6809 it assumes sizeof(source long) >= sizeof(target long) usual register size = int long = 2 int sizes */ #define CHBITSTO 8 /* bits in a character */ #define CHMASKTO 0xFF /* mask to reduce SOURCE int to TARGET uchar */ #define INT16BITSTO 16 /* not accessed in non-16 bit case */ #define INT32BITSTO 32 /* not accessed in non-32 bit case */ #define MAXINTBITSTO 32 /* max bits in an integer (var processors) */ #define MAXSCHTO 127 /* maximum signed character */ #define MAXUCHTO 255 /* maximum unsigned character */ #define MINSCHTO (-128) /* minimum signed character */ #ifdef MC6809 # define is5bitoffset(n) ((uoffset_T) (n) + 0x10 < 0x20) #endif #define isbyteoffset(n) ((uoffset_T) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO) #define ischarconst(n) ((uvalue_t) (n) <= MAXUCHTO) #define isnegbyteoffset(n) ((uvalue_t) (n) + MAXSCHTO <= MAXSCHTO - MINSCHTO) #define isshortbranch(n) ((uoffset_T) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO) #ifdef MC6809 /* Hack to reduce number of direct page variables. */ #define intmaskto ((uvalue_t) 0xFFFFL) #define maxintto ((uvalue_t) 0x7FFFL) #define maxlongto ((uvalue_t) 0x7FFFFFFFL) #define maxoffsetto ((uvalue_t) 0x7FFFL) #define maxshortto ((uvalue_t) 0x7FFFL) #define maxuintto ((uvalue_t) 0xFFFFL) #define maxushortto ((uvalue_t) 0xFFFFL) #define shortmaskto ((uvalue_t) 0xFFFFL) #else extern uvalue_t intmaskto; /* mask for ints */ extern uvalue_t maxintto; /* maximum int */ extern uvalue_t maxlongto; /* maximum long */ extern uvalue_t maxoffsetto; /* maximum offset */ extern uvalue_t maxshortto; /* maximum short */ extern uvalue_t maxuintto; /* maximum unsigned */ extern uvalue_t maxushortto; /* maximum unsigned short */ extern uvalue_t shortmaskto; /* mask for shorts */ #endif dev86-0.16.17/bcc/output.h0000644000000000000000000000101605301213541015010 0ustar rootroot00000000000000/* output.h - output for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define OUTBYTE(ch) \ do {register char *outp = outbufptr; *outp++ = (ch); \ outbufptr = outp; if (outp >= outbuftop) flushout(); } while (0) EXTERN bool_t ctext; /* nonzero to intermix C source */ /* depends on zero init */ EXTERN char *outbufptr; /* current spot in output buffer */ EXTERN char *outbuftop; /* top of current output buffer */ EXTERN bool_t watchlc; /* nonzero to print lc after every line */ /* depends on zero init */ dev86-0.16.17/bcc/codefrag.c0000644000000000000000000007765110057551126015247 0ustar rootroot00000000000000/* codefrag.c - code fragments for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "condcode.h" #include "gencode.h" #include "label.h" #include "output.h" #include "reg.h" #include "scan.h" #include "sizes.h" #define DEFSTR_BYTEMAX 10 #define DEFSTR_DELIMITER '"' #define DEFSTR_STRINGMAX 40 #define EOS_TEXT '0' #define MAXPRINTCHAR '~' #define MINPRINTCHAR ' ' /* segment numbers */ #ifdef I8088 # define CSEG 0 # define outcseg() outop0str(".text\n") # define DSEG 1 # define outdseg() outop0str(".data\n") # define BSSSEG 2 # define outbssseg() outop0str(".bss\n") #endif #ifdef MC6809 # define CSEG 0 # define outcseg() outop0str("LOC\t0\n") # define DPSEG 2 # define outdpseg() outop0str("LOC\t2\n") # define DSEG 3 # define outdseg() outop0str("LOC\t3\n") # define STRSEG 1 # define outstrseg() outop0str("LOC\t1\n") #endif #ifdef I8088 FORWARD void adjcarry P((void)); #endif FORWARD void clr P((store_pt reg)); FORWARD bool_pt lowregisDreg P((void)); #ifdef I8088 FORWARD void outand P((void)); FORWARD void outequate P((void)); # ifdef XENIX_AS FORWARD void outexport P((void)); # endif FORWARD void outmovsx P((void)); FORWARD void outmovzx P((void)); FORWARD void tfrhilo P((void)); FORWARD void tfrlohi P((void)); #endif #ifdef MC6809 FORWARD void negBsbcA P((void)); #endif FORWARD void outaccum P((void)); FORWARD void outstackreg P((void)); FORWARD void opregadr P((void)); /* operator and miscellaneous strings */ #ifdef I8088 # define ACCHISTR "ah" # define ANDSTRING "and\t" # define DEFSTR_QUOTER '\\' # define EORSTRING "xor\t" # define MAX_INLINE_SHIFT 2 /* better 3 for 88, 1 for 186 and above */ # define ORSTRING "or\t" # define TARGET_FIRST # define addfactor(reg) (outadd(), outregname(reg), outncregname(DXREG)) # define defstorage() outop0str(".blkb\t") # define extBnegD() (ctoi(), negDreg()) # define finishfactor() /* save/add/subfactor() ended already */ # define outadc() outop3str("adc\t") # define outandac() (outand(), outaccum(), bumplc()) # define outandlo() (outand(), outstr(acclostr)) # define outbimmed() outbyte('*') # define outcommon() outop0str(".comm\t") # define outcwd() outnop1str("cwd") # define outdefstr() outop0str(".ascii\t\"") # define outexchange() outop1str("xchg\t") # define outglobl() outop0str(".globl\t") # ifdef XENIX_AS # define outimport() outexport() # else # define outexport() outop0str("export\t") # define outimport() outop0str("import\t") # endif # ifdef XENIX_AS # define outj1switch() outop3str("seg\tcs\nbr\t@"); # else # define outj1switch() outop3str("seg\tcs\nbr\t"); # endif # define outj2switch() \ (outindleft(), outstr(ireg0str), outindright(), bumplc2(), outnl()) # define outlcommon() outop0str("\tlcomm\t") # define outlswitch() (outload(), outstr(ireg0str), outncregname(DREG)) # define outnc1() outnstr(",*1") # define outsbc() outop3str("sbb\t") # define outset() outstr ("\tset\t") # define outsl() outop2str("shl\t") # define outsr() outop2str("sar\t") # define outtransfer() outload() # define outusr() outop2str("shr\t") # define outxor() outop2str(EORSTRING) # define reclaimfactor() /* factor in DXREG, DXREG now junk */ # define savefactor(reg) regtransfer((reg), DXREG) # define smiDreg() (outcwd(), regexchange(DREG, DXREG)) # define sr1() (outsr(), outaccum(), outnc1()) # define subfactor(reg) (outsub(), outregname(reg), outncregname(DXREG)) # define usr1() (outusr(), outaccum(), outnc1()) PRIVATE void adjcarry() { outop3str("rcl\t"); outregname(DXREG); outncimmadr((offset_T) 9); outand(); bumplc2(); bumplc2(); outregname(DXREG); outncimmadr((offset_T) 0x100); } PUBLIC void clrBreg() { outxor(); outstr(acclostr); outncregname(BREG); } PUBLIC void comment() { outstr("! "); } PUBLIC void ctoi() { #ifdef I80386 if (i386_32) { outmovzx(); outaccum(); outncregname(BREG); } else #endif { outxor(); outhiaccum(); outcomma(); outhiaccum(); outnl(); } } PUBLIC void defbyte() { outop0str(".byte\t"); } #ifdef XENIX_AS PUBLIC void defword() { } /* don't have to print ".word\t" */ #else PUBLIC void defword() { outop0str(".word\t"); } #endif PUBLIC void defdword() { outop0str("dd\t"); } PUBLIC void even() { outop0str(".even\n"); } PUBLIC void negDreg() { outop2str("neg\t"); outnregname(DREG); } PUBLIC void comDreg() { outop2str("not\t"); outnregname(DREG); } PUBLIC void outadd() { outop2str("add\t"); } PUBLIC void outaddsp() { outadd(); outstackreg(); outcomma(); outimmed(); bumplc2(); } PRIVATE void outand() { outop2str(ANDSTRING); } #ifdef XENIX_AS PUBLIC void outcalladr() { outop2str("call\t@"); } #else PUBLIC void outcalladr() { outop2str("call\t"); } #endif PUBLIC void outcmp() { outop2str("cmp\t"); } PUBLIC void outdec() { outop1str("dec\t"); } PUBLIC void outdword() { outstr("dword "); } PRIVATE void outequate() { outop0str("\t=\t"); } #ifdef XENIX_AS PRIVATE void outexport() { outop0str(".globl\t"); } #endif PUBLIC void outfail() { outop0str(".fail\t"); } PUBLIC void outinc() { outop1str("inc\t"); } #ifdef XENIX_AS PUBLIC void outindleft() { outbyte('('); } PUBLIC void outindright() { outbyte(')'); } #else PUBLIC void outindleft() { outbyte('['); } PUBLIC void outindright() { outbyte(']'); } #endif #ifndef FRAMEPOINTER PUBLIC void outindstackreg() { outindleft(); outregname(STACKREG); outindright(); } #endif PUBLIC void outldaccum() { outload(); outaccum(); outcomma(); } PUBLIC void outldmulreg() { outload(); outregname(MULREG); outcomma(); } PUBLIC void outlea() { outop2str("lea\t"); } PUBLIC void outleasp() { outlea(); outstackreg(); outcomma(); } PUBLIC void outload() { outop2str("mov\t"); } PRIVATE void outmovsx() { outop3str("movsx\t"); } PRIVATE void outmovzx() { outop3str("movzx\t"); } PUBLIC void outmulmulreg() { outop2str("mul\t"); outnregname(MULREG); } PUBLIC void outopsep() { outcomma(); } PUBLIC void outpshs() { outop1str("push"); } PUBLIC void outpuls() { outop1str("pop"); } PUBLIC void outreturn() { outnop1str("ret"); } PUBLIC void outstore() { outload(); } PUBLIC void outsub() { outop2str("sub\t"); } PUBLIC void outtest() { outop2str("test\t"); } PUBLIC void outword() { outstr("word "); } PUBLIC void sctoi() { #ifdef I80386 if (i386_32) { outmovsx(); outaccum(); outncregname(BREG); } else #endif outnop1str("cbw"); } PUBLIC void stoi() { outnop1str("cwde"); } PRIVATE void tfrhilo() { outload(); outstr(acclostr); outcomma(); outhiaccum(); outnl(); } PRIVATE void tfrlohi() { outload(); outhiaccum(); outncregname(BREG); } #ifdef I80386 PUBLIC void ustoi() { outmovzx(); outaccum(); outcomma(); outshortregname(DREG); outnl(); } #endif /* I80386 */ #endif /* I8088 */ #ifdef MC6809 # define ACCHISTR "A" # define ANDSTRING "AND" # define DEFSTR_QUOTER '"' # define EORSTRING "EOR" # define MAX_INLINE_SHIFT 16 # define ORSTRING "OR" # define addfactor(reg) outop2str("ADDD\t,S") # define defstorage() outop0str("RMB\t") # define extBnegD() (ctoi(), negBsbcA()) # define finishfactor() outnl() # define outadc() outop2str("ADC") # define outandhi() outop2str("ANDA") # define outandlo() outop2str("ANDB") # define outcommon() outop0str("\tCOMM\t") # define outdefstr() outop0str("FCC\t\"") # define outequate() outop0str("\tEQU\t") # define outexchange() outop2str("EXG\t") # define outexport() outop0str("EXPORT\t") # define outglobl() outop0str("GLOBL\t") # define outimport() outop0str("IMPORT\t") # define outjswitch() outnop2str("JMP\t[D,X]") # define outlcommon() outop0str("\tLCOMM\t") # define outlswitch() outop3str("LDX\t#") # define outpijswitch() outnop2str("JMP\tD,X") # define outpil1switch() outop3str("LEAX\t<") # define outpil2switch() outnop2str("LDD\tD,X") # define outrolhi() outnop1str("ROLA"); # define outsbc() outop2str("SBC") # define outset() outstr ("\tSET\t") # define outsl() outop1str("LSL") # define outtransfer() outop2str("TFR\t") # define reclaimfactor() outnstr ("++") /* discard factor from stack */ # define savefactor(reg) outop2str("PSHS\tD") # define smiDreg() (clrBreg(), outnop1str("ROLA"), \ outnop2str("SBCB\t#0"), sctoi()) /* this tricky sequence is twice as fast as TFR A,B; SEX; TFR A,B */ /* it gets the sign bit of A in the carry */ /* then subtracts it from 0 in D (effectively) */ # define sr1() (outnop1str("ASRA"), outnop1str("RORB")) # define stackregstr "S" # define subfactor(reg) outop2str("SUBD\t,S") # define testhi() outnop1str("TSTA") # define tfrhilo() outnop2str("TFR\tA,B") # define tfrlohi() outnop2str("TFR\tB,A") # define usr1() (outnop1str("LSRA"), outnop1str("RORB")) PUBLIC void clrBreg() { outnop1str("CLRB"); } PUBLIC void comment() { outstr("| "); } PUBLIC void defbyte() { outop0str("FCB\t"); } PUBLIC void defword() { outop0str("FDB\t"); } PUBLIC void negDreg() { outnop1str("NEGA"); negBsbcA(); } PRIVATE void negBsbcA() { outnop1str("NEGB"); sbc0(); } PUBLIC void comDreg() { outnop1str("COMA"); outnop1str("COMB"); } PUBLIC void outABX() { outnop1str("ABX"); } PUBLIC void outadd() { outop2str("ADD"); } PUBLIC void outaddsp() { outleasp(); bumplc2(); } PUBLIC void outcalladr() { outop2str("JSR"); } PUBLIC void outcmp() { outop2str("CMP"); } PUBLIC void outdec() { outop1str("DEC"); } PUBLIC void outdirectpage() { outbyte('<'); } PUBLIC void outextended() { outbyte('>'); } PUBLIC void outfail() { outop0str("FAIL\t"); } PUBLIC void outinc() { outop1str("INC"); } PUBLIC void outindleft() { outbyte('['); } PUBLIC void outindright() { outbyte(']'); } PUBLIC void outldaccum() { outload(); outaccum(); } PUBLIC void outldmulreg() { outop2str("LDA"); } PUBLIC void outlea() { outop2str("LEA"); } PUBLIC void outleasp() { outop2str("LEAS\t"); } PUBLIC void outload() { outop2str("LD"); } PUBLIC void outmulmulreg() { outnop1str("MUL"); } PUBLIC void outncspregname() { outcomma(); outstackreg(); outnl(); } PUBLIC void outopsep() { } /* is tab, but already done by outadr() */ PUBLIC void outpshs() { outop2str("PSHS"); } PUBLIC void outpuls() { outop2str("PULS"); } PUBLIC void outreturn() { outnop1str("RTS"); } PUBLIC void outstore() { outop2str("ST"); } PUBLIC void outsub() { outop2str("SUB"); } PUBLIC void outtest() { outop1str("TST"); } PUBLIC void sctoi() { outnop1str("SEX"); } PUBLIC void ctoi() { outnop1str("CLRA"); } #endif /* MC6809 */ #ifdef FRAMEREG PUBLIC void outindframereg() { outindleft(); outregname(FRAMEREG); outindright(); } #endif typedef fastin_t seg_t; /* range 0..3 */ PRIVATE seg_t segment; /* current seg, depends on init to CSEG = 0 */ /* add carry resulting from char addition */ PUBLIC void adc0() { #ifdef I80386 if (i386_32) { adjcarry(); outadd(); outaccum(); outncregname(DXREG); } else #endif { outadc(); outhiaccum(); outncimmadr((offset_T) 0); } } /* add constant to register */ PUBLIC void addconst(offset, reg) offset_T offset; store_pt reg; { #ifdef I8088 #ifdef I80386 if ((i386_32 && (uoffset_T) offset + 1 <= 2) /* do -1 to 1 by dec/inc */ || (!i386_32 && (uoffset_T) offset + 2 <= 4)) /* do -2 to 2 */ #else if ((uoffset_T) offset + 2 <= 4) /* do -2 to 2 */ #endif { if (reg == ALREG) reg = AXREG; /* shorter and faster */ do { if (offset < 0) { outdec(); ++offset; } else /* if offset == 0, do inc + dec */ { outinc(); --offset; /* shouldn't happen and harmless */ } outnregname(reg); } while (offset); } else #endif #ifdef MC6809 if (!(reg & ALLDATREGS)) lea(offset, reg, reg); else if (reg == BREG && (offset == 1 || offset == -1)) { if (offset < 0) outdec(); else outinc(); outnregname(reg); } else #endif { outadd(); outimadj(offset, reg); } } /* adjust lc for signed offset */ PUBLIC void adjlc(offset, reg) offset_T offset; store_pt reg; { if (!(reg & CHARREGS)) { bumplc(); if (!isbyteoffset(offset)) { #ifdef I8088 if ((store_t) reg != AXREG) #endif bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif } } } /* adjust stack ptr by adding a labelled constant less current sp */ PUBLIC void adjsp(label) label_no label; { outaddsp(); outbyte(LOCALSTARTCHAR); outlabel(label); if (switchnow != NULL) { outminus(); outswstacklab(); } else { outplus(); outhex((uoffset_T) - sp); } #ifdef MC6809 outcregname(LOCAL); #endif #ifdef I80386 if (i386_32) bumplc2(); #endif outnl(); } /* and accumulator with constant */ PUBLIC void andconst(offset) offset_T offset; { char_t botbits; uoffset_T topbits; if ((topbits = offset & ~(uoffset_T) CHMASKTO & intmaskto) != 0 && topbits != (~(uoffset_T) CHMASKTO & intmaskto)) /* if topbits == 0, callers reduce the type */ { #ifdef OP1 outandhi(); outncimmadr((offset_T) (topbits >> (INT16BITSTO - CHBITSTO))); #else outandac(); #ifdef I80386 if (i386_32) bumplc2(); #endif outncimmadr(offset); return; #endif } if ((botbits = (char_t) offset & CHMASKTO) == 0) clrBreg(); else if (botbits != CHMASKTO) { outandlo(); outncimmadr((offset_T) botbits); } } #ifdef I8088 /* set bss segment */ PUBLIC void bssseg() { if (segment != BSSSEG) { segment = BSSSEG; outbssseg(); } } #endif /* jump to case of switch */ PUBLIC label_no casejump() { label_no jtablelab; #ifdef I8088 outlswitch(); outj1switch(); outlabel(jtablelab = getlabel()); outj2switch(); #ifdef I80386 if (i386_32) bumplc2(); #endif #endif #ifdef MC6809 if (posindependent) { outpil1switch(); outlabel(jtablelab = getlabel()); outncregname(GLOBAL); outpil2switch(); outpijswitch(); } else { outlswitch(); outnlabel(jtablelab = getlabel()); outjswitch(); } #endif return jtablelab; } /* clear register to 0 */ PRIVATE void clr(reg) store_pt reg; { loadconst((offset_T) 0, reg); } /* define common storage */ PUBLIC void common(name) char *name; { #ifdef I8088 outcommon(); outccname(name); outcomma(); #endif #ifdef MC6809 outccname(name); outcommon(); #endif } /* set code segment */ PUBLIC void cseg() { if (segment != CSEG) { segment = CSEG; outcseg(); } } /* define long */ PUBLIC void deflong(value) uoffset_T value; { uoffset_T longhigh; uoffset_T longlow; longlow = value & (uoffset_T) intmaskto; #ifdef I80386 if (i386_32) defdword(); else #endif { longhigh = (value >> INT16BITSTO) & (uoffset_T) intmaskto; defword(); #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN outnhex(longhigh); #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 { outnhex(longlow); longlow = longhigh; } #endif defword(); } outnhex(longlow); } /* define null storage */ PUBLIC void defnulls(nullcount) uoffset_T nullcount; { if (nullcount != 0) { defstorage(); outnhex(nullcount); } } /* define string */ PUBLIC label_no defstr(sptr, stop, dataflag) char *sptr; char *stop; bool_pt dataflag; { int byte; /* promoted char for output */ label_no strlab; seg_t oldsegment; fastin_t count; /* range 0..max(DEFSTR_BYTEMAX,DEFSTR_STRMAX) */ #ifdef HOLDSTRINGS if (!(bool_t) dataflag) return holdstr(sptr, stop); #endif oldsegment = segment; #ifdef I8088 dseg(); #endif #ifdef MC6809 if (dataflag) dseg(); else { segment = STRSEG; /* could use dseg() */ outstrseg(); /* this brings strings together */ } #endif outnlabel(strlab = getlabel()); byte = (unsigned char) *sptr++; while (sptr <= stop) { if ((unsigned char) byte >= MINPRINTCHAR && (unsigned char) byte <= MAXPRINTCHAR) { outdefstr(); count = DEFSTR_STRINGMAX; while (count-- > 0 && (unsigned char) byte >= MINPRINTCHAR && (unsigned char) byte <= MAXPRINTCHAR && sptr <= stop) { #if DEFSTR_DELIMITER - DEFSTR_QUOTER if ((unsigned char) byte == DEFSTR_DELIMITER || (unsigned char) byte == DEFSTR_QUOTER) #else if ((unsigned char) byte == DEFSTR_DELIMITER) #endif outbyte(DEFSTR_QUOTER); outbyte(byte); byte = (unsigned char) *sptr++; } outnbyte(DEFSTR_DELIMITER); } else { defbyte(); count = DEFSTR_BYTEMAX; while (count-- > 0 && ((unsigned char) byte < MINPRINTCHAR || (unsigned char) byte > MAXPRINTCHAR) && sptr <= stop) { if (count < DEFSTR_BYTEMAX - 1) outcomma(); /* byte separator */ outhex((uoffset_T) byte); byte = (unsigned char) *sptr++; } outnl(); } } defbyte(); outnbyte(EOS_TEXT); switch (oldsegment) { case CSEG: cseg(); break; case DSEG: dseg(); break; #ifdef I8088 case BSSSEG: bssseg(); break; #endif #ifdef MC6809 case DPSEG: dpseg(); break; #endif } return strlab; } /* divide D register by a constant if it is easy to do with shifts */ PUBLIC bool_pt diveasy(divisor, uflag) value_t divisor; bool_pt uflag; { bool_t sign; sign = FALSE; if (divisor < 0 && !(bool_t) uflag) { sign = TRUE; divisor = -divisor; } if (bitcount((uvalue_t) divisor) > 1) return FALSE; if (divisor == 0) clr(DREG); else { if (sign) negDreg(); srconst((value_t) highbit((uvalue_t) divisor), uflag); } return TRUE; } #ifdef MC6809 /* set direct page segment */ PUBLIC void dpseg() { if (segment != DPSEG) { segment = DPSEG; outdpseg(); } } #endif /* set data segment */ PUBLIC void dseg() { if (segment != DSEG) { segment = DSEG; outdseg(); } } /* equate a name to an EOL-terminated string */ PUBLIC void equ(name, string) char *name; char *string; { outstr(name); outequate(); outline(string); } /* equate a local label to a value */ PUBLIC void equlab(label, offset) label_no label; offset_T offset; { outbyte(LOCALSTARTCHAR); outlabel(label); outequate(); outshex(offset); outnl(); } /* import or export a variable */ PUBLIC void globl(name) char *name; { outglobl(); outnccname(name); } /* import a variable */ PUBLIC void import(name) char *name; { outimport(); outnccname(name); } /* extend an int to a long */ PUBLIC void itol(reg) store_pt reg; { #define TEMP_LABEL_FOR_REGRESSION_TESTS #ifdef TEMP_LABEL_FOR_REGRESSION_TESTS getlabel(); #endif if (lowregisDreg()) { #ifdef I8088 outcwd(); regtransfer(DXREG, reg); #else label_no exitlab; clr(reg); testhi(); sbranch(GE, exitlab = getlabel()); loadconst((offset_T) - 1, reg); outnlabel(exitlab); #endif } else { regtransfer(DREG, reg); smiDreg(); } } /* define local common storage */ PUBLIC void lcommlab(label) label_no label; { outlabel(label); outlcommon(); } PUBLIC void lcommon(name) char *name; { outccname(name); outlcommon(); } #ifdef MC6809 /* load effective address */ PUBLIC void lea(offset, sourcereg, targreg) offset_T offset; store_pt sourcereg; store_pt targreg; { outlea(); outregname(targreg); outtab(); outshex(offset); outncregname(sourcereg); } #endif /* load constant into given register */ PUBLIC void loadconst(offset, reg) offset_T offset; store_pt reg; { #ifdef I8088 if (offset == 0) { outxor(); outregname(reg); outncregname(reg); } else #endif #ifdef MC6809 if (offset == 0 && reg == BREG) clrBreg(); else #endif { outload(); outregname(reg); #ifdef MC6809 if (reg == YREG) bumplc2(); else #endif if (reg != BREG) { bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif } outncimmadr(offset); } } /* convert index half of long reg pair into low half of pair */ PRIVATE bool_pt lowregisDreg() { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN return FALSE; #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 return TRUE; #endif } /* partially long shift left register by a constant (negative = infinity) */ PUBLIC int lslconst(shift, reg) value_t shift; store_pt reg; { if ((uvalue_t) shift >= INT16BITSTO) { slconst(shift - INT16BITSTO, lowregisDreg() ? DREG : reg); regexchange(reg, DREG); clr(lowregisDreg() ? DREG : reg); return 0; } #ifdef I8088 if (shift >= CHBITSTO) { if (long_big_endian) { tfrlohi(); outnop2str("mov\tal,bh"); outnop2str("mov\tbh,bl"); outnop2str("sub\tbl,bl"); } else { outnop2str("mov\tbh,bl"); outnop2str("mov\tbl,ah"); tfrlohi(); clrBreg(); } return (int) shift - CHBITSTO; } #endif return (int) shift; } /* partially long shift right register by a constant (negative = infinity) */ PUBLIC int lsrconst(shift, reg, uflag) value_t shift; store_pt reg; bool_pt uflag; { if ((uvalue_t) shift >= INT16BITSTO) { if (lowregisDreg()) regexchange(reg, DREG); srconst(shift - INT16BITSTO, uflag); if ((bool_t) uflag) uitol(reg); else itol(reg); return 0; } #ifdef I8088 if (shift >= CHBITSTO) { if (long_big_endian) { outnop2str("mov\tbl,bh"); outnop2str("mov\tbh,al"); tfrhilo(); if ((bool_t) uflag) ctoi(); else sctoi(); } else { tfrhilo(); outnop2str("mov\tah,bl"); outnop2str("mov\tbl,bh"); if ((bool_t) uflag) outnop2str("sub\tbh,bh"); else { regexchange(reg, DREG); sctoi(); regexchange(reg, DREG); } } return (int) shift - CHBITSTO; } #endif return (int) shift; } /* take D register modulo a constant if it is easy to do with a mask */ PUBLIC bool_pt modeasy(divisor, uflag) value_t divisor; bool_pt uflag; { bool_t sign; sign = FALSE; if (divisor < 0 && !(bool_t) uflag) { sign = TRUE; divisor = -divisor; } if (bitcount((uvalue_t) divisor) > 1) return FALSE; if (--divisor == 0) clrBreg(); /* original divisor 1 or -1 yields 0 */ else { if (sign) negDreg(); andconst((offset_T) divisor); /* if original divisor 0, this is null */ if (sign) negDreg(); } return TRUE; } /* multiply register by a constant if it is easy to do with shifts */ PUBLIC bool_pt muleasy(factor, reg) uvalue_t factor; store_pt reg; { int mulstack[MAXINTBITSTO / 2 + 1]; /* must be signed, not a fastin_t */ fastin_pt count; fastin_t single1skip; fastin_t lastcount; fastin_t mulsp; int stackentry; /* signed */ #ifdef I8088 /* Now using imul directly so don't be so keen to shift */ if( factor > 16 && factor != 32 && factor != 64 && factor != 0xFFFFFFFFL ) return FALSE; #endif if (factor == 0) { clr(reg); return TRUE; } single1skip = 0; mulsp = -1; /* may be unsigned, but bumps to 0 */ while (factor != 0) { for (lastcount = single1skip; (factor & 1) == 0; factor >>= 1) ++lastcount; mulstack[(int)++mulsp] = lastcount; /* first time bumps mulsp to 0 even if an unsigned char */ for (count = 0; (factor & 1) != 0; factor >>= 1) ++count; single1skip = 1; if (count == 2 && factor == 0) /* 3 = 2 + 1 better than 3 = 4 - 1 */ /* but rest of algorithm messed up unless factor now 0 */ mulstack[(int)++mulsp] = 1; else if (count > 1) { single1skip = 0; if (lastcount == 1 && mulsp != 0) mulstack[(int)mulsp] = -1 - count; else mulstack[(int)++mulsp] = -count; } } if (mulsp > 3) return FALSE; if (mulsp != 0) { savefactor(reg); /* on stack or in reg as nec */ do { finishfactor(); /* finish save/add/subfactor() if nec */ stackentry = mulstack[(int)mulsp--]; if (stackentry < 0) { #ifdef I8088 if (stackentry == -INT32BITSTO) clr(reg); /* shifting would do nothing */ else #endif slconst((value_t) - stackentry, reg); subfactor(reg); /* from wherever put by savefactor() */ } else { slconst((value_t) stackentry, reg); addfactor(reg); /* from wherever put by savefactor() */ } } while (mulsp != 0); reclaimfactor(); /* reclaim storage if nec */ } slconst((value_t) mulstack[0], reg); return TRUE; } /* negate a register */ PUBLIC void negreg(reg) store_pt reg; { if ((store_t) reg == BREG) extBnegD(); else negDreg(); } /* return string of operator */ PUBLIC char *opstring(op) op_pt op; { switch (op) { case ANDOP: return ANDSTRING; case EOROP: return EORSTRING; case OROP: return ORSTRING; } return "badop"; } /* print DREG (accumulator) */ PRIVATE void outaccum() { outstr(accumstr); } /* print a c compiler name with leading CCNAMEPREXFIX */ PUBLIC void outccname(name) char *name; { outbyte(CCNAMEPREFIX); outstr(name); } /* print high byte of word accumulator */ PUBLIC void outhiaccum() { outstr(ACCHISTR); } /* print immediate address */ PUBLIC void outimmadr(offset) offset_T offset; { #ifdef I8088 if (!isbyteoffset(offset)) outimmed(); else outbimmed(); #else outimmed(); #endif outshex(offset); } /* print register, comma, immediate address and adjust lc */ PUBLIC void outimadj(offset, targreg) offset_T offset; store_pt targreg; { outregname(targreg); adjlc(offset, targreg); outncimmadr(offset); } /* print immediate address designator */ PUBLIC void outimmed() { outbyte('#'); } PUBLIC void outjumpstring() { outop3str(jumpstring); #ifdef I80386 if (i386_32) bumplc2(); #endif } /* print cc name, then newline */ PUBLIC void outnccname(name) char *name; { outccname(name); outnl(); } /* print separator, immediate address, newline */ PUBLIC void outncimmadr(offset) offset_T offset; { #ifdef I8088 outcomma(); #endif #ifdef MC6809 outtab(); #endif outimmadr(offset); outnl(); } /* print signed offset and adjust lc */ PUBLIC void outoffset(offset) offset_T offset; { #ifdef MC6809 if (!is5bitoffset(offset)) #endif adjlc(offset, INDREG0); outshex(offset); } /* print stack register */ PRIVATE void outstackreg() { outstr(stackregstr); } PUBLIC void public(name) char *name; { #ifndef AS09 outexport(); outnccname(name); #endif outccname(name); outnbyte(PUBLICENDCHAR); } /* print cc name as a private label */ PUBLIC void private(name) char *name; { #ifdef LABELENDCHAR outccname(name); outnbyte(LABELENDCHAR); #else outnccname(name); #endif } /* exchange registers */ PUBLIC void regexchange(sourcereg, targreg) store_pt sourcereg; store_pt targreg; { outexchange(); outregname(sourcereg); outncregname(targreg); #ifdef I8088 if (!((sourcereg | targreg) & AXREG)) bumplc(); #endif } /* transfer a register */ PUBLIC void regtransfer(sourcereg, targreg) store_pt sourcereg; store_pt targreg; { outtransfer(); #ifdef TARGET_FIRST outregname(targreg); outncregname(sourcereg); #else outregname(sourcereg); outncregname(targreg); #endif } /* subtract carry resulting from char addition */ PUBLIC void sbc0() { #ifdef I80386 if (i386_32) { adjcarry(); outsub(); outaccum(); outncregname(DXREG); } else #endif { outsbc(); outhiaccum(); outncimmadr((offset_T) 0); } } /* set a name to a value */ PUBLIC void set(name, value) char *name; offset_T value; { outccname(funcname); outbyte(LOCALSTARTCHAR); outstr(name); outset(); outshex(value); #ifdef FRAMEPOINTER #ifdef I8088 #ifndef NO_DEL_PUSH if (framep && optimise && !callersaves && value+sp-framep >= 0 && !(regfuse & callee1mask)) { outbyte('-'); outstr(funcname); outstr(".off"); } #endif #endif #endif outnl(); #ifdef FRAMEPOINTER if (framep) { outbyte(LOCALSTARTCHAR); outstr(funcname); outbyte(LOCALSTARTCHAR); outstr(name); outset(); outshex(value+sp-framep); #ifdef I8088 #ifndef NO_DEL_PUSH if (optimise && !callersaves && value+sp-framep < 0 && !(regfuse & callee1mask)) { outbyte('+'); outstr(funcname); outstr(".off"); } #endif #endif outnl(); } #endif } /* shift left register by 1 */ PUBLIC void sl1(reg) store_pt reg; { outsl(); #ifdef I8088 outregname(reg); outnc1(); #endif #ifdef MC6809 outnregname(BREG); outrolhi(); #endif } /* shift left register by a constant (negative = infinity) */ PUBLIC void slconst(shift, reg) value_t shift; store_pt reg; { #ifdef I80386 if (i386_32) { if ((shift = (uvalue_t) shift % INT32BITSTO) != 0) { outsl(); if (shift != 1) bumplc(); outregname(reg); outncimmadr((offset_T) shift); } return; } #endif if ((uvalue_t) shift >= INT16BITSTO) clr(reg); else { if (shift >= CHBITSTO && reg == DREG) { tfrlohi(); clrBreg(); shift -= CHBITSTO; } #ifdef I8088 # if MAX_INLINE_SHIFT < INT16BITSTO if (shift > MAX_INLINE_SHIFT) { outload(); outregname(SHIFTREG); outcomma(); outimmadr((offset_T) shift); outnl(); outsl(); outregname(reg); outncregname(SHIFTREG); } else # endif #endif while (shift--) sl1(reg); } } /* shift right D register by a constant (negative = infinity) */ PUBLIC void srconst(shift, uflag) value_t shift; bool_pt uflag; { #ifdef I80386 if (i386_32) { if ((shift = (uvalue_t) shift % INT32BITSTO) != 0) { if (uflag) outusr(); else outsr(); if (shift != 1) bumplc(); outaccum(); outncimmadr((offset_T) shift); } return; } #endif if ((uvalue_t) shift >= INT16BITSTO) /* covers negatives too */ { if ((bool_t) uflag) clr(DREG); else /* make D == 0 if D >= 0, else D == -1 */ smiDreg(); /* special case of 68020 Scc instruction */ } else { if (shift >= CHBITSTO) { tfrhilo(); if ((bool_t) uflag) ctoi(); else sctoi(); shift -= CHBITSTO; } #ifdef I8088 # if MAX_INLINE_SHIFT < INT16BITSTO if (shift > MAX_INLINE_SHIFT) { outload(); outregname(SHIFTREG); outcomma(); outimmadr((offset_T) shift); outnl(); if ((bool_t) uflag) outusr(); else outsr(); outaccum(); outncregname(SHIFTREG); } else # endif #endif while (shift--) { if ((bool_t) uflag) usr1(); else sr1(); } } } /* extend an unsigned in DREG to a long */ PUBLIC void uitol(reg) store_pt reg; { if (lowregisDreg()) clr(reg); else { regexchange(DREG, reg); clr(DREG); } } PRIVATE char opregstr[] = "_opreg"; /*----------------------------------------------------------------------------- opregadr() outputs address of variable opreg where OPREG is saved -----------------------------------------------------------------------------*/ PRIVATE void opregadr() { #ifdef I8088 outindleft(); outccname(opregstr); outindright(); bumplc2(); #ifdef I80386 if (i386_32) bumplc2(); #endif #endif #ifdef MC6809 outregname(OPREG); outtab(); if (posindependent) { outccname(opregstr); outncregname(GLOBAL); bumplc(); } else { outextended(); outnccname(opregstr); } bumplc(); #endif } /*----------------------------------------------------------------------------- restoreopreg() restores register OPREG from static location >opreg if it is was use -----------------------------------------------------------------------------*/ PUBLIC void restoreopreg() { if (reguse & OPREG) { #ifdef I8088 outload(); outregname(OPREG); outopsep(); opregadr(); outnl(); #endif #ifdef MC6809 outload(); opregadr(); #endif } } /*----------------------------------------------------------------------------- saveopreg() saves register OPREG to static location >opreg if it is in use this makes the flop routines non-reentrant. It is too messy to push it because the flop routines leave results on the stack -----------------------------------------------------------------------------*/ PUBLIC void saveopreg() { if (reguse & OPREG) { #ifdef I8088 bssseg(); common(opregstr); outnhex(opregsize); cseg(); outstore(); opregadr(); outncregname(OPREG); #endif #ifdef MC6809 dseg(); common(opregstr); outnhex(opregsize); cseg(); outstore(); opregadr(); #endif } } dev86-0.16.17/bcc/reg.h0000644000000000000000000001017305301213542014232 0ustar rootroot00000000000000/* reg.h - registers for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* The compiler generates "addresses" of the form indirect(indcount) (rx + offset) where rx is a machine register (possibly null) n is the indirection count (possibly 0) offset is a constant. It does not support more complicated formats like indirect(indcount) (rx + index * scale + offset). The register is coded as bit flag in the storage component of the symbol structure. This allows groups of registers to be tested using bitwise "&". Throughout the compiler, the group of these bit flags has the type reg_t. If there are only a few registers, reg_t can be an unsigned char. It must be unsigned if the high bit is used, to avoid sign extension problems. For bootstrapping the compiler from a compiler with no unsigned char, the unsigned type should be used instead (with a signifigant waste of storage). The bit flags should really be defined as ((reg_t) whatever) but then they would not (necessarily) be constant expressions and couldn't be used in switch selectors or (worse) preprocessor expressions. The CONSTANT and GLOBAL (non-) register bits are almost equivalent. A constant with nonzero indirection is marked as a GLOBAL and not a CONSTANT. This makes it easier to test for a constant CONSTANT. Globals which are formed in this way are converted to constants if their indirection count is reset to 0 (by & operator). */ /* register bit flags */ #define NOSTORAGE 0x000 /* structure/union member offsets */ #define CONSTANT 0x001 /* offsets are values */ #define BREG 0x002 #define DREG 0x004 #define INDREG0 0x008 #define INDREG1 0x010 #define INDREG2 0x020 #define LOCAL 0x040 #define GLOBAL 0x080 /* offsets from storage name or 0 */ #define CCREG CONSTANT /* arg to PSHS/PULS functions only */ #ifdef I8088 # ifdef FRAMEPOINTER # define FRAMEREG LOCAL # endif # define STACKREG 0x100 # define DATREG1 0x200 # define DATREG2 0x400 # define DATREG1B 0x800 #endif #ifdef MC6809 # define DPREG LOCAL /* arg to PSHS/PULS functions only */ # define PCREG GLOBAL /* arg to PSHS/PULS functions only */ #endif /* data for pushing and pulling registers */ #define MINREGCHAR 'A' #ifdef I8088 # define FLAGSREGCHAR 'f' # define pushchar() pushlist(AXREG) #endif #ifdef MC6809 # define pushchar() pushlist(BREG) #endif /* special registers */ #ifdef I8088 # define ALREG BREG # define AXREG DREG # define DXREG DATREG2 # define MULREG DATREG1B # define SHIFTREG DATREG1B #endif #ifdef MC6809 # define XREG INDREG0 /* XREG is special for ABX in index & switch */ # define YREG INDREG2 /* XREG and YREG allow LEA (Z test) in cmp() */ #endif /* groups of registers */ #define ALLDATREGS (BREG|DREG) #define CHARREGS BREG #define MAXREGS 1 /* number of data registers */ #define WORKDATREGS (BREG|DREG) /* function call and return registers */ #define ARGREG RETURNREG /* for (1st) argument */ #define LONGARGREGS LONGRETURNREGS /* for long or float arg */ #define LONGRETURNREGS (INDREG0|LONGREG2) #define LONGREG2 DREG #ifdef I8088 # define LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ # define RETURNREG DREG #endif #ifdef MC6809 # define RETURNREG INDREG0 #endif /* registers which can be pulled as a group with the program counter */ /* to perform an efficient function return */ #ifdef MC6809 #define JUNK1REGS BREG /* 1 bytes locals to discard */ #define JUNK2REGS INDREG2 #define JUNK3REGS (BREG|INDREG2) #define JUNK4REGS (INDREG1|INDREG2) #endif /* registers which can be pushed as a group with the first argument */ /* to perform an efficient function startup */ #ifdef MC6809 # define LOC1REGS CCREG /* 1 bytes local to allocate */ # define LOC2REGS DREG # define LOC3REGS (CCREG|DREG) # define LOC4REGS (CCREG|DREG|DPREG) # endif /* registers to be used by software operations */ #define OPREG INDREG0 /* 2nd reg for software ops (1st is DREG) */ #define OPWORKREG INDREG2 /* 3rd register for software ops */ /* maximum indirection count for 1 instruction */ #ifdef I8088 # define MAXINDIRECT 1 #endif #ifdef MC6809 # define MAXINDIRECT 2 #endif dev86-0.16.17/bcc/output.c0000644000000000000000000003016510065514146015022 0ustar rootroot00000000000000/* output.c - output and error handling for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "input.h" #include "os.h" #include "sizes.h" #include "table.h" #undef EXTERN #define EXTERN #include "output.h" #ifdef XENIX_AS # define HEXSTARTCHAR '/' #else # define HEXSTARTCHAR '$' #endif #define OUTBUFSIZE 2048 #define opcodeleadin() /* outtab() for fussy assemblers */ PRIVATE unsigned errcount; /* # errors in compilation */ /* depends on zero init */ PRIVATE char hexdigits[] = "0123456789ABCDEF"; PRIVATE char *outbuf; EXTERN char *outbufend; /* end of pair of output buffers */ PRIVATE char *outbufmid; PRIVATE fd_t output; PRIVATE fastin_t outstage; /* depends on zero init */ FORWARD void errorsummary P((void)); FORWARD void errsum1 P((void)); #ifdef MC6809 #ifdef DBNODE FORWARD void outvaldigs P((uvalue_t num)); #endif #endif PUBLIC void bugerror(message) char *message; { error2error("compiler bug? - ", message); } PUBLIC void closeout() { char *saveoutptr; if (outstage == 3) { saveoutptr = outbufptr; flushout(); /* buffer from last stage */ outbufptr = saveoutptr; } outstage = 0; /* flush from top to current ptr */ flushout(); close(output); } /* error handler */ PUBLIC void error(message) char *message; { error2error(message, ""); } /* error handler - concatenate 2 messages */ PUBLIC void error2error(message1, message2) char *message1; char *message2; { char *warning; if (message1[0] == '%' && message1[1] == 'w') { message1 += 2; warning = "warning: "; } else { ++errcount; warning = "error: "; } if (output != 1) { char *old_outbuf; char *old_outbufptr; char *old_outbuftop; fd_t old_output; fastin_t old_outstage; char smallbuf[81]; /* don't use heap - might be full or busy */ old_outbuf = outbuf; old_outbufptr = outbufptr; old_outbuftop = outbuftop; old_output = output; old_outstage = outstage; outbufptr = outbuf = &smallbuf[0]; outbuftop = &smallbuf[sizeof smallbuf]; output = 1; outstage = 0; errorloc(); outstr(warning); outstr(message1); outstr(message2); outnl(); flushout(); outbuf = old_outbuf; outbufptr = old_outbufptr; outbuftop = old_outbuftop; output = old_output; outstage = old_outstage; } outstr("fail"); comment(); errorloc(); outstr(warning); outstr(message1); outstr(message2); outnl(); } /* summarise errors */ PRIVATE void errorsummary() { if (errcount != 0) { outfail(); errsum1(); } outnl(); comment(); errsum1(); } PRIVATE void errsum1() { outudec(errcount); outnstr(" errors detected"); } /* fatal error, exit early */ PUBLIC void fatalerror(message) char *message; { error(message); finishup(); } /* finish up compile */ PUBLIC void finishup() { #ifdef BUILTIN_CPP if (!orig_cppmode) #endif { if (watchlc) { cseg(); outop0str("if *-.program.start-"); outnhex(getlc()); outfail(); outnstr("phase error"); outop0str("endif\n"); } #ifdef HOLDSTRINGS dumpstrings(); #endif dumpglbs(); errorsummary(); } closein(); closeout(); exit(errcount == 0 ? 0 : 1); } /* flush output file */ PUBLIC void flushout() { unsigned nbytes; switch (outstage) { case 0: nbytes = (unsigned) (outbufptr - outbuf); outbufptr = outbuf; break; case 2: nbytes = OUTBUFSIZE; outbufptr = outbuf; outbuftop = outbufmid; outstage = 3; break; default: nbytes = OUTBUFSIZE; if (outstage == 1) nbytes = 0; outbufptr = outbufmid; outbuftop = outbufend; outstage = 2; break; } if (nbytes != 0) { #ifdef BUILTIN_CPP if (!orig_cppmode) #endif clearlabels(outbufptr, outbufptr + nbytes); if (write(output, outbufptr, nbytes) != nbytes) { write(2, "output file error\n", 18); closein(); close(output); exit(1); } } } PUBLIC void initout() { static char smallbuf[1]; outbufend = outbuftop = (outbuf = outbufptr = smallbuf) + sizeof smallbuf; output = 1; /* standard output */ } PUBLIC void limiterror(message) char *message; { error2error("compiler limit exceeded - ", message); finishup(); } PUBLIC void openout(oname) char *oname; { if (output != 1) fatalerror("more than one output file"); if ((output = creat(oname, CREATPERMS)) < 0) { output = 1; fatalerror("cannot open output"); } } /* print character */ PUBLIC void outbyte(c) int c; { #if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1 register char *outp; outp = outbufptr; *outp++ = c; outbufptr = outp; if (outp >= outbuftop) flushout(); #else /* !C_CODE etc */ #if __AS09__ # asm TFR X,D LDX _outbufptr,PC STB ,X+ STX _outbufptr,PC CMPX _outbuftop,PC LBHS CALL.FLUSHOUT # endasm #endif /* __AS09__ */ #if __AS386_16__ # asm # if !__FIRST_ARG_IN_AX__ pop dx pop ax dec sp dec sp # else # if ARGREG != DREG xchg ax,bx # endif # endif mov bx,[_outbufptr] mov [bx],al inc bx mov [_outbufptr],bx cmp bx,[_outbuftop] jae Outbyte.Flush # if !__FIRST_ARG_IN_AX__ jmp dx # else ret # endif Outbyte.Flush: # if !__FIRST_ARG_IN_AX__ push dx # endif br _flushout # endasm #endif /* __AS386_16__ */ #if __AS386_32__ # asm # if !__FIRST_ARG_IN_AX__ mov eax,_outbyte.c[esp] # else # if ARGREG != DREG xchg eax,ebx # endif # endif mov ecx,[_outbufptr] mov [ecx],al inc ecx mov [_outbufptr],ecx cmp ecx,[_outbuftop] jae Outbyte.Flush ret Outbyte.Flush: br _flushout # endasm #endif /* __AS386_32__ */ #endif /* C_CODE etc */ } /* print comma */ PUBLIC void outcomma() { outbyte(','); } /* print line number in format ("# %u \"%s\"%s", nr, fname, str) */ PUBLIC void outcpplinenumber(nr, fname, str) unsigned nr; char *fname; char *str; { outstr("# "); outudec(nr); outstr(" \""); outstr(fname); outstr("\""); outnstr(str); } /* print unsigned offset, hex format */ PUBLIC void outhex(num) uoffset_T num; { #ifdef HEXSTARTCHAR if (num >= 10) outbyte(HEXSTARTCHAR); #endif outhexdigs(num); #ifdef HEXENDCHAR if (num >= 10) outbyte(HEXENDCHAR); #endif } /* print unsigned offset, hex format with digits only (no hex designator) */ PUBLIC void outhexdigs(num) register uoffset_T num; { if (num >= 0x10) { outhexdigs(num / 0x10); num %= 0x10; } outbyte(hexdigits[(int) num]); } /* print string terminated by EOL */ PUBLIC void outline(s) char *s; { register char *outp; register char *rs; outp = outbufptr; rs = s; #ifdef COEOL if (*rs == COEOL) ++rs; #endif do { *outp++ = *rs; if (outp >= outbuftop) { outbufptr = outp; flushout(); outp = outbufptr; } } while (*rs++ != EOL); outbufptr = outp; #ifdef COEOL if (*rs == COEOL) outbyte(COEOL); #endif } /* print minus sign */ PUBLIC void outminus() { outbyte('-'); } /* print character, then newline */ PUBLIC void outnbyte(byte) int byte; { outbyte(byte); outnl(); } /* print unsigned offset, hex format, then newline */ PUBLIC void outnhex(num) uoffset_T num; { outhex(num); outnl(); } /* print newline */ PUBLIC void outnl() { if (watchlc) { outtab(); comment(); outhex(getlc()); } outbyte('\n'); } /* print opcode and newline, bump lc by 1 */ PUBLIC void outnop1str(s) char *s; { opcodeleadin(); outstr(s); bumplc(); outnl(); } /* print opcode and newline, bump lc by 2 */ PUBLIC void outnop2str(s) char *s; { opcodeleadin(); outstr(s); bumplc2(); outnl(); } /* print string, then newline */ PUBLIC void outnstr(s) char *s; { outstr(s); outnl(); } /* print opcode */ PUBLIC void outop0str(s) char *s; { opcodeleadin(); outstr(s); } /* print opcode, bump lc by 1 */ PUBLIC void outop1str(s) char *s; { opcodeleadin(); outstr(s); bumplc(); } /* print opcode, bump lc by 2 */ PUBLIC void outop2str(s) char *s; { opcodeleadin(); outstr(s); bumplc2(); } /* print opcode, bump lc by 3 */ PUBLIC void outop3str(s) char *s; { opcodeleadin(); outstr(s); bumplc3(); } /* print plus sign */ PUBLIC void outplus() { outbyte('+'); } /* print signed offset, hex format */ PUBLIC void outshex(num) offset_T num; { if (num >= -(maxoffsetto + 1)) { outminus(); num = -num; } outhex((uoffset_T) num); } /* print string */ PUBLIC void outstr(s) char *s; { #if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1 register char *outp; register char *rs; outp = outbufptr; rs = s; while (*rs) { *outp++ = *rs++; if (outp >= outbuftop) { outbufptr = outp; flushout(); outp = outbufptr; } } outbufptr = outp; #else /* !C_CODE etc */ #if __AS09__ # asm LEAU ,X LDX _outbuftop,PC PSHS X LDX _outbufptr,PC BRA OUTSTR.NEXT CALL.FLUSHOUT PSHS U,B STX _outbufptr,PC LBSR _flushout LDX _outbufptr,PC LDY _outbuftop,PC PULS B,U,PC OUTSTR.LOOP STB ,X+ CMPX ,S BLO OUTSTR.NEXT BSR CALL.FLUSHOUT STY ,S OUTSTR.NEXT LDB ,U+ BNE OUTSTR.LOOP STX _outbufptr,PC LEAS 2,S # endasm #endif /* __AS09__ */ #if __AS386_16__ # asm # if !__CALLER_SAVES__ mov dx,di mov cx,si # endif # if !__FIRST_ARG_IN_AX__ pop ax pop si dec sp dec sp push ax # else # if ARGREG == DREG xchg si,ax # else mov si,bx # endif # endif mov di,[_outbufptr] mov bx,[_outbuftop] br OUTSTR.NEXT CALL.FLUSHOUT: push si # if !__CALLER_SAVES__ push dx push cx # endif push ax mov [_outbufptr],di call _flushout mov di,[_outbufptr] mov bx,[_outbuftop] pop ax # if !__CALLER_SAVES__ pop cx pop dx #endif pop si ret OUTSTR.LOOP: stosb cmp di,bx jb OUTSTR.NEXT call CALL.FLUSHOUT OUTSTR.NEXT: lodsb test al,al jne OUTSTR.LOOP mov [_outbufptr],di # if !__CALLER_SAVES__ mov si,cx mov di,dx # endif # endasm #endif /* __AS386_16__ */ #if __AS386_32__ # asm # if !__CALLER_SAVES__ mov edx,edi push esi # define TEMPS 4 # else # define TEMPS 0 # endif # if !__FIRST_ARG_IN_AX__ mov esi,TEMPS+_outstr.s[esp] # else # if ARGREG == DREG xchg esi,eax # else mov esi,ebx # endif # endif mov edi,[_outbufptr] mov ecx,[_outbuftop] br OUTSTR.NEXT CALL.FLUSHOUT: push esi # if !__CALLER_SAVES__ push edx # endif push eax mov [_outbufptr],edi call _flushout mov edi,[_outbufptr] mov ecx,[_outbuftop] pop eax # if !__CALLER_SAVES__ pop edx # endif pop esi ret OUTSTR.LOOP: stosb cmp edi,ecx jb OUTSTR.NEXT call CALL.FLUSHOUT OUTSTR.NEXT: lodsb test al,al jne OUTSTR.LOOP mov [_outbufptr],edi # if !__CALLER_SAVES__ pop esi mov edi,edx # endif # endasm #endif /* __AS386_32__ */ #endif /* C_CODE etc */ } /* print tab */ PUBLIC void outtab() { outbyte('\t'); } /* print unsigned, decimal format */ PUBLIC void outudec(num) unsigned num; { char str[10 + 1]; str[sizeof str - 1] = 0; outstr(pushudec(str + sizeof str - 1, num)); } #ifdef MC6809 #ifdef DBNODE /* print unsigned value, hex format (like outhex except value_t is larger) */ PUBLIC void outuvalue(num) uvalue_t num; { #ifdef HEXSTARTCHAR if (num >= 10) outbyte(HEXSTARTCHAR); #endif outvaldigs(num); #ifdef HEXENDCHAR if (num >= 10) outbyte(HEXENDCHAR); #endif } /* print unsigned value, hex format with digits only (no hex designator) */ PRIVATE void outvaldigs(num) register uvalue_t num; { if (num >= 0x10) { outvaldigs(num / 0x10); num %= 0x10; } outbyte(hexdigits[(fastin_t) num]); } /* print signed value, hex format (like outshex except value_t is larger) */ PUBLIC void outvalue(num) register value_t num; { if (num < 0) { outminus(); num = -num; } outuvalue((uoffset_T) num); } #endif /* DBNODE */ #endif /* MC6809 */ /* push decimal digits of an unsigned onto a stack of chars */ PUBLIC char *pushudec(s, num) register char *s; register unsigned num; { register unsigned reduction; while (num >= 10) { reduction = num / 10; *--s = num - 10 * reduction + '0'; num = reduction; } *--s = num + '0'; return s; } PUBLIC void setoutbufs() { if (!isatty(output)) { outbufptr = outbuf = ourmalloc(2 * OUTBUFSIZE); #ifdef TS ts_s_outputbuf += 2 * OUTBUFSIZE; #endif outbufmid = outbuftop = outbufptr + OUTBUFSIZE; outbufend = outbufmid + OUTBUFSIZE; outstage = 1; } if (watchlc) outnstr(".program.start:\n"); /* kludge temp label */ } dev86-0.16.17/bcc/label.h0000644000000000000000000000106105301213541014527 0ustar rootroot00000000000000/* label.h - assembler-specific label characters for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* defaults */ #define CCNAMEPREFIX '_' # define LABELENDCHAR ':' /* last char of ALL labels */ #define LABELSTARTCHAR '.' /* first char of names of generated labels */ #define LOCALSTARTCHAR '.' /* first char of local names */ #define PUBLICENDCHAR ':' /* adjustments for other assemblers */ #ifdef AS09 # undef LABELENDCHAR #endif #ifdef XENIX_AS # undef LABELSTARTCHAR # define LABELSTARTCHAR 'L' # undef LOCALSTARTCHAR # define LOCALSTARTCHAR 'L' #endif dev86-0.16.17/bcc/function.c0000644000000000000000000002305010065301054015272 0ustar rootroot00000000000000/* function.c - function call protocol for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "byteord.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "table.h" #include "type.h" #include "scan.h" #ifdef I8088 # define ADJUSTLONGRETURN # define CANHANDLENOFRAME # undef CANHANDLENOFRAME # define STUPIDFRAME #endif FORWARD void out_callstring P((void)); /* call a named (assembly interface) procedure, don't print newline after */ PUBLIC void call(name) char *name; { out_callstring(); outstr(name); } PUBLIC void function(source) struct symstruct *source; { if (source->indcount == 0 && source->storage == GLOBAL && !(source->flags & LABELLED) && *source->name.namep != 0) { out_callstring(); outnccname(source->name.namep); } else { #ifdef XENIX_AS if (source->indcount == 0) /* fix call fixed address */ out_callstring(); else #endif outcalladr(); #ifdef MC6809 if (source->indcount == 1) ++source->indcount; /* fake for outadr */ #endif outadr(source); } source->type = source->type->nexttype; #ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ if (source->type->scalar & DLONG) { # ifdef ADJUSTLONGRETURN # if DYNAMIC_LONG_ORDER if (long_big_endian) # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN { regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2); regexchange(LONGREG2, DXREG); } # endif # if DYNAMIC_LONG_ORDER else # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 regtransfer(DXREG, LONGRETURNREGS & ~LONGREG2); # endif # endif source->storage = LONGRETURNREGS & ~LONGREG2; } else #endif if (source->type->scalar & CHAR) { #if RETURNREG != DREG transfer(source, DREG); #endif source->storage = BREG; } #ifdef I80386 else if (i386_32) { if (source->type->scalar & DOUBLE) source->storage = doublreturnregs & ~DREG; else source->storage = RETURNREG; } else #endif { if (source->type->scalar & DOUBLE) source->storage = doublreturnregs; #ifdef I8088 else if (source->type->scalar & FLOAT) source->storage = RETURNREG|DATREG2; #endif else source->storage = RETURNREG; } source->offset.offi = source->indcount = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; if (source->type->constructor & STRUCTU) { transfer(source, getindexreg()); /* so it can be indirected * and/or preserved in blockmove() */ source->indcount = 1; source->flags = TEMP; /* kludge so blockpush can be avoided */ } } PUBLIC void ldregargs() { register struct symstruct *symptr; store_pt targreg; struct symstruct temptarg; for (symptr = &locsyms[0]; symptr < locptr && symptr->level == ARGLEVEL; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) { if ((store_t) (targreg = symptr->storage) & allregs) { /* load() is designed to work on expression symbols, so don't * trust it on reg variables although it almost works. */ temptarg = *symptr; if (arg1inreg && symptr == &locsyms[0]) { temptarg.storage = ARGREG; temptarg.offset.offi = 0; } else { temptarg.storage = LOCAL; temptarg.indcount = 1; } load(&temptarg, targreg); symptr->offset.offi = 0; } } regarg = FALSE; } PUBLIC void loadretexpression() { if (returntype->constructor & STRUCTU) { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; struct symstruct *structarg; etmark = etptr; exprmark = exprptr; exp = expression(); makeleaf(exp); structarg = constsym((value_t) 0); structarg->type = pointype(returntype); onstack(structarg); indirec(structarg); structarg->flags = 0; /* assign() doesn't like TEMP even for indir */ structarg->offset.offi = returnadrsize; assign(exp->left.symptr, structarg); etptr = etmark; exprptr = exprmark; } #ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */ else if (returntype->scalar & DLONG) { loadexpression(LONGRETURNREGS & ~LONGREG2, returntype); # ifdef ADJUSTLONGRETURN # if DYNAMIC_LONG_ORDER if (long_big_endian) # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN { regexchange(LONGREG2, DXREG); regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2); } # endif # if DYNAMIC_LONG_ORDER else # endif # if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 regtransfer(LONGRETURNREGS & ~LONGREG2, DXREG); # endif # endif } else #endif { #ifdef I80386 if (i386_32) { if (returntype->scalar & DOUBLE) loadexpression(doublreturnregs & ~DREG, returntype); else loadexpression(RETURNREG, returntype); } else #endif { if (returntype->scalar & DOUBLE) loadexpression(doublreturnregs, returntype); #ifdef I8088 else if (returntype->scalar & FLOAT) loadexpression(/* REURNREG|*/ DATREG2, returntype); #endif else loadexpression(RETURNREG, returntype); } } } PUBLIC void listo(target, lastargsp) struct symstruct *target; offset_T lastargsp; { extend(target); push(target); if (lastargsp != 0 && sp != lastargsp - target->type->typesize) { loadany(target); modstk(lastargsp); push(target); if (sp != lastargsp - target->type->typesize) { bugerror("botched push of arg"); #ifdef DBNODE outstr("arg type is "); dbtype(target->type); outnl(); #endif } } } PUBLIC void listroot(target) struct symstruct *target; { extend(target); /* necessary regs are free since they were saved for function */ if (target->type->scalar & DLONG) load(target, LONGARGREGS & ~LONGREG2); else load(target, ARGREG); } PRIVATE void out_callstring() { outop3str(callstring); #ifdef I80386 if (i386_32) bumplc2(); #endif } #ifdef FRAMEPOINTER PUBLIC void popframe() { #ifdef STUPIDFRAME #ifndef NO_DEL_PUSH if (optimise && !callersaves) { outstr("if "); outstr(funcname); outnstr(".off=0"); } poplist(callee1mask); if (optimise && !callersaves) outnstr("endif"); #else poplist(callee1mask); #endif poplist(FRAMEREG); #else poplist(frame1list); #endif } #endif /* reserve storage for locals if necessary */ /* also push 1st function arg and load register args if necessary */ PUBLIC void reslocals() { #ifdef FRAMEPOINTER # ifndef STUPIDFRAME bool_t loadframe = FALSE; # endif #endif if (switchnow != NULL) { #ifdef FRAMEPOINTER if (framep == 0 && softsp != sp) bugerror("local variables in switch statement messed up, sorry"); #else if (sp != softsp) bugerror("local variables in switch statement don't work, sorry"); #endif if (lowsp > softsp) lowsp = softsp; sp = softsp; return; } #ifdef FRAMEPOINTER if (framep == 0) { # ifdef STUPIDFRAME pushreg(FRAMEREG); regtransfer(STACKREG, FRAMEREG); framep = sp; #ifndef NO_DEL_PUSH if (optimise && !callersaves) { outstr("if "); outstr(funcname); outnstr(".off=0"); } pushlist(callee1mask); if (optimise && !callersaves) outnstr("endif"); #else pushlist(callee1mask); #endif # else /* not STUPIDFRAME */ # ifdef CANHANDLENOFRAME if (stackarg || softsp != -frameregsize) /* args or locals */ # endif { pushlist(frame1list); loadframe = TRUE; } # endif /* not STUPIDFRAME */ } #else if (sp == 0) pushlist(callee1mask); #endif /* FRAMEPOINTER */ if (arg1size) { switch ((fastin_t) arg1size) { case 8: pushlist(doubleargregs); break; case 4: # ifdef I80386 if (!i386_32) # endif { pushlist(LONGARGREGS); break; } case 2: # ifdef I8088 pushlist(ARGREG); # endif # ifdef MC6809 switch (sp - softsp) { case 3: pushlist(LOC1REGS | ARGREG); break; case 4: pushlist(LOC2REGS | ARGREG); break; case 5: pushlist(LOC3REGS | ARGREG); break; case 6: pushlist(LOC4REGS | ARGREG); break; default: pushlist(ARGREG); break; } # endif /* MC6809 */ } arg1size = 0; /* show 1st arg allocated */ } #ifdef FRAMEPOINTER # ifndef STUPIDFRAME /* else this moved above for compat with Xenix cc frame */ if (loadframe || softsp != -frameregsize) modstk(softsp); /* else avoid modstk() because softsp holds space for frame pointer only) */ /* but pointer has not been pushed (must keep softsp for later levels) */ if (loadframe) { regtransfer(STACKREG, FRAMEREG); framep = sp; } # else /* STUPIDFRAME */ modstk(softsp); # endif /* STUPIDFRAME */ #else /* no FRAMEPOINTER */ modstk(softsp); #endif /* FRAMEPOINTER */ if (regarg) ldregargs(); } /* clean up stack and return from a function */ PUBLIC void ret() { #ifdef FRAMEPOINTER offset_T newsp; if (framep != 0) { newsp = -(offset_T) func1saveregsize; if (switchnow != NULL || newsp - sp >= 0x80) changesp(newsp, TRUE); else modstk(newsp); popframe(); } outreturn(); #else /* no FRAMEPOINTER */ # ifdef MC6809 store_pt reglist; switch (sp) { case -1: reglist = JUNK1REGS | PCREG; break; case -2: reglist = JUNK2REGS | PCREG; break; case -3: reglist = JUNK3REGS | PCREG; break; case -4: reglist = JUNK4REGS | PCREG; break; default: modstk(0); outreturn(); return; } poplist(reglist); #else if (sp != 0) { modstk(-(offset_T) func1saveregsize); poplist(callee1mask); } outreturn(); # endif /* no MC6809 */ #endif /* no FRAMEPOINTER */ } dev86-0.16.17/bcc/scan.c0000644000000000000000000004216110065335270014404 0ustar rootroot00000000000000/* scan.c - lexical analyser for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define GCH1() do { if (SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) specialchar(); } while (0) #include "bcc.h" #include "input.h" #include "os.h" #include "output.h" #include "sc.h" #include "sizes.h" #include "table.h" #include "type.h" #undef EXTERN #define EXTERN #include "scan.h" PUBLIC sym_t symofchar[256] = { BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, WHITESPACE, LOGNOTOP, STRINGCONST, CONTROL, /* !"# */ BADCHAR, MODOP, AMPERSAND, CHARCONST, /* $%&' */ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */ COMMA, HYPHEN, FLOATCONST, SLASH, /* ,-./ */ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */ INTCONST, INTCONST, COLON, SEMICOLON, /* 89:; */ LTOP, ASSIGNOP, GTOP, CONDOP, /* <=>? */ BADCHAR, IDENT, IDENT, IDENT, /* @ABC */ IDENT, IDENT, IDENT, IDENT, /* DEFG */ IDENT, IDENT, IDENT, IDENT, /* HIJK */ IDENT, IDENT, IDENT, IDENT, /* LMNO */ IDENT, IDENT, IDENT, IDENT, /* PQRS */ IDENT, IDENT, IDENT, IDENT, /* TUVW */ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */ SPECIALCHAR, RBRACKET, EOROP, IDENT, /* \]^_ */ BADCHAR, IDENT, IDENT, IDENT, /* `abc */ IDENT, IDENT, IDENT, IDENT, /* defg */ IDENT, IDENT, IDENT, IDENT, /* hijk */ IDENT, IDENT, IDENT, IDENT, /* lmno */ IDENT, IDENT, IDENT, IDENT, /* pqrs */ IDENT, IDENT, IDENT, IDENT, /* tuvw */ IDENT, IDENT, IDENT, LBRACE, /* xyz{ */ OROP, RBRACE, NOTOP, BADCHAR, /* |}~ */ BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR, BADCHAR }; FORWARD void getident P((void)); FORWARD void intconst P((void)); FORWARD void ppnumber P((void)); PRIVATE void newstringorcharconst P((void)); /* skip white space up to end of line (skip EOL's if in comments) */ PUBLIC void blanks() { register char *reglineptr; while (TRUE) { reglineptr = lineptr; while (SYMOFCHAR(*reglineptr) == WHITESPACE) ++reglineptr; lineptr = reglineptr; if (SYMOFCHAR(ch = *reglineptr) == SPECIALCHAR) { specialchar(); if (ch == EOL) return; if (SYMOFCHAR(ch) == WHITESPACE) continue; reglineptr = lineptr; } #ifdef BUILTIN_CPP if (*reglineptr != '/') return; if (SYMOFCHAR(*(reglineptr + 1)) == SPECIALCHAR) { ch = *(lineptr = reglineptr + 1); specialchar(); ch = *(reglineptr = --lineptr) = '/'; /* pushback */ } if (*(reglineptr + 1) != '*') return; gch1(); skipcomment(); #else return; #endif } } PUBLIC void cppscan(asm_only) int asm_only; { int start_of_line = 1; #ifndef ASM_BARE #ifdef BUILTIN_CPP virtual_nl = 1; #endif #endif while (!asm_only || asmmode) { int sym = SYMOFCHAR(ch); switch (sym) { case CONTROL: if( !start_of_line ) sym=BADCHAR; break; case WHITESPACE: break; case SPECIALCHAR: if( ch == '\\' ) sym=BADCHAR; start_of_line = 1; break; case CHARCONST: case STRINGCONST: if( asmmode ) sym=BADCHAR; default: start_of_line = 0; } switch (sym) { case CHARCONST: case STRINGCONST: stringorcharconst(); *charptr = 0; /* room reserved */ outstr(constant.value.s); /* XXX - embedded null would kill it */ charptr = constant.value.s; break; #ifdef BUILTIN_CPP case CONTROL: gch1(); if (maclevel != 0) { error("# in a macro: not preprocessed"); /* XXX? */ break; } else { docontrol(); #ifndef ASM_BARE virtual_nl = 1; #endif continue; } case SLASH: gch1(); if (ch == '*') { skipcomment(); break; } outbyte('/'); break; #else /* !BUILTIN_CPP */ case CONTROL: gch1(); docontrol(); continue; #endif case FLOATCONST: gch1(); if (SYMOFCHAR(ch) == INTCONST) { --lineptr; ch = '.'; /* pushback */ ppnumber(); outstr(constant.value.s); charptr = constant.value.s; } else outbyte('.'); break; case IDENT: getident(); #ifdef BUILTIN_CPP if ((gsymptr = findlorg(gsname)) != NULL) { if (gsymptr->flags == DEFINITION) { entermac(); break; } } #endif outstr(gsname); break; case INTCONST: ppnumber(); outstr(constant.value.s); charptr = constant.value.s; break; case SPECIALCHAR: specialchar(); /* XXX - this is necessary because entermac * and skipeol can leave lineptr at a special * char although GCH1 cannot. entermac would * be easy to fix, but too many places already * have to handle the extra work after skipeol * for other reasons. */ if (ch == EOL) { skipeol(); if (eofile) return; break; } #ifdef COEOL if (ch == COEOL) { gch1(); break; } #endif if (SYMOFCHAR(ch) != SPECIALCHAR) break; /* specialchar advanced the input */ /* must be '\\' */ default: /* Allow for multi-instruction lines in asm */ #ifdef BUILTIN_CPP if( ch == '^' && !orig_cppmode && asmmode ) ch='\n'; #else if( ch == '^' && asmmode ) ch='\n'; #endif OUTBYTE(ch); ch = *++lineptr; if (SYMOFCHAR(ch) == SPECIALCHAR && ch != '\\') specialchar(); break; } #ifndef ASM_BARE #ifdef BUILTIN_CPP virtual_nl = 0; #endif #endif } } PUBLIC void eofin(message) char *message; { error2error("end of file in ", message); } /* get identifier in gsname == gs2name + 2 */ PRIVATE void getident() { register int c; register char *idptr; register int length; register char *reglineptr; idptr = gsname; length = NAMESIZE; reglineptr = lineptr; c = ch; more: do { *idptr++ = c; c = (unsigned char) *++reglineptr; } while (symofchar[c] <= MAXIDSYM && --length != 0); ch = c; *idptr = 0; debug(7, "Got ident %s", gsname); lineptr = reglineptr; if (symofchar[c] == SPECIALCHAR) { specialchar(); if (SYMOFCHAR(ch) <= MAXIDSYM && length != 0) { reglineptr = lineptr; c = ch; goto more; } } } /* return nonzero if at an identifier */ PUBLIC bool_pt isident() { if (SYMOFCHAR(ch) != IDENT) return FALSE; getident(); return TRUE; } PRIVATE void intconst() { fastin_t base; fastin_t digit; register char *digptr; fastin_t lcount; fastin_t ucount; bool_t dflag; ppnumber(); digptr = charptr = constant.value.s; if (*digptr == '0') { if (digptr[1] != 'x' && digptr[1] != 'X') base = 8; else { base = 16; digptr += 2; } } else base = 10; dflag = FALSE; if (*digptr == 0) error("constant has no digits"); if (base != 16) { while (SYMOFCHAR(*digptr) == INTCONST) ++digptr; if (*digptr == '.') { dflag = TRUE; ++digptr; while (SYMOFCHAR(*digptr) == INTCONST) ++digptr; } if (*digptr == 'E' || *digptr == 'e') { dflag = TRUE; ++digptr; if (*digptr == '+' || *digptr == '-') ++digptr; if (SYMOFCHAR(*digptr) != INTCONST) error("exponent has no digits"); while (SYMOFCHAR(*digptr) == INTCONST) ++digptr; } } if (dflag) { constant.type = dtype; digit = *digptr; *digptr = 0; constant.value.d = atof(constant.value.s); *digptr = digit; if (digit == 'F' || digit == 'f') { ++digptr; constant.type = fltype; constant.value.d = (float) constant.value.d; } sym = FLOATCONST; if (*digptr != 0) error("junk at end of floating point constant"); return; } if (base != 16) digptr = constant.value.s; constant.value.v = 0; while (*digptr >= '0') { digit = *digptr; if (digit > '9') { if (base != 16) break; if (digit >= 'a' && digit <= 'f') digit = digit + (-'a' + '0' + 10); else if (digit >= 'A' && digit <= 'F') digit = digit + (-'A' + '0' + 10); else break; } constant.value.v = base * constant.value.v + (digit - '0'); ++digptr; } ucount = lcount = 0; while (TRUE) { if (*digptr == 'L' || *digptr == 'l') ++lcount; else if (*digptr == 'U' || *digptr == 'u') ++ucount; else break; ++digptr; } if (constant.value.v <= maxintto && lcount == 0 && ucount == 0) constant.type = itype; else if (constant.value.v <= maxuintto && lcount == 0 && (base != 10 || ucount != 0)) constant.type = uitype; else if (constant.value.v <= maxlongto && ucount == 0) constant.type = ltype; else constant.type = ultype; if (lcount > 1 || ucount > 1 || *digptr != 0) error("junk at end of integer constant"); } PUBLIC void nextsym() { static char lastch; register char *reglineptr; if (expect_statement && asmmode) { outnstr("!BCC_ASM"); dumplocs(); cppscan(1); outnstr("!BCC_ENDASM"); } else while (TRUE) /* exit with short, fast returns */ { reglineptr = lineptr; while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE) ++reglineptr; lastch = *reglineptr; if (SYMOFCHAR(ch = *(lineptr = reglineptr + 1)) == SPECIALCHAR && sym != SPECIALCHAR) specialchar(); debug(7, "In nextsym, got %d \"%C\"", sym, lastch); switch (sym) { case CHARCONST: --lineptr; ch = lastch; /* pushback */ stringorcharconst(); newstringorcharconst(); if (charptr == constant.value.s) { charptr = constant.value.s; error("empty character constant"); constant.value.v = 0; } else { if (charptr != constant.value.s + 1) error("character constant too long"); charptr = constant.value.s; constant.value.v = *constant.value.s & CHMASKTO; } constant.type = itype; return; case CONTROL: #ifdef BUILTIN_CPP if (maclevel != 0) { error("# in a macro: not preprocessed"); /* XXX? */ return; } else #endif { int old_asmmode = asmmode; docontrol(); if (asmmode && !old_asmmode) { sym = SEMICOLON; return; } break; } case FLOATCONST: if (SYMOFCHAR(ch) == INTCONST) { --lineptr; ch = lastch; intconst(); } else sym = STRUCELTOP; return; case IDENT: --lineptr; ch = lastch; getident(); if ((gsymptr = findlorg(gsname)) != NULL) { #ifdef BUILTIN_CPP if (gsymptr->flags == DEFINITION) { entermac(); break; } #endif if (gsymptr->flags == KEYWORD) sym = gsymptr->offset.offsym; } return; case INTCONST: --lineptr; ch = lastch; intconst(); return; case SPECIALCHAR: ch = *(lineptr = reglineptr); specialchar(); if (ch == EOL) { if (incppexpr) { sym = SEMICOLON; return; } skipeol(); if (eofile) { sym = EOFSYM; return; } break; } if (SYMOFCHAR(ch) != SPECIALCHAR) break; gch1(); /* fall through to BADCHAR case */ case BADCHAR: error("illegal character"); break; case STRINGCONST: --lineptr; ch = lastch; /* pushback */ stringorcharconst(); newstringorcharconst(); #ifdef TS ts_n_string += charptr - constant.value.s; #endif return; case COLON: /* could be COLONOP or in label */ case COMMA: /* could be COMMAOP or in list */ case CONDOP: case LBRACE: case LBRACKET: case LPAREN: case NOTOP: case RBRACE: case RBRACKET: case RPAREN: case SEMICOLON: return; case ASSIGNOP: if (ch == '=') { sym = EQOP; gch1(); } return; case ADDOP: if (ch == '+') { sym = INCSYM; /* PREINCOP or POSINCOP */ gch1(); } else if (ch == '=') { sym = ADDABOP; gch1(); } return; case HYPHEN: /* NEGOP or SUBOP or decoded below */ if (ch == '-') { sym = DECSYM; /* PREDECOP or POSTDECOP */ gch1(); } else if (ch == '=') { sym = SUBABOP; gch1(); } else if (ch == '>') { sym = STRUCPTROP; gch1(); } return; case STAR: /* INDIRECTOP or MULOP or as below */ if (ch == '=') { sym = MULABOP; gch1(); } return; case SLASH: #ifdef BUILTIN_CPP if (ch == '*') { skipcomment(); break; } #endif if (ch == '=') { sym = DIVABOP; gch1(); } else sym = DIVOP; return; case MODOP: if (ch == '=') { sym = MODABOP; gch1(); } return; case LTOP: if (ch == '=') { sym = LEOP; gch1(); } else if (ch == '<') { gch1(); if (ch == '=') { sym = SLABOP; gch1(); } else { sym = SLOP; } } return; case GTOP: if (ch == '=') { sym = GEOP; gch1(); } else if (ch == '>') { gch1(); if (ch == '=') { sym = SRABOP; gch1(); } else { sym = SROP; } } return; case AMPERSAND: /* ADDRESSOP or ANDOP or as below */ if (ch == '&') { sym = LOGANDOP; gch1(); } else if (ch == '=') { sym = ANDABOP; gch1(); } return; case EOROP: if (ch == '=') { sym = EORABOP; gch1(); } return; case OROP: if (ch == '|') { sym = LOGOROP; gch1(); } else if (ch == '=') { sym = ORABOP; gch1(); } return; case LOGNOTOP: if (ch == '=') { sym = NEOP; gch1(); } return; } } } PRIVATE void ppnumber() { constant.value.s = charptr; while (TRUE) { if (charptr >= char1top) constant.value.s = growobject(constant.value.s, 2); *charptr++ = ch; if (ch == 'E' || ch == 'e') { gch1(); if (ch == '+' || ch == '-') continue; } else GCH1(); if (SYMOFCHAR(ch) > MAXPPNUMSYM) break; } *charptr = 0; } PUBLIC void stringorcharconst() { char terminator; constant.value.s = charptr; terminator = ch; while (TRUE) { if (charptr >= char3top) constant.value.s = growobject(constant.value.s, 4); *charptr++ = ch; if (ch == '\\') { gch1(); if (ch == EOL) { #ifdef BUILTIN_CPP if (!orig_cppmode) #endif eofin("escape sequence"); break; } *charptr++ = ch; } GCH1(); if (ch == EOL) { #ifdef BUILTIN_CPP if (!orig_cppmode && ifcheck() ) #endif error(terminator == '"' ? "end of line in string constant" : "end of line in character constant"); break; } if (ch == terminator) { *charptr++ = terminator; /* This adds ansi string concatenation BUT only on one line */ do { ch = *++lineptr; } while(SYMOFCHAR(ch) == WHITESPACE); if( ch == terminator ) /* Hang on .. that's another string ... */ { charptr--; /* Stick it together */ gch1(); } else break; } } } PRIVATE void newstringorcharconst() { char *endinptr; int escvalue; fastin_t maxdigits; register char *inptr; register char *outptr; outptr = constant.value.s; inptr = charptr - 1; if (inptr == outptr || *inptr != *outptr) endinptr = charptr; /* not properly terminated */ else endinptr = inptr; inptr = outptr + 1; while (inptr != endinptr) { if (*inptr == '\\') { if (++inptr == endinptr) break; /* error reported already */ if (*inptr >= '0' && *inptr < '8') { escvalue = 0; maxdigits = 3; do { escvalue = 8 * escvalue + *inptr - '0'; ++inptr; } while (--maxdigits != 0 && *inptr >= '0' && *inptr < '8'); --inptr; *outptr++ = escvalue; } else switch (*inptr) { case '"': case '\'': case '\\': *outptr++ = *inptr; break; case 'a': *outptr++ = 7; break; case 'b': *outptr++ = 8; break; case 'f': *outptr++ = 12; break; case 'n': *outptr++ = EOLTO; break; case 'r': *outptr++ = 13; break; case 't': *outptr++ = 9; break; case 'v': *outptr++ = 11; break; default: error("%wnonstandard escape sequence"); *outptr++ = *inptr; break; } } else *outptr++ = *inptr; ++inptr; } charptr = outptr; } dev86-0.16.17/bcc/declare.c0000644000000000000000000006405210171700756015065 0ustar rootroot00000000000000/* declare.c - declaration routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "byteord.h" #include "gencode.h" #include "input.h" /* just for orig_cppmode */ #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" #undef EXTERN #define EXTERN #include "parse.h" PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */ PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */ PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */ #define gvarname (gvar2name + 2) /* last identifier declared */ PRIVATE struct typestruct *gvartype; /* type of last identifier declared */ PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */ FORWARD struct typestruct *chainprefix P((struct typestruct *pretype, struct typestruct *sufftype)); FORWARD void declaf P((void)); FORWARD void declarator P((void)); FORWARD void declarg P((void)); FORWARD struct typestruct *declenum P((void)); FORWARD void declfunc P((void)); FORWARD void declselt P((struct typestruct *structype, offset_T *psoffset, struct typelist ** ptypelist)); FORWARD bool_pt declspec P((void)); FORWARD struct typestruct *declsu P((void)); FORWARD void idecllist P((void)); FORWARD void initarray P((struct typestruct *type)); FORWARD void inititem P((struct typestruct *type)); FORWARD void initstruct P((struct typestruct *type)); FORWARD void lbrace P((void)); FORWARD void multidecl P((char *sname)); FORWARD void need P((int charneeded)); FORWARD void rdeclarator P((void)); FORWARD bool_pt regdecl P((void)); PRIVATE struct typestruct *chainprefix(pretype, sufftype) struct typestruct *pretype; struct typestruct *sufftype; { if (pretype->nexttype != NULL) { sufftype = chainprefix(pretype->nexttype, sufftype); if (pretype->constructor != ARRAY) return prefix(pretype->constructor, pretype->typesize, sufftype); else return prefix(ARRAY, pretype->typesize / pretype->nexttype->typesize * sufftype->typesize, sufftype); } return sufftype; } PUBLIC void colon() { if (sym != COLON) need(':'); else nextsym(); } /* decllist() - list of local declarations */ /* this does the non-terminal symbols declaration-list, type-declaration */ /* list and declaration */ /* the different cases are and ";" at the end are decided by idecllist() */ PUBLIC void decllist() { while (declspec()) { if (gvarsc == NULLDECL) gvarsc = AUTODECL; idecllist(); } } PRIVATE void declaf() { uoffset_T asize; bool_t levelnew; #ifdef TESTING_PROTOTYPES char ogvarname[NAMESIZE]; sym_t ogvarsc; struct symstruct *ogvarsymptr; struct typestruct *ogvartype; #endif if (sym == LPAREN) /* function */ { nextsym(); if (argsallowed && level == GLBLEVEL) { newlevel(); levelnew = TRUE; } else levelnew = FALSE; #ifdef TESTING_PROTOTYPES strcpy(ogvarname, gvarname); ogvarsc = gvarsc; ogvarsymptr = gvarsymptr; ogvartype = gvartype; if (declspec()) { if (level == ARGLEVEL) outstr(gvarname); outbyte('('); do { declarator(); dbtype(gvartype); outbyte(' '); #if 0 if (gvarname[0] != 0 && gsymptr != NULL && gsymptr->level == level) error("repeated argument"); #endif outstr(gvarname); if (levelnew) addloc(gsname, gvartype); /* adjust offsets later */ if (sym != COMMA) break; outcomma(); nextsym(); } while (declspec()); if (sym == STRUCELTOP) { /* ... should be lexed. */ nextsym(); if (sym == STRUCELTOP) { nextsym(); if (sym == STRUCELTOP) { nextsym(); outstr(" ..."); } } } outbyte(')'); if (level == ARGLEVEL) outnl(); } else { #endif /* TESTING_PROTOTYPES */ while (sym == IDENT) { if (gsymptr != NULL && gsymptr->level == level) error("repeated argument"); if (levelnew) addloc(gsname, itype); /* adjust types and offsets later */ nextsym(); if (sym != COMMA) break; nextsym(); } #ifdef TESTING_PROTOTYPES } strcpy(gvarname, ogvarname); gvarsc = ogvarsc; gvarsymptr = ogvarsymptr; gvartype = ogvartype; #endif /* TESTING_PROTOTYPES */ rparen(); declaf(); switch (gvartype->constructor) { case ARRAY: error("function returning array is illegal"); break; case FUNCTION: error("function returning function is illegal"); break; } gvartype = prefix(FUNCTION, ftypesize, gvartype); } else if (sym == LBRACKET) { nextsym(); if (sym == RBRACKET) asize = 0; else asize = constexpression() & intmaskto; /* FIXME: warn overflow */ rbracket(); declaf(); if (gvartype->typesize == 0) switch (gvartype->constructor) { case FUNCTION: error("array of functions is illegal"); break; case STRUCTU: error("undefined structure"); break; default: /* array */ error("null dimension"); gvartype->typesize = 1; } gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype); } } PRIVATE void declarator() { rdeclarator(); if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 && gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL) error("undefined structure"); } PRIVATE void declarg() { if (gvarsymptr->level != ARGLEVEL) error2error(gvarname, " not in argument list"); else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype) multidecl(gvarname); else { gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */ if (gvartype->constructor & (ARRAY | POINTER)) gvartype = pointype(gvartype->nexttype); gvarsymptr->type = gvartype; if (gvarsc == REGDECL && regdecl()) regarg = TRUE; } } /* enum-specifier = "enum" [identifier] "{" enumerator {, enumerator} "}" | "enum" identifier. enumerator = identifier | identifier = constant-expression. */ PRIVATE struct typestruct *declenum() { register struct symstruct *esymptr; register struct typestruct *enumtype; offset_T ordinal; nextsym(); if (sym != IDENT && sym != TYPEDEFNAME) enumtype = addstruct(""); else if ((esymptr = findstruct(gsname)) == NULL) { enumtype = addstruct(gsname); nextsym(); } else { nextsym(); enumtype = esymptr->type; if (sym != LBRACE) return enumtype; if (esymptr->level != level) enumtype = addstruct(esymptr->name.namea); } lbrace(); if (enumtype->typesize != 0) multidecl(enumtype->tname); else { enumtype->typesize = itypesize; enumtype->alignmask = itype->alignmask; } if (sym != IDENT) error("empty enumerator list"); ordinal = 0; while (sym == IDENT) { if ((esymptr = gsymptr) != NULL && esymptr->level == level) multidecl(gsname); else { (esymptr = addlorg(gsname, itype))->storage = CONSTANT; esymptr->indcount = 0; } nextsym(); if (sym == ASSIGNOP) { nextsym(); ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */ if (ordinal > maxintto) ordinal -= (maxuintto + 1); } if (esymptr->storage == CONSTANT) esymptr->offset.offv = ordinal++; if (sym != COMMA) break; nextsym(); } rbrace(); return enumtype; } /* declselt - get list of declarations for a structure/union member */ PRIVATE void declselt(structype, psoffset, ptypelist) struct typestruct *structype; offset_T *psoffset; struct typelist **ptypelist; { struct typestruct *basetype; value_t fieldwidth; value_t fwidth; offset_T offset; scalar_t scalar=0; offset = *psoffset; declspec(); if (gvarsc != NULLDECL) error("illegal type name"); basetype = gvartype; while (sym != SEMICOLON && sym != EOFSYM) { gvartype = basetype; declarator(); fieldwidth = -1; if (sym == COLON) { scalar = gvartype->scalar; if (!(scalar & ISCALAR)) error("bitfield has non-integral type"); nextsym(); fwidth = constexpression(); if (fwidth < 0) error("bitfield has negative width"); else if (fwidth > INT32BITSTO) /* XXX */ error("bitfield is too wide"); else fieldwidth = fwidth; } if (gvarname[0] == 0) { if (fieldwidth == 0) offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; else /* XXX - should really align to fieldwidth'th bit. */ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask; } else { if (fieldwidth == 0) error("bitfield has zero width"); else if (fieldwidth > 0 && scalar & ISCALAR) { if (fieldwidth <= CHBITSTO) /* XXX! */ gvartype = ctype; else if (fieldwidth <= INT32BITSTO) /* XXX */ gvartype = itype; else gvartype = ltype; if (scalar & UNSIGNED) gvartype = tounsigned(gvartype); } gvar2name[0] = structype->structkey[0]; gvar2name[1] = structype->structkey[1]; /* key provides unique name space */ if (findlorg(gvar2name) != NULL) multidecl(gvarname); else { (gvarsymptr = addlorg(gvar2name, gvartype))->storage = NOSTORAGE; structype->alignmask &= gvartype->alignmask; offset = (gvarsymptr->offset.offi = (offset+ ~gvartype->alignmask) & gvartype->alignmask) + gvartype->typesize; { register struct typelist *newtypelist; newtypelist = qmalloc(sizeof *newtypelist); #ifdef TS ++ts_n_newtypelist; ts_s_newtypelist += sizeof *newtypelist; #endif newtypelist->tlnext = NULL; newtypelist->tltype = gvartype; if (*ptypelist == NULL) structype->listtype = newtypelist; else (*ptypelist)->tlnext = newtypelist; *ptypelist = newtypelist; } } } if (sym != COMMA) break; nextsym(); } semicolon(); *psoffset = offset; } PRIVATE bool_pt declspec() { unsigned nsc; unsigned nsigned; unsigned ntype; unsigned nunsigned; gvarsc = NULLDECL; gvartype = itype; nsigned = nunsigned = ntype = nsc = 0; while (TRUE) { switch (sym) { case AUTODECL: ++nsc; gvarsc = sym; nextsym(); break; case ENUMDECL: ++ntype; declenum(); gvartype = itype; /* kludge - ignore type of enum */ break; case EXTERNDECL: ++nsc; gvarsc = sym; nextsym(); break; case REGDECL: ++nsc; gvarsc = sym; nextsym(); break; case STATICDECL: ++nsc; gvarsc = sym; nextsym(); break; case STRUCTDECL: case UNIONDECL: ++ntype; gvartype = declsu(); break; case TYPEDECL: if (ntype == 1) { /* allow short int and long int */ if (gvartype == itype && (gsymptr->type == stype || gsymptr->type == ltype)) ntype = 0; /* Allow long double and long float */ if (gvartype == ltype && (gsymptr->type == fltype || gsymptr->type == dtype)) { gvartype = dtype; nextsym(); break; } /* allow int short and int long, blech */ if (gsymptr->type == itype && (gvartype == stype || gvartype == ltype)) { nextsym(); break; } } ++ntype; gvartype = gsymptr->type; nextsym(); break; case TYPEDEFDECL: ++nsc; gvarsc = sym; nextsym(); break; case TYPEDEFNAME: if (ntype != 0) goto break2; ++ntype; gvartype = gsymptr->type; nextsym(); break; case SIGNDECL: ++nsigned; nextsym(); break; case UNSIGNDECL: ++nunsigned; nextsym(); break; case ASMSYM: nextsym(); doasm(); break; default: goto break2; } } break2: if (nsigned > 0) { if (ntype == 0) { gvartype = itype; ntype = 1; } gvartype = tosigned(gvartype); if (nsigned > 1 || nunsigned > 0) ntype = 2; } if (nunsigned > 0) { if (ntype == 0) { gvartype = uitype; ntype = 1; } gvartype = tounsigned(gvartype); if (nunsigned > 1 || nsigned > 0) ntype = 2; } if (nsc > 0) { if (ntype == 0) ntype = 1; if (nsc > 1) error("multiple storage classes in declaration"); } if (ntype > 1) error("multiple types in declaration"); return nsc > 0 || ntype > 0; } /* declsu - get structure or union name and/or declaration, return type */ PRIVATE struct typestruct *declsu() { sym_t ogvarsc; offset_T soffset; offset_T struclength; sym_t susym; struct typelist *typelist; struct typestruct *structype; susym = sym; nextsym(); if (sym != IDENT && sym != TYPEDEFNAME) structype = addstruct(""); else if ((gvarsymptr = findstruct(gsname)) == NULL) { structype = addstruct(gsname); nextsym(); } else { nextsym(); if (sym == LBRACE && gvarsymptr->level != level) structype = addstruct(gvarsymptr->name.namea); else structype = gvarsymptr->type; } if (sym != LBRACE) return structype; if (structype->typesize != 0) multidecl(structype->tname); nextsym(); ogvarsc = gvarsc; struclength = soffset = 0; typelist = NULL; while (sym != RBRACE && sym != EOFSYM) { declselt(structype, &soffset, &typelist); if (susym == STRUCTDECL) struclength = soffset; else { if (struclength < soffset) struclength = soffset; soffset = 0; } } structype->typesize = (struclength + ~structype->alignmask) & structype->alignmask; rbrace(); gvarsc = ogvarsc; return structype; } /* declfunc() - function name and parameter list */ PRIVATE void declfunc() { offset_T argsp; uoffset_T argsize; struct symstruct *symptr; int main_flag = 0; strcpy(funcname, gvarname); if( strcmp(funcname, "main") != 0 ) main_flag = -1; if (gvarsymptr == NULL) gvarsymptr = addglb(gvarname, gvartype); else if (gvarsymptr->type != gvartype || (gvarsymptr->flags & INITIALIZED)) multidecl(gvarname); /* different type or full declare */ gvarsymptr->flags = INITIALIZED; /* show full declare */ cseg(); if (gvarsc == STATICDECL) private(gvarname); /* don't need to put STATIC in flags */ else public(gvarname); callee1mask = calleemask; #ifdef FRAMEPOINTER frame1list = framelist; #endif func1saveregsize = funcsaveregsize; #if 0 if ((returntype = gvartype->nexttype)->scalar & RSCALAR) #else if ((returntype = gvartype->nexttype)->scalar & DOUBLE) #endif { callee1mask &= ~doublreturnregs; #ifdef FRAMEPOINTER frame1list &= ~doublreturnregs; #endif func1saveregsize = funcdsaveregsize; } arg1size = /* would already be 0 unless last function empty */ #ifdef FRAMEPOINTER framep = stackarg = #endif reguse = 0; /* would already be 0 unless last f had reg vars */ decllist(); argsp = returnadrsize; if (returntype->constructor & STRUCTU) argsp += ptypesize; softsp = -func1saveregsize; for (symptr = &locsyms[0]; symptr < locptr && symptr->flags != STRUCTNAME && *symptr->name.namea >= 'A'; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) { if( main_flag >= 0 ) main_flag++; /* convert arg sizes to offsets */ if (symptr->type == fltype) symptr->type = dtype; argsize = symptr->type->typesize; #ifdef FRAMEPOINTER if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR) stackarg = TRUE; #endif if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR) { if ((arg1size = argsize) < itypesize) arg1size = itypesize; argsp = softsp -= arg1size; } #if INT_BIG_ENDIAN if (argsize < itypesize) argsp += itypesize - argsize; symptr->offset.offi = argsp; argsp += argsize; #else symptr->offset.offi = argsp; if (argsize > itypesize) argsp += argsize; else argsp += itypesize; #endif if (arg1inreg && symptr == &locsyms[0]) argsp = returnadrsize; /* skip return adr after 1st arg */ } if( main_flag > 0 ) { globl("__mkargv"); if( main_flag > 2 ) globl("environ"); } #ifdef I8088 regfuse = 0; #endif lbrace(); compound(); #ifdef I8088 if (regfuse & (callee1mask | INDREG0)) { outstr("! Register"); if (regfuse & INDREG0 ) outstr(" BX"); if (regfuse & INDREG1 & callee1mask) outstr(" SI"); if (regfuse & INDREG2 & callee1mask) outstr(" DI"); if (regfuse & LOCAL & callee1mask) outstr(" BP"); outstr(" used in function "); outnstr(funcname); if (optimise && !callersaves) { outstr(funcname); outnstr(".off = 0"); } } else if (optimise && !callersaves) { outstr(funcname); outstr(".off = "); #ifndef I80386 outnhex(4); #else outnhex(i386_32?12:4); #endif } #endif clearfunclabels(); } /* idecllist() - list of init-declarations with a given base type */ /* this does the non-terminal symbols list( init-declarator ) ";" */ /* and list( type-declaration ) ";" */ /* and complete declarations of functions */ PRIVATE void idecllist() { struct typestruct *basetype; struct typestruct *inittype; scopelev_t levelmark; uoffset_T newoffset; argsallowed = level == GLBLEVEL; levelmark = level; basetype = gvartype; while (sym != SEMICOLON) { gvartype = basetype; declarator(); if (gvarname[0] == 0) needvarname(); if (gvartype->constructor == FUNCTION) { if (sym != COMMA && sym != SEMICOLON) { if (level == ARGLEVEL && gvarsc != TYPEDEFDECL) declfunc(); else error("illegal non-external function"); if (level != levelmark) { oldlevel(); locptr = &locsyms[0]; } argsallowed = FALSE; return; } } if (level != levelmark) { oldlevel(); locptr = &locsyms[0]; } argsallowed = FALSE; if (level == ARGLEVEL) { if (gvarsymptr == NULL) gvarsymptr = addglb(gvarname, gvartype); /* error soon */ declarg(); } else if (gvarsymptr != NULL && (gvarsymptr->level == level || gvartype->constructor == FUNCTION || (gvarsc == EXTERNDECL && gvarsymptr->level == GLBLEVEL))) { if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD) multidecl(gvarname); else if (gvarsymptr->type != gvartype) { if (gvartype->constructor != ARRAY || gvarsymptr->type->constructor != ARRAY || gvartype->nexttype != gvarsymptr->type->nexttype || (gvartype->typesize != 0 && gvarsymptr->type->typesize != 0)) multidecl(gvarname); else if (gvartype->typesize != 0) gvarsymptr->type = gvartype; } if (gvarsc == NULLDECL) gvarsymptr->flags &= ~EXTERNAL; } else if (level == GLBLEVEL || gvartype->constructor == FUNCTION || gvarsc == EXTERNDECL) { gvarsymptr = addglb(gvarname, gvartype); #ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */ if (!(gvartype->constructor & ~POINTER)) gvarsymptr->flags = DIRECTPAGE; #endif if (gvarsc == EXTERNDECL) gvarsymptr->flags |= EXTERNAL; } else { gvarsymptr = addloc(gvarname, gvartype); if ((gvarsc != REGDECL || !regdecl()) && gvartype->constructor != FUNCTION && gvarsc != STATICDECL && gvarsc != TYPEDEFDECL) gvarsymptr->offset.offi = softsp = (softsp & gvartype->alignmask) - gvartype->typesize; } if (gvarsc == STATICDECL) { gvarsymptr->flags &= ~EXTERNAL; gvarsymptr->flags |= STATIC; if (gvarsymptr->level != GLBLEVEL) { gvarsymptr->storage = GLOBAL; gvarsymptr->offset.offlabel = getlabel(); /* must leave gvarsymptr->name.label alone */ /* since name is required for findlorg() */ /* label is activated by expression() */ } } if (gvarsc == TYPEDEFDECL) { gvarsymptr->flags = KEYWORD; gvarsymptr->offset.offsym = TYPEDEFNAME; } if (sym == ASSIGNOP) { if (gvarsymptr->flags & INITIALIZED) multidecl(gvarname); nextsym(); if (level == GLBLEVEL || gvarsc == STATICDECL) { #ifndef DIRECTPAGE dseg(); #else if (gvarsymptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif if ((inittype = gvartype)->constructor == ARRAY) inittype = inittype->nexttype; newoffset = (dataoffset + ~inittype->alignmask) & inittype->alignmask; defnulls(newoffset - dataoffset); dataoffset = newoffset; if (gvarsc == STATICDECL) { if (level == GLBLEVEL) private(gvarname); else outnlabel(gvarsymptr->offset.offlabel); } else public(gvarname); initlistflag = TRUE; if (sym != LBRACE) initlistflag = FALSE; inititem(gvartype); dataoffset += (gvarsymptr->type = gvartype)->typesize; if (gvarsymptr->level == GLBLEVEL) gvarsymptr->flags |= INITIALIZED; if (level != GLBLEVEL) cseg(); } else { if (gvarsc == EXTERNDECL) error("initialization of externs is illegal"); switch (gvartype->constructor) { case ARRAY: error("initialization of auto arrays is illegal"); break; case FUNCTION: error("initialization of functions is illegal"); break; default: initexpression(gvartype); break; } } } else if (level != GLBLEVEL && gvarsc == STATICDECL && gvartype->constructor != FUNCTION) { #ifndef DIRECTPAGE bssseg(); #else if (gvarsymptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif lcommlab(gvarsymptr->offset.offlabel); outnhex(gvartype->typesize); cseg(); } if (sym != COMMA) break; nextsym(); } semicolon(); argsallowed = FALSE; } PRIVATE void initarray(type) struct typestruct *type; { uoffset_T basesize; struct typestruct *basetype; uoffset_T dimension; char *stringend; uoffset_T stringlength; uoffset_T remaining; if ((basesize = (basetype = type->nexttype)->typesize) == 0) dimension = remaining = 0; else dimension = remaining = type->typesize / basesize; if (sym == STRINGCONST && (basetype->scalar & CHAR)) { stringlength = (stringend = charptr) - constant.value.s; if (remaining != 0 && stringlength >= remaining) /* same dim should be allowed but defstr always nullterms */ { error("string longer than dimension"); stringend = constant.value.s + (/* size_t */ unsigned) (stringlength = remaining - 1); } defstr(constant.value.s, stringend, TRUE); remaining -= (stringlength + 1); nextsym(); } else do inititem(basetype); while (--remaining != 0 && sym == COMMA && initlistflag && (nextsym(), sym != RBRACE)); if (dimension == 0) { if (type == gvartype) gvartype = prefix(ARRAY, -remaining * basesize, basetype); } else defnulls(remaining * basesize); } PRIVATE void inititem(type) struct typestruct *type; { sym_t startsym; if ((startsym = sym) == LBRACE) nextsym(); switch (type->constructor) { case ARRAY: initarray(type); break; case STRUCTU: initstruct(type); break; case FUNCTION: error("initialization of functions is illegal"); break; default: initexpression(type); } if (startsym == LBRACE) { if (sym == COMMA) { nextsym(); if (sym != RBRACE) error("too many initializers"); } rbrace(); } } PRIVATE void initstruct(type) struct typestruct *type; { struct typestruct *memtype; uoffset_T newoffset; uoffset_T offset; struct typelist *typelist; offset = 0; if ((typelist = type->listtype) != NULL) do { memtype = typelist->tltype; newoffset = (offset + ~memtype->alignmask) & memtype->alignmask; defnulls(newoffset - offset); offset = newoffset + memtype->typesize; inititem(memtype); } while ((typelist = typelist->tlnext) != NULL && sym == COMMA && initlistflag && (nextsym(), sym != RBRACE)); /* eof here will break next time */ defnulls(type->typesize - offset); } PRIVATE void lbrace() { if (sym != LBRACE) need('{'); else nextsym(); } PUBLIC void lparen() { if (sym != LPAREN) need('('); else nextsym(); } PRIVATE void multidecl(sname) char *sname; { error2error(sname, " already declared"); } PRIVATE void need(charneeded) int charneeded; { static char message[] = "need 'x'"; message[6] = charneeded; error(message); } PUBLIC void needvarname() { error("need variable name"); nextsym(); } PUBLIC void program() { #ifdef BUILTIN_CPP if (orig_cppmode) cppscan(0); else #endif { nextsym(); while (sym != EOFSYM) { declspec(); idecllist(); } } } PUBLIC void rbrace() { if (sym != RBRACE) need('}'); else nextsym(); } PUBLIC void rbracket() { if (sym != RBRACKET) need(']'); else nextsym(); } PRIVATE void rdeclarator() { while (sym == STAR) { nextsym(); gvartype = pointype(gvartype); } if (sym == LPAREN) { struct typestruct *pretype; struct typestruct *sufftype; nextsym(); sufftype = gvartype; gvartype = ctype; rdeclarator(); rparen(); pretype = gvartype; gvartype = sufftype; declaf(); gvartype = chainprefix(pretype, gvartype); } else if (sym == IDENT || sym == TYPEDEFNAME) { strcpy(gvarname, gsname); gvarsymptr = gsymptr; nextsym(); } else { gvarname[0] = 0; gvarsymptr = NULL; } declaf(); } PRIVATE bool_pt regdecl() { store_t regavail; #if !NOTFINISHED if (gvarsymptr->type->constructor != POINTER) return FALSE; #endif #ifdef MC6809 if (gvarsymptr->type->constructor != POINTER) return FALSE; #endif if (!(regavail = regregs & ~reguse)) return FALSE; gvarsymptr->flags = REGVAR; gvarsymptr->indcount = 0; #define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */ reguse |= gvarsymptr->storage = LOWBITMASK(regavail); return TRUE; } PUBLIC void rparen() { if (sym != RPAREN) need(')'); else nextsym(); } PUBLIC void semicolon() { outnstr("!BCC_EOS"); if (sym != SEMICOLON) need(';'); else nextsym(); } PUBLIC struct typestruct *typename() { char ogvarname[NAMESIZE]; sym_t ogvarsc; struct symstruct *ogvarsymptr; struct typestruct *ogvartype; struct typestruct *type; /* the global variable data must be preserved */ /* although this is only called for casts and sizeof, */ /* the casts can be in initialisers */ /* and the sizeof in an array size expression */ strcpy(ogvarname, gvarname); ogvarsc = gvarsc; ogvarsymptr = gvarsymptr; ogvartype = gvartype; if (declspec()) { declarator(); if (gvarsc != NULLDECL || gvarname[0] != 0) error("illegal type name"); type = gvartype; } else type = NULL; strcpy(gvarname, ogvarname); gvarsc = ogvarsc; gvarsymptr = ogvarsymptr; gvartype = ogvartype; return type; } dev86-0.16.17/bcc/assign.c0000644000000000000000000002313207523003721014737 0ustar rootroot00000000000000/* assign.c - assignment and casting operations for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "sizes.h" #include "type.h" FORWARD void blockmove P((struct symstruct *source, struct symstruct *target)); FORWARD void call3 P((char *funcname, struct symstruct *target, struct symstruct *source, uoffset_T size)); FORWARD void fconvert P((struct symstruct *source, struct typestruct *type)); PUBLIC void assign(source, target) struct symstruct *source; struct symstruct *target; { store_pt regpushed; store_pt sourcereg; scalar_t tscalar; if (target->type->constructor & (ARRAY | FUNCTION) || target->flags == TEMP || target->flags == (LABELLED | STRING) || (target->indcount == 0 && target->flags != REGVAR)) { bugerror("botched lvalue"); return; } if (source->storage != target->storage || source->indcount != target->indcount || source->level != target->level || source->offset.offi != target->offset.offi /* kludge union cmp */ || source->type != target->type || ((source->storage & (LOCAL | GLOBAL) || source->level == OFFKLUDGELEVEL) && ((source->flags ^ target->flags) & LABELLED || (source->flags & LABELLED && source->name.label != target->name.label) || (!(source->flags & LABELLED) && strcmp(source->name.namep, target->name.namep) != 0)))) { tscalar = target->type->scalar; if (tscalar & CHAR && source->storage == CONSTANT) { source->offset.offv &= CHMASKTO; source->type = target->type; } regpushed = preslval(source, target); if (!(tscalar & CHAR) || source->flags != TEMP || source->offset.offi != sp || source->type->typesize > itypesize) cast(target->type, source); if (tscalar & RSCALAR) { if (source->storage == CONSTANT && (!reguse & doubleregs)) load(source, doubleregs & ~DREG); if (source->storage != CONSTANT && source->indcount == 0) { /* XXX - 386 only */ storereg(DREG, target); #ifdef I80386 if (i386_32) { if (tscalar & DOUBLE) { target->indcount = 1; /* XXX outnnadr clobbers this */ target->offset.offi += accregsize; storereg(doubleregs & ~DREG, target); } } else #endif if (tscalar & DOUBLE) { int i; for(i=1; i; i<<=1) if( i!= DREG && (doubleregs & i) ) { target->indcount = 1; /* XXX outnnadr clobbers this */ target->offset.offi += accregsize; storereg(i, target); } } #ifdef I8088 else if (tscalar & FLOAT) { target->indcount = 1; /* XXX outnnadr clobbers this */ target->offset.offi += accregsize; storereg(DATREG2, target); } #endif target->storage = source->storage; target->offset.offi = 0; } else if (f_indirect(source) && tscalar & DOUBLE && (!(reguse & OPREG) || target->storage == OPREG)) { struct symstruct temptarg; temptarg = *target; pointat(&temptarg); call("Fpull"); outntypechar(temptarg.type); sp += dtypesize; } else blockmove(source, target); } else if (target->type->constructor & STRUCTU) blockmove(source, target); else { if (tscalar & CHAR) load(source, DREG); else if (target->indcount == 0 && target->storage & regregs) load(source, target->storage); else loadany(source); if (tscalar & DLONG) { storereg(DREG, target); target->indcount = 1; target->offset.offi += accregsize; } if ((store_t) (sourcereg = source->storage) == DREG && target->type->scalar & CHAR) sourcereg = BREG; storereg(sourcereg, target); if ((store_t) regpushed != 0) { /* DLONG */ target->indcount = 1; target->offset.offi -= accregsize; recovlist(regpushed); } else { target->storage = sourcereg; target->offset.offi = 0; if (target->level == OFFKLUDGELEVEL) target->level = EXPRLEVEL; } } } } /* block move assumes itypesize == accregsize && BREG size == 1 */ PRIVATE void blockmove(source, target) struct symstruct *source; struct symstruct *target; { struct symstruct oldtarget; uoffset_T typesize; struct symstruct worksource; oldtarget = *target; if ((typesize = target->type->typesize) >= 8 * itypesize || source->indcount + target->indcount != 2) { address(source); address(target); call3("_memcpy", target, source, typesize); } else { if (source->level == OFFKLUDGELEVEL) addoffset(source); /* else kludge is lost and offsets big */ if (target->level == OFFKLUDGELEVEL) addoffset(target); worksource = *source; for (; typesize >= itypesize; typesize -= itypesize) { loadreg(source, DREG); worksource.offset.offi += itypesize; *source = worksource; storereg(DREG, target); target->indcount = 1; target->offset.offi += accregsize; } while (typesize-- != 0) { outload(); outregname(BREG); outopsep(); outadr(source); worksource.offset.offi += 1; *source = worksource; storereg(BREG, target); target->indcount = 1; target->offset.offi += 1; } } *target = oldtarget; } PRIVATE void call3(funcname, target, source, size) char *funcname; struct symstruct *target; struct symstruct *source; uoffset_T size; { store_pt regpushed; offset_T spmark; struct symstruct *length; pushlist(regpushed = reguse & ~calleemask); spmark = sp; length = constsym((value_t) size); length->type = uitype; push(length); push(source); push(target); call(funcname); outnl(); if (regpushed) { modstk(spmark); recovlist(regpushed); } } PUBLIC void cast(type, target) struct typestruct *type; struct symstruct *target; { scalar_t newscalar; uoffset_T newsize; scalar_t oldscalar; uoffset_T oldsize; store_pt targreg; if (type->constructor & (ARRAY | FUNCTION) || (type->constructor & STRUCTU && target->type != type)) { bugerror("botched implicit cast"); return; } if (target->type == type) return; if (target->type->constructor == ARRAY) oldsize = ptypesize; else oldsize = target->type->typesize; newscalar = type->scalar; oldscalar = target->type->scalar; if ((newsize = type->typesize) == oldsize && !((newscalar | oldscalar) & RSCALAR)) ; else if (newsize == ctypesize) /* char only */ { if (oldscalar & RSCALAR) fconvert(target, type); else if (target->indcount == 1) { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN # if INT_BIG_ENDIAN target->offset.offi += oldsize - ctypesize; # else { if (oldscalar & DLONG) target->offset.offi += itypesize; /* discard msword */ } # endif #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 # if INT_BIG_ENDIAN target->offset.offi += ctypesize; # else ; # endif #endif } else if (target->storage != CONSTANT) { load(target, DREG); target->storage = BREG; } } else if ((newscalar & (SHORT | INT | LONG) && !(newscalar & DLONG)) || type->constructor & POINTER) { if (oldscalar & RSCALAR) fconvert(target, type); else if (oldsize < newsize) extend(target); else if (target->indcount == 1) { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN { if (oldscalar & DLONG) target->offset.offi += itypesize; /* discard msword */ } #endif } else load(target, DREG); } else if (newscalar & DLONG) { if (oldscalar & RSCALAR) fconvert(target, type); else if (target->storage != CONSTANT) { extend(target); load(target, DREG); target->storage = targreg = getindexreg(); if (oldscalar & UNSIGNED || target->type->constructor & (ARRAY | FUNCTION | POINTER)) uitol(targreg); else itol(targreg); } } else if (newscalar & RSCALAR) { saveopreg(); /* XXX */ if (oldscalar & (ISCALAR | FLOAT)) fpush(target); if (newscalar & FLOAT) { pointat(target); call("dto"); outntypechar(type); justpushed(target); /* XXX - sets dtype wrong (harmless) and * wastes (dtypesize - ftypesize) stack */ } restoreopreg(); } target->type = type; } /* extend char or short to int (unsigned if from unsigned) */ PUBLIC void extend(target) struct symstruct *target; { scalar_t tscalar; if ((tscalar = target->type->scalar) & (CHAR | SHORT)) { if (target->storage != CONSTANT && target->type->typesize < itypesize) { load(target, DREG); if (target->type == sctype) sctoi(); #if defined(I8088) && defined(I80386) else if (tscalar & SHORT) { if (tscalar & UNSIGNED) ustoi(); else stoi(); } #endif else ctoi(); target->storage = DREG; } if (tscalar & UNSIGNED) target->type = uitype; else target->type = itype; } } PRIVATE void fconvert(source, type) struct symstruct *source; struct typestruct *type; { offset_T spmark; pushlist(reguse & OPREG); spmark = sp; pointat(source); if (source->type->scalar & DOUBLE) call("dto"); else call("fto"); if (type->scalar & UNSIGNED) outbyte('u'); outntypechar(type); if (type->scalar & DLONG) { if (reguse & OPREG) bugerror("loading long into used reg"); source->storage = OPREG; } else if (type->scalar & CHAR) source->storage = BREG; else source->storage = DREG; source->offset.offi = source->flags = source->indcount = 0; modstk(spmark); /* could adjust later (load instead of pop) */ poplist(reguse & OPREG); } dev86-0.16.17/bcc/debug.h0000644000000000000000000000147210065275677014571 0ustar rootroot00000000000000 #ifndef _DEBUG_H_ #define _DEBUG_H_ #if __STDC__ void debug_do_setlevel(char * fname, int lineno, int level); int debug_pos(char * file, int lineno); int debug_msg(int level, char * name, ...); int debug_never(int level, char * name, ...); #else void debug_do_setlevel(); int debug_pos(); int debug_msg(); int debug_never(); #endif /* __STDC__ */ /* The new CPP has these. */ #if defined(__BCC__) && (__BCC_VERSION__ >= 0x001011L) #define VARARG_MACROS #endif #ifdef DEBUG extern int debug_level; #define debug !debug_level?0:debug_pos(__FILE__,__LINE__)+debug_msg #define debug_setlevel(lvl) debug_do_setlevel(__FILE__, __LINE__, lvl) #else /* !DEBUG */ #ifdef VARARG_MACROS # define debug(junk ...) 0 #else # define debug 1?0:debug_never #endif # define debug_setlevel(lvl) #endif /* DEBUG */ #endif /* _DEBUG_H_ */ dev86-0.16.17/bcc/dbprintf.c0000644000000000000000000001043610065343022015262 0ustar rootroot00000000000000 #include #include #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) #include #define va_strt va_start #else #include #define va_strt(p,i) va_start(p) #endif #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__) int dbprintf(const char * fmt, ...) #else int dbprintf(fmt, va_alist) __const char *fmt; va_dcl #endif { va_list ptr; int rv; va_strt(ptr, fmt); rv = vdbprintf(fmt,ptr); va_end(ptr); return rv; } static unsigned char * __numout (long i, int base); static void putch(int ch) { static char buf[2]; *buf = ch; write(2,buf,1); } int vdbprintf(fmt, ap) register __const char *fmt; register va_list ap; { int c; int count = 0; int type, base; long val; char * cp; char padch=' '; int minsize, maxsize; while(c=*fmt++) { count++; if(c!='%') putch(c); else { type=1; padch = *fmt; maxsize=minsize=0; if(padch == '-') fmt++; for(;;) { c=*fmt++; if( c<'0' || c>'9' ) break; minsize*=10; minsize+=c-'0'; } if( c == '.' ) for(;;) { c=*fmt++; if( c<'0' || c>'9' ) break; maxsize*=10; maxsize+=c-'0'; } if( padch == '-' ) minsize = -minsize; else if( padch != '0' ) padch=' '; if( c == 0 ) break; if(c=='h') { c=*fmt++; type = 0; } else if(c=='l') { c=*fmt++; type = 2; } switch(c) { case 'x': base=16; type |= 4; if(0) { case 'o': base= 8; type |= 4; } if(0) { case 'u': base=10; type |= 4; } if(0) { case 'd': base=-10; } switch(type) { case 0: /* Promoted: val=va_arg(ap, short); break; */ case 1: val=va_arg(ap, int); break; case 2: val=va_arg(ap, long); break; case 4: /* Promoted: val=va_arg(ap, unsigned short); break; */ case 5: val=va_arg(ap, unsigned int); break; case 6: val=va_arg(ap, unsigned long); break; default:val=0; break; } cp = __numout(val,base); if(0) { case 's': cp=va_arg(ap, char *); } count--; c = strlen(cp); if( !maxsize ) maxsize = c; if( minsize > 0 ) { minsize -= c; while(minsize>0) { putch(padch); count++; minsize--; } minsize=0; } if( minsize < 0 ) minsize= -minsize-c; while(*cp && maxsize-->0 ) { putch(*cp++); count++; } while(minsize>0) { putch(' '); count++; minsize--; } break; case 'c': putch(va_arg(ap, int)); break; case 'C': c = va_arg(ap, int); if (c>0x7F) { c &=0x7F; putch('M'); putch('-'); } if (c<' ' || c == '\177') { putch('^'); putch(c^'@'); } else putch(c); break; default: putch(c); break; } } } return count; } static char nstring[]="0123456789ABCDEF"; #ifndef __AS386_16__ #define NUMLTH 11 static unsigned char * __numout(long i, int base) { static unsigned char out[NUMLTH+1]; int n; int flg = 0; unsigned long val; if (base<0) { base = -base; if (i<0) { flg = 1; i = -i; } } val = i; out[NUMLTH] = '\0'; n = NUMLTH-1; do { out[n--] = nstring[val % base]; val /= base; } while(val); if(flg) out[n--] = '-'; return &out[n+1]; } #else #asm ! numout.s ! .bss ___out lcomm $C .text ___numout: push bp mov bp,sp push di push si add sp,*-4 mov byte ptr -8[bp],*$0 ! flg = 0 mov si,4[bp] ; i or val.lo mov di,6[bp] ; i or val.hi mov cx,8[bp] ; base test cx,cx ! base < 0 ? jge .3num neg cx ! base = -base or di,di ! i < 0 ? jns .5num mov byte ptr -8[bp],*1 ! flg = 1 neg di ! i = -i neg si sbb di,0 .5num: .3num: mov byte ptr [___out+$B],*$0 ! out[11] = nul mov -6[bp],*$A ! n = 10 .9num: !!! out[n--] = nstring[val % base]; xor dx,dx xchg ax,di div cx xchg ax,di xchg ax,si div cx xchg ax,si ! val(new) = val / base mov bx,dx ! dx = val % base mov al,_nstring[bx] mov bx,-6[bp] dec word ptr -6[bp] mov ___out[bx],al mov ax,si or ax,di ! while (val) jne .9num cmp byte ptr -8[bp],*$0 ! flg == 0 ? je .Dnum mov bx,-6[bp] dec word ptr -6[bp] mov byte ptr ___out[bx],*$2D ! out[n--] = minus .Dnum: mov ax,-6[bp] add ax,#___out+1 add sp,*4 pop si pop di pop bp ret #endasm #endif dev86-0.16.17/bcc/type.c0000644000000000000000000001121707523172555014451 0ustar rootroot00000000000000/* type.c - type and storage-class routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "gencode.h" /* s.b. switches.h */ #include "sc.h" #include "scan.h" #include "table.h" #undef EXTERN #define EXTERN #include "type.h" PUBLIC uoffset_T ctypesize = 1; PUBLIC uoffset_T dtypesize = 8; PUBLIC uoffset_T ftypesize = 0; PUBLIC uoffset_T itypesize = 2; PUBLIC uoffset_T ptypesize = 2; PUBLIC uoffset_T stypesize = 2; PRIVATE char skey0; PRIVATE char skey1; PUBLIC struct typestruct *addstruct(structname) char *structname; { unsigned namelength; struct symstruct *symptr; struct typestruct *structype; (structype = newtype())->constructor = STRUCTU; structype->alignmask = ctype->alignmask; if (++skey1 == 0) { ++skey1; /* must be nonzero or key string would end */ ++skey0; /* will never reach 'A' to be an identifier */ } structype->structkey[0] = skey0; structype->structkey[1] = skey1; if (*structname != 0) { symptr = addlorg(structname, structype); symptr->storage = 0; symptr->flags = STRUCTNAME; if (charptr + (namelength = strlen(structname)) >= chartop) growheap(namelength + 1); #ifdef TS ++ts_n_structname; ts_s_structname += namelength + 1; #endif structype->tname = strcpy(charptr, structname); charptr += namelength + 1; } return structype; } PUBLIC struct typestruct *iscalartotype(scalar) scalar_pt scalar; { if (scalar & LONG) { if (scalar & UNSIGNED) return ultype; return ltype; } if (scalar & UNSIGNED) return uitype; return itype; } PUBLIC struct typestruct *newtype() { register struct typestruct *type; type = qmalloc(sizeof *type); #ifdef TS ++ts_n_type; ts_s_type += sizeof *type; #endif type->typesize = /* (uoffset_T) */ type->scalar = /* (scalar_t) */ type->constructor = /* (constr_t) */ type->structkey[0] = 0; type->nexttype = type->prevtype = type->sidetype = NULL; type->listtype = NULL; type->tname = ""; return type; } PUBLIC void outntypechar(type) struct typestruct *type; { outnbyte(*type->tname); } PUBLIC struct typestruct *pointype(type) struct typestruct *type; { return prefix(POINTER, ptypesize, type); } PUBLIC struct typestruct *prefix(constructor, size, type) constr_pt constructor; uoffset_T size; struct typestruct *type; { register struct typestruct *searchtype; for (searchtype = type->prevtype; searchtype != NULL; searchtype = searchtype->sidetype) if (searchtype->constructor == (constr_t) constructor && searchtype->typesize == size) return searchtype; switch ((searchtype = newtype())->constructor = constructor) { case ARRAY: searchtype->alignmask = type->alignmask; break; case FUNCTION: searchtype->alignmask = ~(uoffset_T) 0; break; case POINTER: searchtype->alignmask = ~(ptypesize - 1) | alignmask; break; case STRUCTU: bugerror("prefixing structure/union"); searchtype->alignmask = alignmask; break; } searchtype->typesize = size; searchtype->nexttype = type; searchtype->sidetype = type->prevtype; return type->prevtype = searchtype; } PUBLIC struct typestruct *promote(type) struct typestruct *type; { scalar_t scalar; if ((scalar = type->scalar) & (CHAR | SHORT)) { if (scalar & UNSIGNED) return uitype; return itype; } if (scalar & FLOAT) return dtype; if (type->constructor & ARRAY) return pointype(type->nexttype); if (type->constructor & FUNCTION) return pointype(type); return type; } PUBLIC struct typestruct *tosigned(type) struct typestruct *type; { switch (type->scalar & ~(UNSIGNED | DLONG)) { case CHAR: return sctype; case SHORT: return stype; case INT: return itype; case LONG: return ltype; default: error("signed only applies to integral types"); return type; } } PUBLIC struct typestruct *tounsigned(type) struct typestruct *type; { switch (type->scalar & ~(UNSIGNED | DLONG)) { case CHAR: return uctype; case SHORT: return ustype; case INT: return uitype; case LONG: return ultype; default: error("unsigned only applies to integral types"); return type; } } PUBLIC void typeinit() { #ifdef I80386 if (i386_32) { uitype->typesize = itype->typesize = ptypesize = itypesize = 4; dtype->alignmask = fltype->alignmask = uitype->alignmask = ltype->alignmask = ultype->alignmask = itype->alignmask = ~(uoffset_T) (4 - 1); ltype->scalar = LONG; /* not DLONG */ ultype->scalar = UNSIGNED | LONG; } #endif fitype = prefix(FUNCTION, ftypesize, itype); pctype = pointype(ctype); skey0 = 1; vtype->constructor = VOID; } dev86-0.16.17/bcc/genloads.c0000644000000000000000000007621310171677724015274 0ustar rootroot00000000000000/* genloads.c - generate loads of registers and memory for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "condcode.h" #include "gencode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" FORWARD void badaddress P((void)); FORWARD void blockpush P((struct symstruct *source)); FORWARD void loadadr P((struct symstruct *source, store_pt targreg)); FORWARD void loadlongindirect P((struct symstruct *source, store_pt targreg)); FORWARD void outnamoffset P((struct symstruct *adr)); FORWARD void outnnadr P((struct symstruct *adr)); FORWARD fastin_pt pushpull P((store_pt reglist, bool_pt pushflag)); PUBLIC void addoffset(source) struct symstruct *source; { #ifdef I8088 if (source->level == OFFKLUDGELEVEL) { outadd(); outregname(source->storage); outcomma(); outimmed(); outnamoffset(source); outnl(); if (source->storage & (AXREG | ALREG)) unbumplc(); if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; } else #endif if (source->offset.offi != 0) { addconst(source->offset.offi, source->storage); source->offset.offi = 0; } } PUBLIC void address(source) struct symstruct *source; { if (source->indcount == 0) bugerror("taking address of non-lvalue"); else { if (source->type->constructor & (ARRAY | FUNCTION)) bugerror("botched indirect array or function"); else if (--source->indcount == 0 && source->storage == GLOBAL && !(source->flags & LABELLED) && *source->name.namep == 0) source->storage = CONSTANT; source->type = pointype(source->type); } } PRIVATE void badaddress() { bugerror("bad address"); } PRIVATE void blockpush(source) struct symstruct *source; { struct symstruct *length; offset_T spmark; uoffset_T typesize; typesize = source->type->typesize; length = constsym((value_t) typesize); length->type = uitype; address(source); modstk(spmark = sp - (offset_T) typesize); #ifdef STACKREG regtransfer(STACKREG, DREG); #else #ifdef MC6809 /* XXX ? */ regtransfer(LOCAL, DREG); #else #include "need STACKREG and stackregstr" #endif #endif push(length); push(source); pushreg(DREG); call("_memcpy"); outnl(); modstk(spmark); indirec(source); } PUBLIC void exchange(source, target) struct symstruct *source; struct symstruct *target; { store_t tempreg; regexchange(source->storage, target->storage); tempreg = target->storage; target->storage = source->storage; source->storage = tempreg; } /*----------------------------------------------------------------------------- getindexreg() returns the "best" available index register -----------------------------------------------------------------------------*/ PUBLIC store_pt getindexreg() { if (!(reguse & INDREG0)) return INDREG0; if (!(reguse & INDREG1)) return INDREG1; if (!(reguse & INDREG2)) return INDREG2; #if NOTFINISHED #ifdef I80386 if (i386_32) { if (!(reguse & DATREG1)) return DATREG1; if (!(reguse & DATREG2)) return DATREG2; } #endif #endif bugerror("out of index regs"); return 0; } /*----------------------------------------------------------------------------- indexadr(index leaf, pointer leaf) is used by the index and add and subtract (pointer) routines it handles expressions like pointer + index &array[index] the target becomes register direct with offset (except for index = 0, when nothing is changed) constant indexes are optimised by leaving them as offsets register direct pointers are optimised by leaving the offset alone (except for PC register direct, since there is no LEAX D,PC) -----------------------------------------------------------------------------*/ PUBLIC void indexadr(source, target) struct symstruct *source; struct symstruct *target; { #ifdef MC6809 bool_t canABX; #endif uoffset_T size; store_pt sourcereg; struct typestruct *targtype; store_pt targreg; if (!(target->type->constructor & (ARRAY | POINTER))) { bugerror("cannot index"); return; } size = target->type->nexttype->typesize; if (source->storage == CONSTANT) { if (source->offset.offv != 0) { if (target->indcount != 0) loadany(target); target->offset.offi += source->offset.offv * size; } return; } if (target->storage & ALLDATREGS) push(target); if ((store_t) (sourcereg = target->storage) & ~reguse & allindregs) targreg = sourcereg; else targreg = getindexreg(); #ifdef I8088 if ((store_t) sourcereg == GLOBAL && target->indcount == 0 && !(source->type->scalar & CHAR) && source->storage != DREG) load(source, targreg); else #endif load(source, DREG); #ifdef I8088 softop(MULOP, constsym((value_t) size), source); #endif #ifdef MC6809 /*----------------------------------------------------------------------------- do some calculations in advance to decide if index can be done with ABX -----------------------------------------------------------------------------*/ if ((store_t) targreg == XREG && source->type->scalar & CHAR && size < CANABXCUTOFF) canABX = TRUE; else { canABX = FALSE; softop(MULOP, constsym((value_t) size), source); } #endif /*----------------------------------------------------------------------------- deal with constant target - constant becomes offset, result in DREG -----------------------------------------------------------------------------*/ if (target->storage == CONSTANT) { target->storage = DREG; return; } /*----------------------------------------------------------------------------- load target if it is indirect or GLOBAL or canABX so D or B can be added otherwise, it is register direct (maybe S register, maybe with offset) and the offset can be left after adding DREG -----------------------------------------------------------------------------*/ #ifdef I8088 if (target->indcount != 0) { targtype = target->type; target->type = itype; add(source, target); target->type = targtype; return; } if ((store_t) sourcereg == GLOBAL) { target->storage = source->storage; target->level = OFFKLUDGELEVEL; return; } #endif #ifdef MC6809 if (canABX || (store_t) sourcereg == GLOBAL) { load(target, targreg); sourcereg = targreg; } else if (target->indcount != 0) { targtype = target->type; target->type = itype; add(source, target); target->type = targtype; return; } if (canABX) while (size--) outABX(); else #endif { #ifdef I8088 if ((store_t) targreg != (store_t) sourcereg) regtransfer(sourcereg, targreg); outadd(); outregname(targreg); outncregname(DREG); #endif #ifdef MC6809 outlea(); outregname(targreg); outtab(); outregname(DREG); outncregname(sourcereg); #endif } if ((store_t) sourcereg == LOCAL) #ifdef FRAMEPOINTER target->offset.offi -= framep; #else target->offset.offi -= sp; #endif target->storage = targreg; } PUBLIC void indirec(source) struct symstruct *source; { if (!(source->type->constructor & (ARRAY | POINTER))) bugerror("illegal indirection"); else if (source->indcount == (indn_t) - 1) limiterror("too many indirections (256)"); else { if (source->storage & ALLDATREGS) transfer(source, getindexreg()); if (!((source->type = source->type->nexttype)->constructor & (ARRAY | FUNCTION))) ++source->indcount; if (source->storage == CONSTANT) source->storage = GLOBAL; } } /*----------------------------------------------------------------------------- load(source leaf, target register) loads the specified register without changing any others (except CC) if the type is long or float, DREG is paired with the target register the result has no offset -----------------------------------------------------------------------------*/ PUBLIC void load(source, targreg) struct symstruct *source; store_pt targreg; { if (source->type->scalar & DLONG) { if (source->storage == CONSTANT) loadreg(source, targreg); else if (source->indcount == 0) { #if DYNAMIC_LONG_ORDER if (!long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 { if ((store_t) targreg == DREG) source->storage = DREG; } #endif if (source->storage != (store_t) targreg) transfer(source, targreg); if (source->offset.offi != 0) bugerror("loading direct long with offset not implemented"); } else loadlongindirect(source, targreg); } else if (source->type->scalar & DOUBLE) { if (source->storage == targreg && source->indcount == 0) return; if (source->storage == CONSTANT) { #ifdef I80386 if (i386_32) { loadconst(((offset_T *) source->offset.offd)[0], DREG); loadconst(((offset_T *) source->offset.offd)[1], targreg&~DREG); } else /* XXX - more for non-386 */ #endif { int regs, i, off=1; loadconst(((unsigned short *) source->offset.offd)[0], DREG); regs = (targreg&~DREG); for(i=1; i; i<<=1) { if( regs&i ) loadconst( ((unsigned short *) source->offset.offd)[off++], i); } } } else { push(source); poplist(targreg | DREG); /* actually it's the full reg list */ } source->storage = targreg; /* XXX - multi for non-386 */ source->indcount = 0; source->flags = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; } else if (source->type->scalar & FLOAT && source->storage == CONSTANT) { float val; val = *source->offset.offd; #ifdef I80386 if (i386_32) loadconst(((offset_T *) &val)[0], targreg); /* XXX 386 */ else #endif { loadconst(((unsigned short *) &val)[0], DREG); loadconst(((unsigned short *) &val)[1], targreg&~DREG); } } #ifdef I80386 else if (!i386_32 && source->type->scalar & FLOAT) #else else if (source->type->scalar & FLOAT) #endif { /* Treat a float just like a long ... */ if (source->indcount == 0) { if (source->storage != (store_t) targreg) transfer(source, targreg); if (source->offset.offi != 0) bugerror("loading direct float with offset not implemented"); } else loadlongindirect(source, targreg); } else if (source->indcount == 0 && source->storage != CONSTANT) loadadr(source, targreg); else if (source->type->scalar || source->type->constructor & (ARRAY | POINTER)) loadreg(source, targreg); else bugerror("attempting to load non-scalar non-pointer"); } PRIVATE void loadadr(source, targreg) struct symstruct *source; store_pt targreg; { if ((store_t) targreg & ALLDATREGS) { if (source->storage == GLOBAL) { #ifdef MC6809 if (posindependent) { pushreg(INDREG0); loadreg(source, INDREG0); transfer(source, DREG); recovlist(INDREG0); } else #endif loadreg(source, targreg); } if (source->storage == LOCAL) #ifdef FRAMEPOINTER source->offset.offi -= framep; #else source->offset.offi -= sp; #endif if (source->type->scalar & CHAR) targreg = BREG; #ifdef I8088 if (source->storage == DREG) addoffset(source); #endif if (source->storage != (store_t) targreg) transfer(source, targreg); addoffset(source); } else if (source->storage & ALLDATREGS) { addoffset(source); transfer(source, targreg); } else if (source->storage != (store_t) targreg || source->offset.offi != 0 || source->level == OFFKLUDGELEVEL) loadreg(source, targreg); } PUBLIC void loadany(source) struct symstruct *source; { if (source->indcount != 0 || source->offset.offi != 0 || /* kludge u cmp */ source->level == OFFKLUDGELEVEL || !(source->storage & allregs)) { if (source->type->scalar & RSCALAR) load(source, doubleregs & ~DREG); else if ((source->storage == CONSTANT && !(source->type->scalar & DLONG)) || source->type->scalar & CHAR) load(source, DREG); else if (source->storage & ~reguse & allregs) load(source, source->storage); else if (((reguse & allindregs) == allindregs || ((!(source->type->constructor & (ARRAY | POINTER)) && source->indcount != 0) && !(source->type->scalar & DLONG)))) load(source, DREG); else load(source, getindexreg()); } } PRIVATE void loadlongindirect(source, targreg) struct symstruct *source; store_pt targreg; { sc_t flags; offset_T offset; store_t reg; struct typestruct *type; if (source->level == OFFKLUDGELEVEL) addoffset(source); /* else kludge is lost and offsets big */ flags = source->flags; offset = source->offset.offi; reg = source->storage; type = source->type; source->type = itype; loadreg(source, DREG); source->flags = flags; source->storage = reg; source->indcount = 1; source->offset.offi = offset + accregsize; loadreg(source, targreg); source->type = type; } PUBLIC void loadreg(source, targreg) struct symstruct *source; store_pt targreg; { offset_T longhigh; offset_T longlow; if (source->storage == CONSTANT) { if (source->type->scalar & CHAR && (store_t) targreg & ALLDATREGS) targreg = BREG; longlow = (offset_T) source->offset.offv; if (source->type->scalar & DLONG) { longlow &= (offset_T) intmaskto; longhigh = (offset_T) (source->offset.offv >> INT16BITSTO) & (offset_T) intmaskto; if ((store_t) targreg != LONGREG2) /* loading the whole long */ { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN loadconst(longhigh, DREG); #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 { loadconst(longlow, DREG); longlow = longhigh; } #endif } } loadconst(longlow, targreg); source->storage = targreg; source->offset.offi = 0; } else { #ifdef I8088 if (source->indcount == 0 && source->storage != GLOBAL && (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)) { if ((store_t) targreg == source->storage) { addoffset(source); return; } source->indcount = 1; /* fake for outadr() to produce "()" */ outlea(); } else { #ifdef I8088 /* Added acess to CPU registers. Just declare _AX etc. as * extern int, and you can use them to get/set * the register values. (vak) */ if (source->storage == GLOBAL && !(source->flags & LABELLED) && *source->name.namep != 0 && strncmp(source->name.namep, "__", 2) == 0) { if (strcmp (source->name.namep, "__AX") == 0) { /* Load AX register - do nothing. */ done: if (targreg != AXREG) bugerror("specified access of register clone variable not implemented"); source->storage = AXREG; /* in register for further use */ source->flags = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; /* indcount was adjusted by outadr */ return; } if (strcmp (source->name.namep, "__BX") == 0) { outstr ("mov\tax,bx\n"); goto done; } if (strcmp (source->name.namep, "__CX") == 0) { outstr ("mov\tax,cx\n"); goto done; } if (strcmp (source->name.namep, "__DX") == 0) { outstr ("mov\tax,dx\n"); goto done; } if (strcmp (source->name.namep, "__SP") == 0) { outstr ("mov\tax,sp\n"); goto done; } if (strcmp (source->name.namep, "__BP") == 0) { outstr ("mov\tax,bp\n"); goto done; } if (strcmp (source->name.namep, "__SI") == 0) { outstr ("mov\tax,si\n"); goto done; } if (strcmp (source->name.namep, "__DI") == 0) { outstr ("mov\tax,di\n"); goto done; } if (strcmp (source->name.namep, "__CS") == 0) { outstr ("mov\tax,cs\n"); goto done; } if (strcmp (source->name.namep, "__DS") == 0) { outstr ("mov\tax,ds\n"); goto done; } if (strcmp (source->name.namep, "__ES") == 0) { outstr ("mov\tax,es\n"); goto done; } if (strcmp (source->name.namep, "__SS") == 0) { outstr ("mov\tax,ss\n"); goto done; } if (strcmp (source->name.namep, "__FLAGS") == 0) { outstr ("pushf\npop\tax\n"); goto done; } } #endif outload(); if (source->storage == GLOBAL && source->indcount != 0 && (store_t) targreg & (AXREG | ALREG)) unbumplc(); } #endif #ifdef MC6809 if (source->indcount == 0 && (source->storage != GLOBAL || posindependent)) outlea(); else { outload(); if ((store_t) targreg == YREG) bumplc(); } #endif movereg(source, targreg); } } PUBLIC void makelessindirect(source) struct symstruct *source; { store_pt lreg; if (!((store_t) (lreg = source->storage) & ~reguse & allindregs)) lreg = getindexreg(); while (source->indcount > MAXINDIRECT) loadreg(source, lreg); #if MAXINDIRECT > 1 if (source->indcount == MAXINDIRECT && (source->type->typesize > maxregsize || source->type->constructor & FUNCTION)) { source->indcount = 1; loadreg(source, lreg); source->indcount = 1; } #endif } PUBLIC void movereg(source, targreg) struct symstruct *source; store_pt targreg; { if ((store_t) targreg & ALLDATREGS && source->type->scalar & CHAR) targreg = BREG; #ifdef I8086 if (source->type->scalar & CHAR && targreg != BREG && targreg != DATREG1B ) { bugerror("moving char sym into int register"); } #endif #ifdef I80386 if (i386_32 && source->type->scalar & SHORT && source->indcount <= 1) { outshortregname(targreg); bumplc(); } else #endif outregname(targreg); if (source->storage == CONSTANT) adjlc((offset_T) source->offset.offv, targreg); #ifdef I8088 outcomma(); #endif outadr(source); source->storage = targreg; /* in register for further use */ source->flags = 0; if (source->level == OFFKLUDGELEVEL) source->level = EXPRLEVEL; source->offset.offi = 0; /* indcount was adjusted by outadr */ } PUBLIC void onstack(target) register struct symstruct *target; { target->storage = LOCAL; target->flags = TEMP; if (target->level == OFFKLUDGELEVEL) target->level = EXPRLEVEL; target->indcount = 1; target->offset.offi = sp; } PUBLIC void outadr(adr) struct symstruct *adr; { outnnadr(adr); outnl(); } PUBLIC void outcregname(reg) store_pt reg; { outcomma(); outregname(reg); } PRIVATE void outnamoffset(adr) struct symstruct *adr; { if (adr->flags & LABELLED) outlabel(adr->name.label); else outccname(adr->name.namep); if (adr->offset.offi != 0) { if (adr->offset.offi > 0) outplus(); outshex(adr->offset.offi); } bumplc2(); #ifdef I80386 if (i386_32) bumplc2(); #endif } /* print comma, then register name, then newline */ PUBLIC void outncregname(reg) store_pt reg; { outcomma(); outnregname(reg); } PRIVATE void outnnadr(adr) struct symstruct *adr; { bool_t indflag; indflag = FALSE; #ifdef I8088 if (adr->indcount >= MAXINDIRECT) indflag = TRUE; #endif #ifdef MC6809 outtab(); if (adr->indcount >= MAXINDIRECT && (adr->indcount & 1) == 0) { indflag = TRUE; /* indirection means double indirect */ outindleft(); } #endif switch (adr->storage) { case CONSTANT: outimmadr((offset_T) adr->offset.offv); break; #ifdef I8088 case DREG: if (indflag || adr->offset.offi != 0 || adr->level == OFFKLUDGELEVEL) badaddress(); else outregname(DREG); break; #endif #ifdef I8088 case DATREG1: case DATREG2: #ifdef I80386 if (indflag && !i386_32) #else if (indflag) #endif { outnl(); badaddress(); break; } #endif case INDREG0: case INDREG1: case INDREG2: if (adr->level == OFFKLUDGELEVEL) { #ifdef I8088 if (!indflag) #endif outimmed(); outnamoffset(adr); } #ifndef MC6809 else if (adr->offset.offi != 0) #endif outoffset(adr->offset.offi); #ifdef I8088 if (indflag) outindleft(); outregname(adr->storage); # ifdef XENIX_AS if (indflag) outindright(); # endif #endif #ifdef MC6809 if (indflag && adr->offset.offi != 0 && is5bitoffset(adr->offset.offi)) bumplc(); outcregname(adr->storage); #endif break; case LOCAL: #ifdef I8088 # ifdef FRAMEPOINTER if (framep == 0) bugerror("no frame pointer"); if (indflag) { if (adr->offset.offi == framep) bumplc(); else { int off; if (switchnow != NULL && adr->flags == TEMP) outswoffset(off = adr->offset.offi); else outoffset(off = adr->offset.offi - framep); #ifndef NO_DEL_PUSH if (optimise && !callersaves && off < 0) { outstr("+"); outstr(funcname); outstr(".off"); } #endif } outindleft(); } else if (adr->offset.offi != framep) badaddress(); outregname(LOCAL); # else if (indflag) { bumplc(); if (adr->offset.offi != sp) outoffset(adr->offset.offi - sp); outindleft(); } else if (adr->offset.offi != sp) badaddress(); outregname(LOCAL); # endif /* FRAMEPOINTER */ # ifdef XENIX_AS if (indflag) outindright(); # endif #endif /* I8088 */ #ifdef MC6809 if (adr->flags == TEMP && adr->offset.offi == sp && adr->indcount == 1) { outcregname(LOCAL); outplus(); ++sp; if (adr->type->typesize != 1) { outplus(); ++sp; } break; } outoffset(adr->offset.offi - sp); if (indflag && adr->offset.offi != sp && is5bitoffset(adr->offset.offi - sp)) bumplc(); outcregname(LOCAL); #endif /* MC6809 */ break; case GLOBAL: #ifdef I8088 bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif if (!indflag) outimmed(); else { # ifndef XENIX_AS outindleft(); # endif bumplc(); } #endif #ifdef MC6809 if (!posindependent) { if (adr->indcount == 0) { outimmed(); bumplc(); } else if (indflag) { outextended(); bumplc2(); } else if (adr->flags & DIRECTPAGE) outdirectpage(); else { outextended(); bumplc(); } } #endif if (adr->flags & LABELLED) outlabel(adr->name.label); else if (*adr->name.namep == 0) /* constant address */ { outhex((uoffset_T) adr->offset.offi); break; } else outccname(adr->name.namep); if (adr->offset.offi != 0) { if (adr->offset.offi > 0) outplus(); outshex(adr->offset.offi); } #ifdef MC6809 if (posindependent) { outcregname(GLOBAL); bumplc2(); } #endif break; default: outnl(); badaddress(); break; } #ifdef I8088 if (indflag) { --adr->indcount; # ifndef XENIX_AS outindright(); # endif } #endif #ifdef MC6809 if (indflag) { outindright(); adr->indcount -= MAXINDIRECT; } else if (adr->indcount != 0) --adr->indcount; #endif } /* print register name, then newline */ PUBLIC void outnregname(reg) store_pt reg; { outregname(reg); outnl(); } /* print register name */ PUBLIC void outregname(reg) store_pt reg; { switch ((store_t) reg) { case BREG: outstr(acclostr); break; case DREG: outstr(accumstr); break; #ifdef MC6809 case GLOBAL: outstr("PC"); break; #endif case INDREG0: outstr(ireg0str); regfuse |= INDREG0; break; case INDREG1: outstr(ireg1str); regfuse |= INDREG1; break; case INDREG2: outstr(ireg2str); regfuse |= INDREG2; break; case LOCAL: outstr(localregstr); regfuse |= LOCAL; break; #ifdef STACKREG case STACKREG: outstr(stackregstr); break; #endif #ifdef DATREG1 case DATREG1: outstr(dreg1str); break; #endif #ifdef DATREG1B case DATREG1B: outstr(dreg1bstr); break; #endif #ifdef DATREG2 case DATREG2: outstr(dreg2str); break; #endif default: { int i; if (reg) for(i=1; i; i<<=1) { if( reg&i ) { outregname(i); outstr(" "); } } else outstr(badregstr); } break; } } #if defined(I8088) && defined(I80386) /* print register name for short type */ PUBLIC void outshortregname(reg) store_pt reg; { switch ((store_t) reg) { case DREG: outstr(accumstr + 1); break; case INDREG0: outstr(ireg0str + 1); break; case INDREG1: outstr(ireg1str + 1); break; case INDREG2: outstr(ireg2str + 1); break; case DATREG1: outstr(dreg1str + 1); break; case DATREG2: outstr(dreg2str + 1); break; default: outstr(badregstr); break; } } #endif /*----------------------------------------------------------------------------- pointat(target leaf) point OPREG at target target must be singly indirect or float or double -----------------------------------------------------------------------------*/ PUBLIC void pointat(target) struct symstruct *target; { if (target->type->scalar & RSCALAR) (void) f_indirect(target); address(target); load(target, OPREG); target->type = target->type->nexttype; } PUBLIC void poplist(reglist) store_pt reglist; { if (reglist) sp += pushpull(reglist, FALSE); } PUBLIC void push(source) struct symstruct *source; { store_t reg; #ifdef I8088 uoffset_T size; #endif scalar_t sscalar; if (source->type->constructor & STRUCTU) { if (source->flags != TEMP) /* TEMP must be from last function */ blockpush(source); } else if ((sscalar = source->type->scalar) & RSCALAR) { if (!f_indirect(source)) { saveopreg(); fpush(source); restoreopreg(); } } #ifdef I8088 else if ((source->indcount == 1 && (sscalar & (SHORT | INT | LONG | FLOAT) || source->type->constructor & POINTER)) #ifdef I80386 || (source->storage == CONSTANT && i386_32) #endif ) { size = source->type->typesize; if (size == 1) size = 2; if (sscalar & DLONG) { source->offset.offi += itypesize; outpshs(); bumplc(); outtab(); outadr(source); source->indcount = 1; source->offset.offi -= itypesize; } outpshs(); bumplc(); outtab(); #ifdef I80386 if (i386_32) { if (source->storage == CONSTANT) { unbumplc(); adjlc((offset_T) source->offset.offv, INDREG0); } if (size == 2) { outword(); bumplc(); } else outdword(); } #endif outadr(source); sp -= size; } #endif else { reg = source->storage; loadany(source); if (sscalar & DLONG) pushlist(DREG | source->storage); else if (sscalar & CHAR) pushchar(); else pushreg(source->storage); if (source->flags != REGVAR) reguse &= ~(reg | source->storage); } onstack(source); } PUBLIC void pushlist(reglist) store_pt reglist; { if ((store_t) reglist) sp -= pushpull(reglist, TRUE); } PRIVATE fastin_pt pushpull(reglist, pushflag) store_pt reglist; bool_pt pushflag; { store_pt lastregbit; void (*ppfunc) P((void)); char *regptr; #ifdef MC6809 int separator; /* promoted char for output */ #endif fastin_t bytespushed; store_pt regbit; if ((bool_t) pushflag) { ppfunc = outpshs; #ifdef I8088 regbit = 1 << 10; #else regbit = 1 << 7; #endif regptr = regpushlist; lastregbit = 1; } else { ppfunc = outpuls; regbit = 1; regptr = regpulllist; #ifdef I8088 lastregbit = 1 << 10; #else lastregbit = 1 << 7; #endif } #ifdef MC6809 /* temp use pull strings to keep old order */ regbit = 1; regptr = regpulllist; lastregbit = 1 << 7; #endif #ifdef MC6809 separator = OPSEPARATOR; (*ppfunc) (); #endif bytespushed = 0; while (TRUE) { if (regbit & reglist) { #ifdef I8088 (*ppfunc)(); if (*regptr != FLAGSREGCHAR) outtab(); #endif #ifdef MC6809 outbyte(separator); #endif do outbyte(*regptr++); while (*regptr >= MINREGCHAR); bytespushed += *regptr++ - '0'; #ifdef I8088 outnl(); #endif #ifdef MC6809 separator = OPERANDSEPARATOR; #endif } else do ; while (*regptr++ >= MINREGCHAR); if (regbit == lastregbit) break; #ifdef MC6809 /* temp use pull strings to keep old order */ regbit <<= 1; #else /* this should normally be unconditional */ if ((bool_t) pushflag) regbit >>= 1; else regbit <<= 1; #endif } #ifdef MC6809 outnl(); #endif return bytespushed; } PUBLIC void pushreg(reg) store_pt reg; { outpshs(); outtab(); outnregname(reg); sp -= pshregsize; } PUBLIC void storereg(sourcereg, target) store_pt sourcereg; struct symstruct *target; { store_pt targreg; if (target->indcount == 0) { if (target->offset.offi != 0 || target->level == OFFKLUDGELEVEL || !(target->storage & allregs) || target->storage & CHARREGS) bugerror("bad register store"); else if ((store_t) (targreg = target->storage) != (store_t) sourcereg) { target->storage = sourcereg; loadadr(target, targreg); /* do LEA or TFR */ } } else { #ifdef I8088 /* Added acess to CPU registers. Just declare _AX etc. as * extern int, and you can use them to get/set * the register values. (vak) */ if (target->storage == GLOBAL && !(target->flags & LABELLED) && *target->name.namep != 0 && strncmp(target->name.namep, "__", 2) == 0) { if (strcmp (target->name.namep, "__AX") == 0) { return; } if (strcmp (target->name.namep, "__BX") == 0) { outstr ("mov\tbx,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__CX") == 0) { outstr ("mov\tcx,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__DX") == 0) { outstr ("mov\tdx,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__SP") == 0) { outstr ("mov\tsp,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__BP") == 0) { outstr ("mov\tbp,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__SI") == 0) { outstr ("mov\tsi,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__DI") == 0) { outstr ("mov\tdi,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__CS") == 0) { outstr ("mov\tcs,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__DS") == 0) { outstr ("mov\tds,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__ES") == 0) { outstr ("mov\tes,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__SS") == 0) { outstr ("mov\tss,"); outregname(sourcereg); outnl(); return; } if (strcmp (target->name.namep, "__FLAGS") == 0) { outstr ("push\tax"); outregname(sourcereg); outstr ("\npopf\n"); return; } } #endif outstore(); #ifdef I8088 if (target->storage == GLOBAL && (store_t) sourcereg & (AXREG | ALREG)) unbumplc(); outnnadr(target); outcomma(); #ifdef I80386 if (i386_32 && target->type->scalar & SHORT) { outshortregname(sourcereg); bumplc(); outnl(); } else #endif outnregname(sourcereg); #endif #ifdef MC6809 if ((store_t) sourcereg == YREG) bumplc(); outregname(sourcereg); outadr(target); #endif } } /*----------------------------------------------------------------------------- struc(element leaf, structure leaf) evaluates the expression structure.element -----------------------------------------------------------------------------*/ PUBLIC void struc(source, target) struct symstruct *source; struct symstruct *target; { address(target); if (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL) { if (target->indcount != 0 || target->level == OFFKLUDGELEVEL) load(target, getindexreg()); target->offset.offi += source->offset.offi; } if (source->indcount == 0) target->type = source->type; else { target->type = pointype(source->type); /* lost by = */ indirec(target); } } PUBLIC void transfer(source, targreg) struct symstruct *source; store_pt targreg; { regtransfer(source->storage, targreg); source->storage = targreg; } dev86-0.16.17/bcc/table.c0000644000000000000000000004252710065300545014552 0ustar rootroot00000000000000/* table.c - table handler for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must * usually be set to some level different from OFFKLUDGELEVEL. */ #include "bcc.h" #include "align.h" #include "gencode.h" #include "os.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" #undef EXTERN #define EXTERN #include "table.h" #define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */ #define HASHTABSIZE 256 #define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */ #ifdef VERY_SMALL_MEMORY #define MAXEXPR 125 #else #define MAXEXPR 500 #endif #define MAXLOCAL 100 #define NKEYWORDS 39 #ifdef NOFLOAT #define NSCALTYPES 10 #else #define NSCALTYPES 12 #endif #define STACKSPACE 256 /* punt for normal recursions - switch extra */ struct keywordstruct { char *kwname; sym_t kwcode; }; #ifdef HOLDSTRINGS struct string { struct string *snext; char *sptr; char *stop; label_no slabel; }; #endif struct typedatastruct { char *tdname; bool_t tdkeyscalar; scalar_t tdscalar; smalin_t tdsize; struct typestruct **tdtypeptr; }; PRIVATE struct symstruct exprsyms[MAXEXPR]; PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* depends on zero init */ #ifdef HOLDSTRINGS PRIVATE struct string *laststring; /* last in list of strings */ /* depends on NULL init */ #endif PUBLIC struct symstruct locsyms[MAXLOCAL]; PRIVATE struct symstruct constemplate = { CONSTANT, /* storage */ 0, /* indcount */ 0, /* flags */ EXPRLEVEL, /* level */ NULL, /* next */ NULL, /* prev */ NULL, /* type, init later to itype */ /* offset is a union, set every time constemplate is used */ /* name is a union, namea member is constant "\0" */ }; PRIVATE struct keywordstruct keywords[NKEYWORDS] = { { "enum", ENUMDECL, }, { "struct", STRUCTDECL, }, { "union", UNIONDECL, }, { "unsigned", UNSIGNDECL, }, { "signed", SIGNDECL, }, { "auto", AUTODECL, }, { "extern", EXTERNDECL, }, { "register", REGDECL, }, { "static", STATICDECL, }, { "typedef", TYPEDEFDECL, }, { "asm", ASMSYM, }, { "break", BREAKSYM, }, { "case", CASESYM, }, { "continue", CONTSYM, }, { "default", DEFAULTSYM, }, { "do", DOSYM, }, { "else", ELSESYM, }, { "for", FORSYM, }, { "goto", GOTOSYM, }, { "if", IFSYM, }, { "return", RETURNSYM, }, { "sizeof", SIZEOFSYM, }, { "switch", SWITCHSYM, }, { "while", WHILESYM, }, { "#asm", ASMCNTL, }, { "#define", DEFINECNTL, }, { "#elif", ELIFCNTL, }, { "#else", ELSECNTL, }, { "#endasm", ENDASMCNTL, }, { "#endif", ENDIFCNTL, }, { "#if", IFCNTL, }, { "#ifdef", IFDEFCNTL, }, { "#include", INCLUDECNTL, }, { "#ifndef", IFNDEFCNTL, }, { "#line", LINECNTL, }, { "#undef", UNDEFCNTL, }, { "#warning", WARNINGCNTL, }, { "#error", ERRORCNTL, }, { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */ }; PRIVATE struct typedatastruct scaltypes[NSCALTYPES] = { { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */ { "char", TRUE, CHAR, 1, &ctype, }, { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, }, { "char", FALSE, CHAR, 1, &sctype, }, { "short", TRUE, SHORT, 2, &stype, }, { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, }, { "int", TRUE, INT, 2, &itype, }, { "int", FALSE, UNSIGNED | INT, 2, &uitype, }, { "long", TRUE, LONG | DLONG, 4, <ype, }, { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, }, #ifndef NOFLOAT { "float", TRUE, FLOAT, 4, &fltype, }, { "double", TRUE, DOUBLE, 8, &dtype, }, #endif }; FORWARD struct symstruct *addkeyword P((char *name, sym_pt code)); FORWARD void heapcorrupterror P((void)); PUBLIC struct symstruct *addglb(name, type) char *name; struct typestruct *type; { struct symstruct **hashptr; struct symstruct *oldsymptr = NULL; /* for -Wall */ register struct symstruct *symptr; hashptr = gethashptr(name); symptr = *hashptr; while (symptr != NULL) { oldsymptr = symptr; symptr = symptr->next; } symptr = qmalloc(sizeof (struct symstruct) + strlen(name)); #ifdef TS ++ts_n_global; ts_size_global += sizeof (struct symstruct) + strlen(name); #endif addsym(name, type, symptr); symptr->storage = GLOBAL; symptr->level = GLBLEVEL; if (*hashptr == NULL) { *hashptr = symptr; symptr->prev = hashptr; } else { oldsymptr->next = symptr; symptr->prev = &oldsymptr->next; } return symptr; } PRIVATE struct symstruct *addkeyword(name, code) char *name; sym_pt code; { struct symstruct *symptr; (symptr = addglb(name, vtype))->flags = KEYWORD; symptr->offset.offsym = code; return symptr; } PUBLIC struct symstruct *addloc(name, type) char *name; struct typestruct *type; { struct symstruct **hashptr; register struct symstruct *symptr; hashptr = gethashptr(name); symptr = *hashptr; while (symptr != NULL) symptr = symptr->next; symptr = locptr; locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]); if (locptr >= &locsyms[MAXLOCAL]) limiterror("too many local symbols (101)"); addsym(name, type, symptr); if (type->constructor == FUNCTION) symptr->storage = GLOBAL; else symptr->storage = LOCAL; symptr->level = level; if (*hashptr != NULL) { symptr->next = *hashptr; symptr->next->prev = &symptr->next; } *hashptr = symptr; symptr->prev = hashptr; return symptr; } PUBLIC struct symstruct *addlorg(name, type) char *name; struct typestruct *type; { if (level != GLBLEVEL) return addloc(name, type); return addglb(name, type); } PUBLIC void addsym(name, type, symptr) char *name; struct typestruct *type; register struct symstruct *symptr; { if (type->constructor & (ARRAY | FUNCTION)) symptr->indcount = 0; else symptr->indcount = 1; symptr->flags = 0; symptr->next = NULL; symptr->type = type; symptr->offset.offi = 0; strcpy(symptr->name.namea, name); } PUBLIC struct symstruct *constsym(longconst) value_t longconst; { register struct symstruct *symptr; symptr = exprsym(&constemplate); symptr->offset.offv = longconst; return symptr; } PUBLIC void delsym(symptr) register struct symstruct *symptr; { if ((*(symptr->prev) = symptr->next) != NULL) symptr->next->prev = symptr->prev; } /* dumpglbs() - define locations of globals and reserve space for them */ PUBLIC void dumpglbs() { int i; register struct symstruct *symptr; register struct typestruct *type; #ifdef TS extern char *brksize; struct ts { char *what; uvalue_t *where; }; static struct ts ts[] = { "ts_n_newtypelist ", &ts_n_newtypelist, "ts_s_newtypelist ", &ts_s_newtypelist, "ts_n_filename_term ", &ts_n_filename_term, "ts_s_filename_term ", &ts_s_filename_term, "ts_n_filename ", &ts_n_filename, "ts_s_filename ", &ts_s_filename, "ts_s_filename_tot ", &ts_s_filename_tot, "ts_n_pathname ", &ts_n_pathname, "ts_s_pathname ", &ts_s_pathname, "ts_s_pathname_tot ", &ts_s_pathname_tot, "ts_n_inputbuf ", &ts_n_inputbuf, "ts_s_inputbuf ", &ts_s_inputbuf, "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot, "ts_n_includelist ", &ts_n_includelist, "ts_s_includelist ", &ts_s_includelist, "ts_s_outputbuf ", &ts_s_outputbuf, "ts_n_macstring_ident ", &ts_n_macstring_ident, "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary, "ts_n_macstring_param ", &ts_n_macstring_param, "ts_n_macstring_quoted ", &ts_n_macstring_quoted, "ts_n_macstring_term ", &ts_n_macstring_term, "ts_s_macstring ", &ts_s_macstring, "ts_n_defines ", &ts_n_defines, "ts_s_defines ", &ts_s_defines, "ts_n_macparam ", &ts_n_macparam, "ts_s_macparam ", &ts_s_macparam, "ts_s_macparam_tot ", &ts_s_macparam_tot, "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary, "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted, "ts_n_macparam_string_term ", &ts_n_macparam_string_term, "ts_s_macparam_string ", &ts_s_macparam_string, "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot, "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced, "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot, "ts_s_fakeline ", &ts_s_fakeline, "ts_s_fakeline_tot ", &ts_s_fakeline_tot, "ts_n_string ", &ts_n_string, "ts_n_case ", &ts_n_case, "ts_n_case_realloc ", &ts_n_case_realloc, "ts_s_case ", &ts_s_case, "ts_s_case_tot ", &ts_s_case_tot, "ts_n_structname ", &ts_n_structname, "ts_s_structname ", &ts_s_structname, "ts_n_type ", &ts_n_type, "ts_s_type ", &ts_s_type, "ts_n_global ", &ts_n_global, "ts_size_global ", &ts_size_global, "ts_n_holdstr ", &ts_n_holdstr, "ts_size_holdstr ", &ts_size_holdstr, "ts_n_growobj ", &ts_n_growobj, "ts_size_growobj_wasted ", &ts_size_growobj_wasted, "ts_n_growheap ", &ts_n_growheap, "ts_s_growheap ", &ts_s_growheap, }; struct ts *tp; for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp) { comment(); outstr(tp->what); outstr(""); outuvalue(*tp->where); outnl(); } comment(); outstr("brksize "); outhex((uvalue_t) brksize); outnl(); #endif #ifndef DIRECTPAGE bssseg(); #endif for (i = 0; i < HASHTABSIZE; ++i) for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next) if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL) && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG /* Don't access type unless flags <= MAXDUMPFLAG, because * type is punned to a symbol pointer for the label chain * and might be null. */ && symptr->type->constructor != FUNCTION) { #ifdef DIRECTPAGE if (symptr->flags & DIRECTPAGE) dpseg(); else dseg(); #endif type = symptr->type; if (symptr->flags & STATIC) lcommon(symptr->name.namea); else common(symptr->name.namea); outnhex(type->typesize); } if (printf_fp) globl("__xfpcvt"); if (scanf_fp) globl("__xfptvc"); } /* dumplocs() - define offsets of current locals */ PUBLIC void dumplocs() { register struct symstruct *symptr; int i; #ifdef ASM_USES_CALLEE_REGS if (framep && optimise && !callersaves) { regfuse |= callee1mask; outnstr("! Assuming #asm uses all callee saves registers"); } #endif for (i = 0; i < HASHTABSIZE; ++i) for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next) if (symptr->storage == LOCAL) set(symptr->name.namea, symptr->offset.offi - sp); } #ifdef HOLDSTRINGS /* dumpstrings() - dump held-up strings */ PUBLIC void dumpstrings() { struct string *stringp; dseg(); for (stringp = laststring; stringp != NULL; stringp = stringp->snext) { outnlabel(stringp->slabel); defstr(stringp->sptr, stringp->stop, TRUE); dataoffset += stringp->stop - stringp->sptr + 1; } } #endif PUBLIC struct symstruct *exprsym(symptr) struct symstruct *symptr; { register struct symstruct *newsymptr; newsymptr = exprptr++; if (exprptr >= &exprsyms[MAXEXPR]) #if MAXEXPR == 500 limiterror("expression too complex (501 symbols)"); #else limiterror("expression too complex (MAXEXPR)"); #endif *newsymptr = *symptr; newsymptr->level = EXPRLEVEL; newsymptr->name.namep = symptr->name.namea; return newsymptr; } PUBLIC struct symstruct *findlorg(name) char *name; { struct symstruct *symptr; symptr = *gethashptr(name); while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 || symptr->flags == STRUCTNAME)) symptr = symptr->next; return symptr; } PUBLIC struct symstruct *findstruct(name) char *name; { struct symstruct *symptr; symptr = *gethashptr(name); while (symptr != NULL && (symptr->flags != STRUCTNAME || strcmp(symptr->name.namea, name) != 0)) symptr = symptr->next; return symptr; } /* convert name to a hash table ptr */ PUBLIC struct symstruct **gethashptr(sname) char *sname; { register int hashval; register char *rsname; hashval = 0; rsname = sname; #if 1 while (*rsname) hashval = hashval * 2 + *rsname++; #else hashval = rsname[0]; if (rsname[1] != 0) hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1); else hashval = rsname[0]; #endif return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1)); } PRIVATE void heapcorrupterror() { outofmemoryerror(" (heap corrupt - stack overflow?)"); } #ifdef HOLDSTRINGS /* hold string for dumping at end, to avoid mixing it with other data */ PUBLIC label_no holdstr(sptr, stop) char *sptr; char *stop; { register struct string *stringp; stringp = qmalloc(sizeof *stringp); #ifdef TS ++ts_n_holdstr; ts_size_holdstr += sizeof *stringp; #endif stringp->snext = laststring; stringp->sptr = sptr; stringp->stop = stop; laststring = stringp; return stringp->slabel = getlabel(); } #endif /* HOLDSTRINGS */ PUBLIC void newlevel() { if (*(unsigned *) chartop != MARKER) heapcorrupterror(); if (level >= MAXLEVEL) limiterror("compound statements nested too deeply (126 levels)"); else ++level; } PUBLIC void oldlevel() { register struct symstruct *symptr; if (*(unsigned *) chartop != MARKER) heapcorrupterror(); if (level == 0) bugerror("not in a compound statement"); else --level; for (symptr = &locsyms[0]; symptr < locptr; symptr = (struct symstruct *) align(&symptr->name.namea[strlen(symptr->name.namea) + 1])) if (symptr->level > level) delsym(symptr); } PUBLIC void ourfree(ptr) void *ptr; { free(ptr); } PUBLIC void *ourmalloc(nbytes) unsigned nbytes; { void *ptr; if ((ptr = malloc(nbytes)) == NULL) outofmemoryerror(""); return ptr; } PUBLIC void outofmemoryerror(message) char *message; { error2error("compiler out of memory", message); #ifdef __AS386_16__ { unsigned size; char *ptr; for (size = 0x1000; size != 0; --size) if ((ptr = malloc(size)) != NULL) { outstr("found free memory at "); outuvalue((uvalue_t) ptr); outstr(" size "); outuvalue((uvalue_t) size); outnl(); } } #endif finishup(); } PUBLIC void *growobject(object, extra) void *object; unsigned extra; { /* size_t */ unsigned oblength; /* It would be nice to realloc the previous memory if it can be left in * the same place. Since a realloc that moves the memory can almost be * relied on to mess up pointers before *obptr, and since malloc(extra) * would be unlikely to produce memory adjoining chartop, it is not * clear how to do this. */ #ifdef TS ts_size_growobj_wasted += chartop - (char *) object; #endif oblength = (/* size_t */ unsigned) (charptr - (char *) object); growheap(oblength + extra); #ifdef TS ++ts_n_growobj; #endif memcpy(charptr, object, oblength); object = charptr; charptr += oblength; return object; } #define ALLOC_UNIT ((unsigned) 0x400) #ifdef S_ALIGNMENT #define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned)) #else #define ALLOC_OVERHEAD (sizeof (unsigned)) #endif PUBLIC void growheap(size) unsigned size; { register char *newptr; if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL && (newptr = malloc(size -= ALLOC_UNIT)) == NULL) outofmemoryerror(""); #ifdef TS ++ts_n_growheap; ts_s_growheap += size; #endif charptr = newptr; newptr = (char *) align(newptr + size - ALLOC_OVERHEAD); chartop = newptr; char1top = newptr - 1; char3top = newptr - 3; *(unsigned *) newptr = MARKER; } PUBLIC void *qmalloc(size) unsigned size; { register char *ptr; if ((charptr = (char *) align(charptr)) + size > chartop) growheap(size); ptr = charptr; charptr += size; return ptr; } PUBLIC void swapsym(sym1, sym2) struct symstruct *sym1; struct symstruct *sym2; { struct symstruct swaptemp; swaptemp = *sym1; *sym1 = *sym2; *sym2 = swaptemp; } PUBLIC void syminit() { struct keywordstruct *kwptr; struct typedatastruct *tdptr; struct typestruct *type; exprptr = exprsyms; locptr = locsyms; for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr) { (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar; type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) | alignmask; type->tname = tdptr->tdname; if (tdptr->tdkeyscalar) addkeyword(tdptr->tdname, TYPEDECL)->type = type; } for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr) addkeyword(kwptr->kwname, kwptr->kwcode); constemplate.type = itype; } dev86-0.16.17/bcc/const.h0000644000000000000000000000423610065365121014612 0ustar rootroot00000000000000/* const.h - constants for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef __STDC__ #include #else #include #endif #include "debug.h" /* switches for code generation */ #if !defined(I8088) && !defined(MC6809) /* The default compiler type ... */ #define I8088 /* target processor is Intel 8088 thru 80386 */ #undef MC6809 /* target processor is Motorola 6809 */ #endif #ifdef __AS386_16__ #define VERY_SMALL_MEMORY #endif #ifndef VERY_SMALL_MEMORY #define SELFTYPECHECK /* check calculated type = runtime type */ #define DBNODE /* generate compiler node debugging code */ #define OPTIMISE /* include optimisation code */ #endif #ifndef __BCC__ #define BUILTIN_CPP /* Remove the built in C preprocessor */ #endif #ifdef I8088 # define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */ # define HOLDSTRINGS /* hold strings for dumping at end * since assembler has only 1 data seg */ # define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */ #ifdef __HAS_NO_FLOATS__ /* Humm, now this is nasty :-) */ #define float no_hope #define double no_hope #define atof atol #define NOFLOAT typedef long no_hope; #endif #ifndef VERY_SMALL_MEMORY #ifndef NO_I80386 # define I80386 /* Little BCC doesn't need 386 */ #endif #endif #endif #ifdef MC6809 # define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */ # define OP1 /* logical operators only use 1 byte */ # define POSINDEPENDENT /* position indep code can (also) be gen */ #endif /* switches for source and target operating system dependencies */ /*#define SOS_EDOS*/ /* source O/S is EDOS */ /*#define SOS_MSDOS*/ /* source O/S is MSDOS */ /*#define TOS_EDOS*/ /* target O/S is EDOS */ #ifdef MSDOS #define SOS_MSDOS #endif /* switches for source machine dependencies */ /* Unportable alignment needed for specific compilers */ #ifndef VERY_SMALL_MEMORY # define S_ALIGNMENT (sizeof(long)) /* A little safer */ #endif /* local style */ #ifndef NULL #define NULL 0 #endif #define FALSE 0 #define TRUE 1 #define EXTERN extern #define FORWARD static #define PRIVATE static #define PUBLIC /* #define C_CODE * Don't use assembler outstr() function. */ dev86-0.16.17/bcc/state.c0000644000000000000000000004324607522770205014612 0ustar rootroot00000000000000/* state.c - statement routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "align.h" #include "condcode.h" #include "gencode.h" #include "input.h" /* just for ch and eof for label check */ #include "label.h" #include "os.h" /* just for EOL */ #include "parse.h" #include "reg.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" #define COLONCHAR ':' /* for label */ #define GROWCASES 64 /* extra cases for growth of switch struct */ #define INITIALCASES 16 /* initial cases in switch structure */ struct loopstruct { label_no breaklab; /* destination for break */ label_no contlab; /* destination for continue */ struct nodestruct *etmark; /* expression tree built during loop */ struct symstruct *exprmark; /* expression symbols built during loop */ struct symstruct *locmark; /* local variables built during loop */ struct loopstruct *prevloop; /* previous active for, switch or while */ offset_T spmark; /* stack value for continue and break */ }; struct switchstruct { struct casestruct *caseptr; /* current spot in caselist */ struct casestruct *casetop; /* last in caselist + 1 */ bool_t charselector; /* tells if case selector is char */ label_no dfaultlab; /* destination for default case (0 if none) */ struct switchstruct *prevswitch; /* previous active switch */ struct casestruct { value_t casevalue; /* value giving this case */ label_no caselabel; /* corresponding label */ } caselist[INITIALCASES]; /* perhaps larger */ }; PRIVATE struct loopstruct *loopnow; /* currently active for/switch/while */ /* depends on NULL init */ PRIVATE bool_t returnflag; /* set if last effective statement */ /* was a return */ PRIVATE label_no swstacklab; /* label giving stack for switch statement */ FORWARD void addloop P((struct loopstruct *newloop)); FORWARD void badloop P((void)); FORWARD void deleteloop P((void)); FORWARD void evalexpression P((struct nodestruct *exp)); FORWARD void exprstatement P((void)); FORWARD bool_pt isforever P((struct nodestruct *exp)); FORWARD void sort P((struct casestruct *caselist, int count)); FORWARD void dobreak P((void)); FORWARD void docase P((void)); FORWARD void docont P((void)); FORWARD void dodefault P((void)); FORWARD void dodowhile P((void)); FORWARD void dofor P((void)); FORWARD void dogoto P((void)); FORWARD void doif P((void)); FORWARD void doreturn P((void)); FORWARD void doswitch P((void)); FORWARD void dowhile P((void)); FORWARD void jumptocases P((void)); FORWARD void statement P((void)); /* --- utility routines --- */ PRIVATE void addloop(newloop) struct loopstruct *newloop; { newloop->breaklab = getlabel(); newloop->contlab = getlabel(); newloop->etmark = etptr; newloop->exprmark = exprptr; newloop->locmark = locptr; newloop->prevloop = loopnow; newloop->spmark = sp; loopnow = newloop; } PRIVATE void badloop() { error(" no active fors, switches or whiles"); } PRIVATE void deleteloop() { etptr = loopnow->etmark; exprptr = loopnow->exprmark; locptr = loopnow->locmark; loopnow = loopnow->prevloop; } PRIVATE void evalexpression(exp) struct nodestruct *exp; { offset_T spmark; spmark = sp; makeleaf(exp); modstk(spmark); } PRIVATE void exprstatement() { struct nodestruct *etmark; struct symstruct *exprmark; etmark = etptr; exprmark = exprptr; evalexpression(expression()); etptr = etmark; exprptr = exprmark; } PRIVATE bool_pt isforever(exp) register struct nodestruct *exp; { return exp == NULL || (exp->tag == LEAF && exp->left.symptr->storage == CONSTANT && exp->left.symptr->offset.offv != 0); } PRIVATE void sort(caselist, count) /* shell sort */ struct casestruct *caselist; int count; { register int gap; register int i; int j; struct casestruct swaptemp; gap = 1; do gap = 3 * gap + 1; while (gap <= count); while (gap != 1) { gap /= 3; for (j = gap; j < count; ++j) for (i = j - gap; i >= 0 && caselist[i].casevalue > caselist[i + gap].casevalue; i -= gap) { swaptemp = caselist[i]; caselist[i] = caselist[i + gap]; caselist[i + gap] = swaptemp; } } } /* --- syntax routines --- */ /* ---------------------------------------------------------------------------- compound-statement: "{" "}" ---------------------------------------------------------------------------- */ PUBLIC void compound() /* have just seen "{" */ { struct symstruct *locmark; store_t regmark; #ifdef FRAMEPOINTER offset_T framepmark; offset_T softspmark; #else /* softsp == sp here unless level == ARGLEVEL so mark is unnec */ /* this is also true if funcsaveregsize != 0 but the tests are too messy */ #endif offset_T spmark; locmark = locptr; regmark = reguse; #ifdef FRAMEPOINTER softspmark = softsp; framepmark = framep; #endif spmark = sp; newlevel(); expect_statement++; decllist(); softsp &= alignmask; if (sym != RBRACE) /* no need for locals if empty compound */ reslocals(); returnflag = FALSE; while (sym != RBRACE && sym != EOFSYM) statement(); expect_statement--; oldlevel(); if (!returnflag) { if (level != ARGLEVEL) { if (switchnow == NULL) { #ifdef FRAMEPOINTER if (framep != 0) { /* some args or locals, maybe at lower levels */ modstk(softspmark); if (framep != framepmark) /* frame was just set up */ popframe(); } #else modstk(spmark); #endif } } else ret(); } #ifdef FRAMEPOINTER framep = framepmark; sp = spmark; softsp = softspmark; #else softsp = sp = spmark; #endif reguse = regmark; locptr = locmark; rbrace(); } PUBLIC void doasm() { if (sym == LPAREN) nextsym(); if (sym!=STRINGCONST) error("string const expected"); else { outnstr("!BCC_ASM"); for(;;) { constant.value.s[charptr-constant.value.s]='\0'; outbyte('\t'); outnstr(constant.value.s); /* XXX: Need to investigate: wasting memory? * * charptr = constant.value.s; */ nextsym(); if (sym == COMMA) nextsym(); if (sym!=STRINGCONST) break; } outnstr("!BCC_ENDASM"); if (sym == RPAREN) nextsym(); semicolon(); } } PRIVATE void dobreak() { offset_T spmark; if (loopnow == NULL) badloop(); else { if (switchnow == NULL) { spmark = sp; modstk(loopnow->spmark); sp = spmark; } jump(loopnow->breaklab); } } PRIVATE void docase() { value_t caseval; caseval = constexpression() & intmaskto; /* FIXME: warn overflow */ if (caseval > maxintto) caseval -= (maxuintto + 1); colon(); if (switchnow == NULL) error("case not in switch"); else { if (switchnow->charselector && (caseval < 0 || caseval > 255)) error("%wcase cannot be reached with char switch"); else { if (switchnow->caseptr >= switchnow->casetop) { int ncases; ncases = (/* ptrdiff_t */ int) (switchnow->caseptr - &switchnow->caselist[0]); switchnow = realloc(switchnow, (/* size_t */ unsigned) ((char *) switchnow->caseptr - (char *) switchnow) + GROWCASES * sizeof (struct casestruct)); #ifdef TS ++ts_n_case_realloc; ts_s_case += GROWCASES * sizeof (struct casestruct); ts_s_case_tot += GROWCASES * sizeof (struct casestruct); #endif if (switchnow == NULL) outofmemoryerror(""); switchnow->caseptr = &switchnow->caselist[ncases]; switchnow->casetop = switchnow->caseptr + GROWCASES; } switchnow->caseptr->casevalue = caseval; deflabel(switchnow->caseptr->caselabel = getlabel()); ++switchnow->caseptr; } } } PRIVATE void docont() { struct loopstruct *contloop; offset_T spmark; struct switchstruct *switchthen; for (contloop = loopnow, switchthen = switchnow; ; contloop = contloop->prevloop, switchthen = switchthen->prevswitch) { if (contloop == NULL) { badloop(); return; } if (contloop->contlab != 0) break; } if (switchnow == NULL) { spmark = sp; modstk(contloop->spmark); sp = spmark; } else if (switchthen == NULL) { outaddsp(); outshex(contloop->spmark); outminus(); outswstacklab(); #ifdef MC6809 outcregname(LOCAL); #endif #ifdef I80386 if (i386_32) bumplc2(); #endif outnl(); } jump(contloop->contlab); } PRIVATE void dodefault() { colon(); if (switchnow == NULL) error("default not in switch"); else if (switchnow->dfaultlab != 0) error("multiple defaults"); else deflabel(switchnow->dfaultlab = getlabel()); } PRIVATE void dodowhile() { struct loopstruct dwhileloop; label_no dolab; addloop(&dwhileloop); deflabel(dolab = getlabel()); statement(); if (sym == WHILESYM) nextsym(); else error("missing while at end of do-while"); deflabel(dwhileloop.contlab); lparen(); jumptrue(expression(), dolab); rparen(); semicolon(); deflabel(dwhileloop.breaklab); deleteloop(); } PRIVATE void dofor() { struct loopstruct forloop; label_no forstatlab; label_no fortestlab = 0; /* for -Wall */ struct nodestruct *testexp; struct nodestruct *loopexp; lparen(); if (sym != SEMICOLON) exprstatement(); semicolon(); addloop(&forloop); if (sym == SEMICOLON) testexp = NULL; else testexp = expression(); /* remember test expression */ semicolon(); if (sym == RPAREN) loopexp = NULL; else loopexp = expression(); /* remember loop expression */ rparen(); if (!isforever(testexp)) jump(fortestlab = getlabel()); /* test at bottom */ deflabel(forstatlab = getlabel()); /* back here if test succeeds */ statement(); deflabel(forloop.contlab); if (loopexp != NULL) evalexpression(loopexp); if (isforever(testexp)) jump(forstatlab); else { deflabel(fortestlab); /* test label */ jumptrue(testexp, forstatlab); } deflabel(forloop.breaklab); deleteloop(); } PRIVATE void dogoto() { struct symstruct *symptr; if (sym == IDENT || sym == TYPEDEFNAME) { symptr = namedlabel(); /* if (symptr->indcount == 4) modstk( else */ adjsp(symptr->offset.offlabel); jump(symptr->offset.offlabel); nextsym(); } else error("need identifier"); } PRIVATE void doif() { struct nodestruct *etmark; label_no elselab; label_no exitlab; struct symstruct *exprmark; lparen(); etmark = etptr; exprmark = exprptr; jumpfalse(expression(), elselab = getlabel()); etptr = etmark; exprptr = exprmark; rparen(); statement(); /* true, do a statement */ if (sym == ELSESYM) /* "if .. else" statement */ { nextsym(); jump(exitlab = getlabel()); /* over "else" label and code */ deflabel(elselab); statement(); deflabel(exitlab); } else deflabel(elselab); } PRIVATE void doreturn() { offset_T spmark; spmark = sp; if (sym != SEMICOLON) /* returning expression */ loadretexpression(); ret(); /* clean up stack and return */ sp = spmark; /* restore stack for rest of function */ } PRIVATE void doswitch() { struct switchstruct *sw; struct loopstruct switchloop; offset_T spmark = 0; /* for -Wall */ label_no sdecidelab; sw = (struct switchstruct *) ourmalloc(sizeof *sw); #ifdef TS ++ts_n_case; ts_s_case += sizeof *sw; ts_s_case_tot += sizeof *sw; #endif lparen(); sw->charselector = loadexpression(DREG, NULLTYPE)->scalar & CHAR; rparen(); if (switchnow == NULL) spmark = lowsp = sp; addloop(&switchloop); sw->dfaultlab = switchloop.contlab = 0; /* kill to show this is a switch */ sw->casetop = (sw->caseptr = sw->caselist) + INITIALCASES; sw->prevswitch = switchnow; jump(sdecidelab = getlabel()); /* to case decision label */ if (switchnow == NULL) swstacklab = gethighlabel(); switchnow = sw; statement(); /* cases */ sw = switchnow; jump(switchloop.breaklab); /* over case decision to break label */ deflabel(sdecidelab); if (sw->prevswitch == NULL) modstk(lowsp); jumptocases(); deflabel(switchloop.breaklab); if ((switchnow = sw->prevswitch) == NULL) { equlab(swstacklab, lowsp); clearswitchlabels(); modstk(spmark); } deleteloop(); #ifdef TS ts_s_case_tot -= (char *) sw->casetop - (char *) sw; #endif ourfree(sw); } PRIVATE void dowhile() { struct loopstruct whileloop; struct nodestruct *testexp; label_no wstatlab; lparen(); addloop(&whileloop); testexp = expression(); rparen(); if (!isforever(testexp)) jump(whileloop.contlab); /* test at bottom */ deflabel(wstatlab = getlabel()); /* back here if test succeeds */ statement(); deflabel(whileloop.contlab); jumptrue(testexp, wstatlab); deflabel(whileloop.breaklab); deleteloop(); } PRIVATE void jumptocases() { value_t basevalue; struct casestruct *case1ptr; struct casestruct *caseptr; struct casestruct *casetop; value_t caseval; bool_t charselector; bool_t dfaultflag; label_no dfaultlab; label_no jtablelab; ccode_t lowcondition; store_pt targreg; label_no zjtablelab; caseptr = switchnow->caselist; casetop = switchnow->caseptr; sort(caseptr, (/* ptrdiff_t */ int) (casetop - caseptr)); basevalue = 0; if ((charselector = switchnow->charselector) != 0) { targreg = BREG; lowcondition = LO; } else { targreg = DREG; lowcondition = LT; } dfaultflag = TRUE; if ((dfaultlab = switchnow->dfaultlab) == 0) { dfaultflag = FALSE; dfaultlab = loopnow->breaklab; } --casetop; for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr) if (case1ptr->casevalue == (case1ptr + 1)->casevalue) error("duplicate case in switch"); while (caseptr <= casetop) { outsub(); outimadj((offset_T) (caseptr->casevalue - basevalue), targreg); basevalue = caseptr->casevalue; for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr) if (case1ptr->casevalue < (case1ptr + 1)->casevalue - 10) break; if (case1ptr < caseptr + 5) { lbranch(EQ, caseptr->caselabel); ++caseptr; } else { lbranch(lowcondition, dfaultlab); outcmp(); outimadj((offset_T) (case1ptr->casevalue - basevalue), targreg); lbranch(HI, zjtablelab = getlabel()); if (charselector) ctoi(); #ifdef MC6809 else bumplc(); /* extra for CMPD */ #endif slconst((value_t) (ptypesize / 2), DREG); /* really log ptypesize */ deflabel(jtablelab = casejump()); #ifdef I8088 jtablelab = jtablelab; /* not used, allocated for regress */ #endif for (caseval = caseptr->casevalue; caseval <= case1ptr->casevalue; ++caseval) { #ifdef I8088 if (ptypesize > 2) defdword(); else #endif defword(); if (caseval != caseptr->casevalue) outlabel(dfaultlab); else { outlabel(caseptr->caselabel); ++caseptr; } #ifdef MC6809 if (posindependent) { outminus(); outlabel(jtablelab); } #endif bumplc2(); #ifdef I8088 if (ptypesize > 2) bumplc2(); #endif outnl(); } deflabel(zjtablelab); } lowcondition = LO; /* 1st subtraction makes rest unsigned */ } if (dfaultflag) jump(dfaultlab); } PUBLIC void outswoffset (offset) offset_T offset; { #ifdef FRAMEPOINTER outoffset(offset - softsp - framep); #else outoffset(offset - softsp - sp); #endif outplus(); outswstacklab(); #ifdef I8088 bumplc(); #ifdef I80386 if (i386_32) bumplc2(); #endif #endif } PUBLIC void outswstacklab() { outbyte(LOCALSTARTCHAR); outlabel(swstacklab); } /* ---------------------------------------------------------------------------- statement: ; ---------------------------------------------------------------------------- */ PRIVATE void statement() { #if 1 struct symstruct *symptr; #endif more: switch (sym) { case LBRACE: nextsym(); compound(); return; case IFSYM: nextsym(); doif(); break; case ELSESYM: error("unexpected else"); nextsym(); break; case WHILESYM: nextsym(); dowhile(); break; case FORSYM: nextsym(); dofor(); break; case RETURNSYM: nextsym(); doreturn(); semicolon(); returnflag = TRUE; return; case SWITCHSYM: nextsym(); doswitch(); break; case BREAKSYM: nextsym(); dobreak(); semicolon(); break; case CASESYM: nextsym(); docase(); goto more; case DEFAULTSYM: nextsym(); dodefault(); goto more; case DOSYM: nextsym(); dodowhile(); break; case CONTSYM: nextsym(); docont(); semicolon(); break; case GOTOSYM: nextsym(); dogoto(); semicolon(); break; case SEMICOLON: outnstr("!BCC_EOS"); nextsym(); return; case ASMSYM: nextsym(); doasm(); break; case IDENT: case TYPEDEFNAME: blanks(); /* cannot afford nextsym() */ while (ch == EOL && !eofile) { /* this now fails only on #controls and macros giving ':' */ skipeol(); blanks(); } if (ch == COLONCHAR) { #if 0 struct symstruct *symptr; #endif symptr = namedlabel(); if (symptr->indcount != 2) error("redefined label"); else { deflabel(symptr->offset.offlabel); if (switchnow != NULL) symptr->indcount = 3; else { symptr->indcount = 4; outbyte(LOCALSTARTCHAR); outlabel(symptr->offset.offlabel); outop0str("\t=\t"); outshex(sp); outnl(); } } nextsym(); nextsym(); goto more; } /* else fall into default */ default: exprstatement(); semicolon(); break; } returnflag = FALSE; } dev86-0.16.17/bcc/label.c0000644000000000000000000002136106456134233014543 0ustar rootroot00000000000000/* label.c - label handling routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "condcode.h" #include "gencode.h" #include "label.h" #include "output.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" #ifdef I8088 # define outlbranch() outop3str( "b") # define outsbranch() outop2str( "j") #endif #ifdef MC6809 # define outlbranch() outop3str( "LB") # define outsbranch() outop2str( "B") #endif #define MAXVISLAB 32 struct labdatstruct { label_no labnum; /* 0 if not active */ offset_T lablc; /* location counter for branch or label */ char *labpatch; /* buffer ptr for branch, NULL for label */ ccode_t labcond; /* condition code for branch */ }; #ifdef I8088 PRIVATE char lcondnames[][2] = /* names of long condition codes */ { { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', }, { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', }, { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' }, }; PRIVATE char scondnames[][2] = /* names of short condition codes */ { { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, }, { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', }, { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', }, }; #endif #ifdef MC6809 PRIVATE char condnames[][2] = /* names of condition codes */ { { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', }, { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', }, { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', }, }; #endif PRIVATE label_no lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */ /* lint */ PRIVATE label_no lastlab; /* bss init to 0 */ PRIVATE offset_T lc; /* bss init to 0 */ PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */ PRIVATE smalin_t nextvislab; /* bss init to NULL */ PRIVATE struct symstruct *namedfirst; /* bss init to NULL */ PRIVATE struct symstruct *namedlast; /* bss init to NULL */ FORWARD void addlabel P((ccode_pt cond, label_no label, char *patch)); FORWARD struct labdatstruct *findlabel P((label_no label)); /* add label to circular list */ PRIVATE void addlabel(cond, label, patch) ccode_pt cond; label_no label; char *patch; { register struct labdatstruct *labptr; labptr = &vislab[(int)nextvislab]; labptr->labcond = cond; labptr->labnum = label; labptr->lablc = lc; labptr->labpatch = patch; if (++nextvislab == MAXVISLAB) nextvislab = 0; } /* bump location counter */ PUBLIC void bumplc() { ++lc; } /* bump location counter by 2 */ PUBLIC void bumplc2() { lc += 2; } /* bump location counter by 3 */ PUBLIC void bumplc3() { lc += 3; } /* clear out labels in function */ PUBLIC void clearfunclabels() { register struct symstruct *symptr; register struct symstruct *tmp; for (symptr = namedfirst; symptr != NULL;) { if (symptr->indcount == 2) error("undefined label"); symptr->indcount = 0; tmp = symptr; symptr = (struct symstruct *) symptr->type; tmp->type = NULL; } namedlast = namedfirst = NULL; } /* clear out labels no longer in buffer */ PUBLIC void clearlabels(patchbuf, patchtop) char *patchbuf; char *patchtop; { register struct labdatstruct *labptr; struct labdatstruct *labtop; register char *labpatch; for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB]; labptr < labtop; ++labptr) if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop) labptr->labnum = 0; } /* clear out labels in switch statement */ PUBLIC void clearswitchlabels() { register struct symstruct *symptr; for (symptr = namedfirst; symptr != NULL; symptr = (struct symstruct *) symptr->type) if (symptr->indcount == 3) { equlab(symptr->offset.offlabel, lowsp); symptr->indcount = 4; } } /* return location counter */ PUBLIC uoffset_T getlc() { return (uoffset_T) lc; } /* define location of label and backpatch references to it */ PUBLIC void deflabel(label) label_no label; { char *cnameptr; struct labdatstruct *labmin; struct labdatstruct *labmax; struct labdatstruct *labmid; struct labdatstruct *labptrsave; offset_T nlonger; outnlabel(label); { register struct labdatstruct *labptr; register char *labpatch; labmin = &vislab[0]; labmax = &vislab[MAXVISLAB]; labptr = labmid = &vislab[(int)nextvislab]; if (!watchlc) do { if (labptr == labmin) labptr = &vislab[MAXVISLAB]; --labptr; if (labptr->labnum == label) { if ((labpatch = labptr->labpatch) != NULL && isshortbranch(lc - labptr->lablc)) { #ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */ *labpatch = 'j'; *(labpatch + 1) = *(cnameptr = scondnames[(int)labptr->labcond]); #endif #ifdef MC6809 # ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */ *labpatch = 'B'; *(labpatch + 4) = '\t'; /* redundant unless JMP */ *(labpatch + 1) = *(cnameptr = condnames[labptr->labcond]); # else if (labptr->labcond == RA) strncpy(labpatch, "BRA\t\t", 5); else *labpatch = '\t'; goto over; # endif #endif *(labpatch + 2) = *(cnameptr + 1); *(labpatch + 3) = ' '; #ifdef MC6809 # ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */ over: ; /* temp regression test kludge */ # endif #endif nlonger = jcclonger; if (labptr->labcond == RA) nlonger = jmplonger; lc -= nlonger; labptrsave = labptr; while (++labptr != labmid) if (labptr == labmax) labptr = &vislab[-1]; else labptr->lablc -= nlonger; labptr = labptrsave; } } } while (labptr != labmid); } addlabel((ccode_pt) 0, label, (char *) NULL); } PRIVATE struct labdatstruct *findlabel(label) label_no label; { register struct labdatstruct *labptr; struct labdatstruct *labtop; for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB]; labptr < labtop; ++labptr) if (labptr->labnum == label) { if (labptr->labpatch != 0) break; return labptr; } return (struct labdatstruct *) NULL; } /* reserve a new label, from top down to temp avoid renumbering low labels */ PUBLIC label_no gethighlabel() { return --lasthighlab; } /* reserve a new label */ PUBLIC label_no getlabel() { return ++lastlab; } /* jump to label */ PUBLIC void jump(label) label_no label; { lbranch(RA, label); } /* long branch on condition to label */ PUBLIC void lbranch(cond, label) ccode_pt cond; label_no label; { #ifdef I8088 char *cnameptr; #endif struct labdatstruct *labptr; char *oldoutptr; if ((ccode_t) cond == RN) return; if ((labptr = findlabel(label)) != NULL && isshortbranch(lc - labptr->lablc + 2)) { sbranch(cond, label); return; } oldoutptr = outbufptr; if (cond == RA) outjumpstring(); else { outlbranch(); #ifdef I8088 outbyte(*(cnameptr = lcondnames[(int) cond])); outbyte(*(cnameptr + 1)); if ((ccode_t) cond == LS || (ccode_t) cond == HS) outbyte('s'); /* "blos" or "bhis" */ else outbyte(' '); outtab(); bumplc2(); #ifdef I80386 if (i386_32) bumplc(); #endif #endif #ifdef MC6809 outcond(cond); bumplc(); #endif } outlabel(label); outnl(); if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */ addlabel(cond, label, oldoutptr); } /* look up the name gsname in label space, install it if new */ PUBLIC struct symstruct *namedlabel() { struct symstruct *symptr; gs2name[1] = 0xFF; if ((symptr = findlorg(gs2name + 1)) == NULL) { symptr = addglb(gs2name + 1, vtype); symptr->flags = LABELLED; } if (symptr->indcount < 2) { symptr->indcount = 2; symptr->offset.offlabel = gethighlabel(); if (namedfirst == NULL) namedfirst = symptr; else namedlast->type = (struct typestruct *) symptr; namedlast = symptr; symptr->type = NULL; } return symptr; } #ifdef MC6809 /* print condition code name */ PUBLIC void outcond(cond) ccode_pt cond; { char *cnameptr; outbyte(*(cnameptr = condnames[(ccode_t) cond])); outbyte(*(cnameptr + 1)); outtab(); } #endif /* print label */ PUBLIC void outlabel(label) label_no label; { outbyte(LABELSTARTCHAR); outhexdigs((uoffset_T) label); } /* print label and newline */ PUBLIC void outnlabel(label) label_no label; { outlabel(label); #ifdef LABELENDCHAR outnbyte(LABELENDCHAR); #else outnl(); #endif } /* short branch on condition to label */ PUBLIC void sbranch(cond, label) ccode_pt cond; label_no label; { #ifdef I8088 char *cnameptr; if ((ccode_t) cond != RN) { outsbranch(); outbyte(*(cnameptr = scondnames[(int) cond])); outbyte(*(cnameptr + 1)); outtab(); outlabel(label); outnl(); } #endif #ifdef MC6809 outsbranch(); outcond(cond); outlabel(label); outnl(); #endif } /* reverse bump location counter */ PUBLIC void unbumplc() { --lc; } dev86-0.16.17/bcc/glogcode.c0000644000000000000000000003175206456134233015254 0ustar rootroot00000000000000/* glogcode.c - generate code for logical expressions for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "condcode.h" #include "gencode.h" #include "reg.h" #include "scan.h" #include "sizes.h" #include "type.h" #define cc_signed(cc) ((cc) >= 4 && (cc) < 8) PRIVATE char oppcc[] = /* opposite condition codes LT --> GE etc */ /* EQ, NE, RA, RN, LT, GE, LE, GT, LO, HS, LS, HI, indices */ { NE, EQ, RN, RA, GE, LT, GT, LE, HS, LO, HI, LS, }; PRIVATE char reverscc[] = /* reverse condition codes LT --> GT etc */ { EQ, NE, RN, RA, GT, LE, GE, LT, HI, LS, HS, LO, }; PRIVATE char testcc[] = /* test condition codes LS --> EQ etc */ { EQ, NE, RA, RN, LT, GE, LE, GT, RN, RA, EQ, NE, }; PRIVATE char unsigncc[] = /* unsigned condition codes LT --> LO etc */ { EQ, NE, RA, RN, LO, HS, LS, HI, LO, HS, LS, HI, }; FORWARD void cmplocal P((struct symstruct *source, struct symstruct *target, ccode_t *pcondtrue)); #ifdef MC6809 FORWARD void cmporsub P((struct symstruct *target)); FORWARD bool_pt cmpsmallconst P((value_t intconst, struct symstruct *target, ccode_t *pcondtrue)); #endif FORWARD void comparecond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void jumpcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void loadlogical P((struct symstruct *source, label_no falselab)); FORWARD void logandcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void logorcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); FORWARD void reduceconst P((struct symstruct *source)); FORWARD void test P((struct symstruct *target, ccode_t *pcondtrue)); FORWARD void testcond P((struct nodestruct *exp, label_no truelab, label_no falselab, bool_pt nojump)); PUBLIC void cmp(source, target, pcondtrue) struct symstruct *source; struct symstruct *target; ccode_t *pcondtrue; { label_no falselab; cmplocal(source, target, pcondtrue); #if 0 #ifdef I80386 if (i386_32) { if (*pcondtrue == LO) { getlabel(); getlabel(); outnop2str("sbb\teax,eax"); outnop1str("inc eax"); target->storage = BREG; target->type = ctype; return; } if (*pcondtrue == HS) { getlabel(); getlabel(); outnop2str("sbb\teax,eax"); outnop2str("neg eax"); target->storage = BREG; target->type = ctype; return; } } #endif #endif sbranch(oppcc[(int)*pcondtrue], falselab = getlabel()); loadlogical(target, falselab); } PRIVATE void cmplocal(source, target, pcondtrue) struct symstruct *source; struct symstruct *target; ccode_t *pcondtrue; { scalar_t sscalar; scalar_t tempscalar; scalar_t tscalar; reduceconst(source); reduceconst(target); sscalar = source->type->scalar; tscalar = target->type->scalar; if ((source->storage != CONSTANT && (target->storage == CONSTANT || (sscalar & CHAR && !(tscalar & CHAR)) || ((sscalar & CHAR || !(tscalar & CHAR)) && source->indcount == 0 && target->indcount != 0))) || (tscalar & DLONG && target->indcount != 0)) { swapsym(target, source); *pcondtrue = reverscc[(int)*pcondtrue]; tempscalar = sscalar; sscalar = tscalar; tscalar = tempscalar; } if ((sscalar & CHAR && tscalar & CHAR && (source->type != sctype || target->type != sctype)) || (sscalar | tscalar) & UNSIGNED || (source->type->constructor | target->type->constructor) & (ARRAY | POINTER)) *pcondtrue = unsigncc[(int)*pcondtrue]; if (source->type->scalar & DLONG) { longop(EQOP, source, target); return; } if (source->type->scalar & RSCALAR) { floatop(EQOP, source, target); return; } if (source->storage == CONSTANT) { if (sscalar & CHAR) { if (tscalar & CHAR) *pcondtrue = unsigncc[(int)*pcondtrue]; else { source->type = iscalartotype(sscalar); sscalar = source->type->scalar; } } if (source->offset.offv == 0) { test(target, pcondtrue); return; } #ifdef MC6809 if (cmpsmallconst(source->offset.offv, target, pcondtrue)) return; #endif } if (!(sscalar & CHAR) && tscalar & CHAR) { loadpres(target, source); extend(target); } #ifndef MC6809 # define posindependent 0 #endif if (source->indcount == 0 && source->storage != CONSTANT && (posindependent || source->storage != GLOBAL)) { loadpres(source, target); #ifdef MC6809 push(source); #endif } loadpres(target, source); #ifdef MC6809 cmporsub(target); #else outcmp(); #endif #ifdef I8088 if (source->storage == GLOBAL && source->indcount == 0 && !(target->storage & (AXREG | ALREG))) bumplc(); #endif movereg(source, target->storage); } #ifdef MC6809 PRIVATE void cmporsub(target) struct symstruct *target; { if (target->storage & ALLDATREGS) outsub(); else { outcmp(); if (target->storage != XREG) bumplc(); } } PRIVATE bool_pt cmpsmallconst(intconst, target, pcondtrue) value_t intconst; struct symstruct *target; ccode_t *pcondtrue; { store_pt targreg; if ((*pcondtrue == EQ || *pcondtrue == NE) && !(target->storage & ALLDATREGS) && !(target->type->scalar & CHAR) && isnegbyteoffset(intconst) && (reguse & (XREG | YREG)) != (XREG | YREG)) { targreg = XREG; if (reguse & XREG) targreg = YREG; if (target->indcount != 0) load(target, targreg); target->offset.offi -= (offset_T) intconst; loadreg(target, targreg); return TRUE; } return FALSE; } #endif PRIVATE void comparecond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { ccode_t condtrue; store_t regmark; struct symstruct *source; offset_T spmark; struct symstruct *target; regmark = reguse; spmark = sp; bileaf(exp); target = exp->left.nodeptr->left.symptr; source = exp->right->left.symptr; /* exp->right != NULL since cond */ switch (exp->tag) { case GEOP: condtrue = GE; break; case GTOP: condtrue = GT; break; case LEOP: condtrue = LE; break; case EQOP: condtrue = EQ; break; case LTOP: condtrue = LT; break; case NEOP: condtrue = NE; break; } cmplocal(source, target, &condtrue); changesp(spmark, FALSE); reguse = regmark; if ((bool_t) nojump) lbranch(oppcc[(int)condtrue], falselab); else lbranch(condtrue, truelab); } PUBLIC void condop(exp) struct nodestruct *exp; { label_no exitlab; label_no falselab; struct nodestruct *falsenode; struct symstruct *falsesym; label_no truelab; struct nodestruct *truenode; struct symstruct *truesym; jumpcond(exp->left.nodeptr, truelab = getlabel(), falselab = getlabel(), ~0); deflabel(truelab); makeleaf(truenode = exp->right->left.nodeptr); loadany(truesym = truenode->left.symptr); if (truesym->storage & reguse) { /* This can happen if truesym was a reg variable. */ if (truesym->type->scalar & RSCALAR) /* XXX - always happens for non-386 with 2 regs vars assigned. */ bugerror("loaded float or double into used reg"); load(truesym, DREG); } falsenode = exp->right->right; if (/* falsenode->tag != LEAF || XXX */ truesym->type != falsenode->left.symptr->type) cast(truenode->nodetype == falsenode->nodetype ? truenode->nodetype : exp->nodetype, truesym); jump(exitlab = getlabel()); deflabel(falselab); makeleaf(falsenode); falsesym = falsenode->left.symptr; if (falsesym->type != truesym->type) cast(truesym->type, falsesym); load(falsesym, truesym->storage); deflabel(exitlab); exp->tag = LEAF; exp->left.symptr = truesym; } PRIVATE void jumpcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { switch (exp->tag) { case GEOP: case GTOP: case LEOP: case EQOP: case LTOP: case NEOP: comparecond(exp, truelab, falselab, nojump); break; case LOGANDOP: logandcond(exp, truelab, falselab, nojump); break; case LOGNOTOP: jumpcond(exp->left.nodeptr, falselab, truelab, ~nojump); break; case LOGOROP: logorcond(exp, truelab, falselab, nojump); break; default: testcond(exp, truelab, falselab, nojump); break; } } PUBLIC void jumpfalse(exp, label) struct nodestruct *exp; label_no label; { label_no truelab; jumpcond(exp, truelab = getlabel(), label, ~0); deflabel(truelab); } PUBLIC void jumptrue(exp, label) struct nodestruct *exp; label_no label; { label_no falselab; jumpcond(exp, label, falselab = getlabel(), 0); deflabel(falselab); } PRIVATE void loadlogical(source, falselab) struct symstruct *source; label_no falselab; { label_no exitlab; struct symstruct *target; target = constsym((value_t) TRUE); target->type = ctype; loadreg(target, DREG); sbranch(RA, exitlab = getlabel()); deflabel(falselab); target = constsym((value_t) FALSE); target->type = ctype; *source = *target; loadreg(source, DREG); outnlabel(exitlab); } PRIVATE void logandcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { label_no andlab; andlab = getlabel(); jumpcond(exp->left.nodeptr, andlab, falselab, ~0); deflabel(andlab); jumpcond(exp->right, truelab, falselab, nojump); } PUBLIC void logop(exp) struct nodestruct *exp; { label_no falselab; struct symstruct *target; label_no truelab; jumpcond(exp, truelab = getlabel(), falselab = getlabel(), ~0); deflabel(truelab); target = constsym((value_t) 0); /* anything, loadlogical makes B reg */ target->type = ctype; loadlogical(target, falselab); exp->tag = LEAF; exp->left.symptr = target; } PRIVATE void logorcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { label_no orlab; orlab = getlabel(); jumpcond(exp->left.nodeptr, truelab, orlab, 0); deflabel(orlab); jumpcond(exp->right, truelab, falselab, nojump); } PRIVATE void reduceconst(source) struct symstruct *source; { if (source->storage == CONSTANT && ischarconst(source->offset.offv) && (source->type->scalar & (CHAR | SHORT | INT | DLONG)) != DLONG) { if (source->type->scalar & UNSIGNED) source->type = uctype; else source->type = ctype; } } PRIVATE void test(target, pcondtrue) struct symstruct *target; ccode_t *pcondtrue; { #ifdef I8088 store_t targreg; #endif *pcondtrue = testcc[(int)*pcondtrue]; if (target->type->scalar & DLONG) { long1op(EQOP, target); return; } if (target->type->scalar & RSCALAR) { float1op(EQOP, target); return; } #ifdef I8088 if (target->indcount != 0 || (target->storage == LOCAL && target->offset.offi != sp)) load(target, DREG); if (target->storage == GLOBAL) load(target, getindexreg()); if (target->type->scalar & CHAR) load(target, DREG); targreg = target->storage; if (target->offset.offi != 0 && cc_signed(*pcondtrue)) load(target, targreg); #ifdef I80386 /* Extension was not done in exptree for the == 0 case, to allow * optimization here - which we don't do for shorts. (foo--) is * newfoo == -1 here and used to be missed. */ if (i386_32 && target->type->scalar & SHORT) extend(target); #endif if (target->offset.offi == 0) { outtest(); outregname(targreg); outcomma(); outnregname(targreg); return; } outcmp(); outimadj(-target->offset.offi, targreg); #endif #ifdef MC6809 if (target->indcount != 0 || target->storage == LOCAL && target->offset.offi != sp) { load(target, DREG); return; } if (cmpsmallconst(0, target, pcondtrue)) return; if (target->storage == GLOBAL) load(target, getindexreg()); if (target->type->scalar & CHAR) load(target, DREG); if (target->offset.offi != 0 && cc_signed(*pcondtrue)) load(target, target->storage); if (target->type->scalar & CHAR) { if (target->offset.offi == 0) { outtest(); outnregname(BREG); return; } outcmp(); outimadj(-target->offset.offi, BREG); } else { cmporsub(target); outimadj(-target->offset.offi, target->storage); } #endif } /* test expression and jump depending on NE/EQ */ PRIVATE void testcond(exp, truelab, falselab, nojump) struct nodestruct *exp; label_no truelab; label_no falselab; bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */ { ccode_t condtrue; struct symstruct *source; makeleaf(exp); source = exp->left.symptr; reduceconst(source); if (source->storage != CONSTANT) { condtrue = NE; test(source, &condtrue); if ((bool_t) nojump) lbranch(oppcc[(int)condtrue], falselab); else lbranch(condtrue, truelab); } else if (source->offset.offi == 0) { if ((bool_t) nojump) jump(falselab); } else if (!(bool_t) nojump) jump(truelab); } dev86-0.16.17/bcc/bcc.h0000644000000000000000000000116606413413157014217 0ustar rootroot00000000000000/* Copyright (C) 1997 Robert de Bath * This file is part of the Linux-8086 Development environment and is * distributed under the GNU General Public License. */ #ifdef _AIX #include /* AIX 4.1 + GCC seems to need this */ #endif /* Ansi C has certain guarentees ... except under MSdross :-( */ #ifdef __STDC__ #ifndef MSDOS #include #include #include #include #endif #define P(x) x #else #define P(x) () #endif #include "const.h" #include "types.h" #include "proto.h" #if !defined(__STDC__) || defined(MSDOS) #include "sysproto.h" #endif dev86-0.16.17/bcc/bcc.doc0000644000000000000000000001567010002503235014524 0ustar rootroot00000000000000WARNING: This document bis out of date; it's kept mainly for the 6809 notes. bcc options ----------- bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option] [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir] [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles] The 6809 version does not support -0, -3 or -G. Only the c386 version supports -Q. defaults (off or none except for these): -03 native outfile stdout for preprocessor output somewhere/file.[ci] -> file.s for compiler output somewhere/file.[cis] -> file.o for assembler output a.out for ld output -ansi Pass the source through 'unproto' first -0 8086 target (works even on 80386 host) -3 80386 target (works even on 8086 host) -A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing) -B prefix for executable search path (as usual; the search order is all paths specified using -B, in order, then the path given in the environment variable BCC_EXEC_PREFIX if that is set, then the compiled-in defaults (something like /usr/libexec/i386/bcc/ followed by /usr/bin/)) -C pass remainder of option to cc1 (e.g. -C-c for caller-saves) -D define (as usual) -E produce preprocessor output (as usual) -G produce gnu-Minix objects (link with gnu ld) -Ix include search path (as usual) -I don't add default include to search list -Lx add dir name x to the head of the list of library dirs searched -L don't add default library to search list -X pass remainder of option to linker -O optimize (does nothing) -P produce preprocessor output with no line numbers (as usual) -Q pass full option to c386 -S produce assembler file (as usual) -T temporary directory (overrides previous value and default; default is from the environment variable TMPDIR if that is set, otherwise /tmp) -U undefine (as usual) -V print names of files being compiled -c produce object file (as usual) -e run the preprocess pass separately. This takes less memory, and may help or harm by giving more traditional semantics like token pasting with /**/. -f error (float emulation not supported) -g produce debugging info (does nothing) -o output file name follows (assembler, object or executable) (as usual) -p error (profiling not supported) -t error (substitution of some cc passes not supported) -v print names and args of subprocesses being run. Two or more -v's: print names of files being unlinked. Three or more -v's: print names of paths being searched. Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s. The -i option is always passed to the linker but can be cancelled using -i-. This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L, -T, -V, -e, -v and where not supported. cc1 options ---------- cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile] The 6809 version does not support -0 or -3 but it supports -p. defaults (off or none except for these): -03 native -c on for 6809 -f on for 6809 outfile stdout infile stdin -0 8086 target (works even on 80386 host) -3 80386 target (works even on 8086 host) -D define (as usual) -E produce preprocessor output (as usual) -I include search path (as usual) -P produce preprocessor output with no line numbers (as usual) -c produce code with caller saving regs before function calls -d print debugging information in assembly output -f produce code with 1st argument passed in a register -l produce code for 2 3 1 0 long byte order (only works in 16-bit versions) -o assembler output file name follows -p produce (almost) position-independent code -t print source code in assemby output -w print what cc1 thinks is the location counter in assembly output All the options except -D, -I and -o may be turned off by following the option letter by a '-'. Options are processed left to right so the last setting has precedence. The following is defined before option processing: __BCC__ 1 The following may be defined after option processing: __AS09__ 1 if 6809 version __AS386_16__ 1 if -0 option on 80*86 __AS386_32__ 1 if -3 option on 80*86 __CALLER_SAVES__ 1 if -c option __FIRST_ARG_IN_AX__ 1 if -f option on 80*86 __FIRST_ARG_IN_X__ 1 if -f option on 6809 __LONG_BIG_ENDIAN__ 1 if -l option __POS_INDEPENDENT__ 1 if -p option on 6809 The following are standard builtins: __FILE__ stringized name of current input file __LINE__ current line number as options ---------- as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src The 6809 version does not support -0, -3, -a or -j. defaults (off or none except for these; no output is produced without a flag): -03 native list stdout (beware of clobbering next arg) name basename of the source name -0 start with 16-bit code segment -3 start with 32-bit code segment -a enable partial compatibility with asld -g only put global symbols in object file -j force all jumps to be long -l produce list file, filename may follow -m print macro expansions in listing -n name of module follows (goes in object instead of source name) -o produce object file, filename follows -b produce binary file, filename may follow -s produce symbol file, filename follows -u take undefined symbols as imported-with-unspecified segment -w don't print warnings The -u and -w options are perhaps back to front because they are needed for cc1 output and Minix's make does the wrong thing with .s files left around. However, all assembler code not written by compilers should assemble with them turned off. The -b flag now produces a 'raw' binary file with no header, if there's no -s flag the file starts at location 0. The -s generates an ASCII symbol table, if a binary file doesn't start at location zero the first two items are the start and end addresses of the binary file. ld options ---------- ld [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile] [-Llibdir] [-Olibfile] [-T textaddr] infile... The version that produces old Minix a.out format does not support -r. The 6809 version does not support -i or -r. defaults (off or none except for these): -03 native -L/usr/local/lib/m/ (m is machine-dependent) outfile a.out -0 produce header with 16-bit magic and use library subdir i86 for -lx -3 produce header with 32-bit magic and use library subdir i386 for -lx -Cx add file libdir-from-search/crtx.o to list of files linked -Lx add dir name x to the head of the list of library dirs searched -M print symbols linked on stdout -Ox add library libdir-from-search/x to list of files linked -T text base address follows (in format suitable for strtoul) -i separate I&D output -lx add library libdir-from-search/libx.a to list of files linked -m print modules linked on stdout -o output file name follows -r produce output suitable for further relocation -s strip symbols -t trace modules being looked at on stdout -z produce "unmapped zero page" executables All the options not taking an argument may be turned off by following the option letter by a '-', as for cc1. dev86-0.16.17/bcc/types.h0000644000000000000000000001254606456134236014645 0ustar rootroot00000000000000/* types.h - type definitions for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* source types big enough to handle target quantities these have to be match the source compiler and target machine this is impossible if the source long type is too small */ typedef unsigned char char_t; /* target char */ typedef long value_t; /* target ints, longs and offsets */ typedef unsigned long uvalue_t; /* target unsigned ints, longs and offsets */ #ifdef I8088 typedef long offset_T; /* target machine offset */ typedef unsigned long uoffset_T; /* target unsigned machine offset */ #define outuvalue outhex #define outvalue outshex #endif #ifdef MC6809 typedef int offset_T; typedef unsigned uoffset_T; #endif /* storage class type must hold all the flags defined elsewhere it must have a few more bits than the target has registers */ #ifdef I8088 typedef unsigned store_pt; /* promoted store_t */ typedef unsigned store_t; /* storage class flags */ #endif #ifdef MC6809 #ifdef __STDC__ typedef int store_pt; # else typedef unsigned store_pt; # endif typedef unsigned char store_t; #endif /* types for library routines */ typedef int fd_t; /* file descriptor */ /* basic scalar types - may be tuned to suit machine */ typedef int fastin_pt; /* promoted fastin_t */ /* always an int - use to show that the */ /* value may be accessed as a fastin_t */ typedef char fastin_t; /* fast int - a small integer value */ /* on some machines, chars can be accessed */ /* more efficiently than ints for arithmetic */ /* such as comparing and masking which */ /* does not requiring promotion */ /* change to int if chars are inefficient */ /* or if char has < 8 bits */ typedef int smalin_pt; /* promoted smalin_t */ typedef char smalin_t; /* small int - a small integer value */ /* on most machines, chars are stored in */ /* less space than any other type */ /* change to fastin_t if this is not true */ /* or if char has < 8 bits */ /* or if space is not a limiting factor */ #ifdef __STDC__ typedef int smalu_pt; #else typedef unsigned smalu_pt; #endif typedef unsigned char smalu_t; /* derived scalar types the types containing bit flags fit in an 8 bit smalin_t */ typedef fastin_pt bool_pt; /* promoted bool_t */ typedef fastin_t bool_t; /* boolean: TRUE if nonzero */ typedef fastin_pt ccode_pt; /* promoted ccode_t */ typedef fastin_t ccode_t; /* condition code code */ typedef smalu_pt constr_pt; /* promoted constr_t */ typedef smalu_t constr_t; /* type constructor flags */ typedef smalu_pt indn_pt; /* promoted indn_t */ typedef smalu_t indn_t; /* storage indirection count */ typedef unsigned label_no; /* label number */ typedef smalu_t maclev_t; /* macro expansion level */ typedef smalin_pt op_pt; /* promoted op_t */ typedef smalin_t op_t; /* operator code */ typedef smalu_t sc_t; /* storage class flags */ typedef smalu_pt scalar_pt; /* promoted scalar_t */ typedef smalu_t scalar_t; /* type scalar flags */ typedef smalu_t scopelev_t; /* scope level */ typedef fastin_pt sym_pt; /* promoted sym_t */ typedef fastin_t sym_t; /* symbol code from scanner */ typedef smalu_t weight_t; /* expression tree node weight */ /* derived structure types the fields are ordered in a way that is most space-efficient when smalin_t is char and smalu_t is unsigned char the first element of the structures is the one most frequently accessed */ /* expression table entry format */ struct nodestruct { op_t tag; weight_t weight; smalu_t flags; struct typestruct *nodetype; union nodeunion { struct nodestruct *nodeptr; struct symstruct *symptr; } left; struct nodestruct *right; }; /* symbol table entry format */ struct symstruct { store_t storage; indn_t indcount; sc_t flags; scopelev_t level; struct symstruct *next; struct symstruct **prev; struct typestruct *type; union { double *offd; /* value for double constants */ offset_T offi; /* offset for register or global storage */ label_no offlabel; /* label number for strings */ char *offp; /* to string for macro definitions */ sym_pt offsym; /* symbol code for keywords */ value_t offv; /* value for integral constants */ } offset; union { label_no label; /* label number for strings */ char namea[1]; /* variable length array for declarations */ char *namep; /* to constant storage for exprs */ } name; }; /* type table entry format */ struct typestruct { scalar_t scalar; /* scalar type flags u d f l i s c */ constr_t constructor; /* constructed type flags a f p s/u */ char structkey[2]; /* unique prefix for member names */ /* ranges from "\001\001" to "@\377" */ /* avoiding nulls */ uoffset_T alignmask; /* alignment mask, typesize - 1 for scalars */ uoffset_T typesize; /* size of this type */ char *tname; /* name of scalar type or constructor */ struct typelist *listtype; /* list of member types */ struct typestruct *nexttype; /* next in list */ struct typestruct *prevtype; /* previous in list */ struct typestruct *sidetype; /* next in sideways list */ }; /* list of type structures */ struct typelist { struct typelist *tlnext; struct typestruct *tltype; }; /* definitions to avoid passing raw NULLs to functions */ #define NULLNODE ((struct nodestruct *) NULL) #define NULLTYPE ((struct typestruct *) NULL) dev86-0.16.17/bcc/parse.h0000644000000000000000000000072407420066672014606 0ustar rootroot00000000000000/* parse.h - parser for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* possible scope levels */ #define ARGLEVEL 1 #define GLBLEVEL 0 #define MAXLEVEL 125 #define MINLOCLEVEL 1 /* possible node flags */ #define LVALUE (1 << 0) EXTERN struct nodestruct *etptr; /* ptr to next entry in expression tree */ EXTERN struct symstruct *gvarsymptr; /* gsymptr for last identifier declared */ EXTERN scopelev_t level; /* scope level */ /* depends on zero init */ dev86-0.16.17/bcc/sc.h0000644000000000000000000000176305301213542014067 0ustar rootroot00000000000000/* sc.h - storage classes for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef MC6809 #define DIRECTPAGE 0x01 /* modifier on global to show in dpseg */ #endif #define EXTERNAL 0x02 /* external */ #define STATIC 0x04 /* symbols with flags above the 1st initialised value are not to be dumped */ #define MAXDUMPFLAG 0x07 #define INITIALIZED 0x08 /* modifier on global to show initialized */ #define LABELLED 0x10 /* modifier on static to show labelled */ /* and on STRING to show labelled */ /* remaining "flags" are numbers, not flags */ /* they are disjoint from all combinations of flags above */ /* except STRING => LABELLED (and no other flags) */ #define DEFINITION 0x20 /* #defined name */ #define KEYWORD 0x40 /* reserved word for C */ #define STRUCTNAME 0x60 /* struct/union name or member name */ #define REGVAR 0x80 /* register variable */ #define TEMP 0xa0 /* temporary on stack expression eval */ #define STRING 0xc0 /* string constant (=> LABELLED) */ dev86-0.16.17/bcc/scan.h0000644000000000000000000001022307520720126014403 0ustar rootroot00000000000000/* scan.h - scanner for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define NAMESIZE 64 /* limit on identifier lengths */ #define SYMOFCHAR(ch) (symofchar[(unsigned char) (ch)]) /* scanner codes */ enum scan_states { /* The first group of entries consists of all the values that occur in the switch for cppscan(). */ IDENT, INTCONST, #define MAXIDSYM INTCONST /* IDENT and INTCONST must be the only * symofchar[] entries below this */ FLOATCONST, #define MAXPPNUMSYM FLOATCONST /* IDENT, INTCONST and FLOATCONST must be the * only symofchar[] entries below this */ CHARCONST, CONTROL, SLASH, SPECIALCHAR, STRINGCONST, /* The next group of entries are all the rest of the values that occur in symofchar[] and so in the switch for nextsym(). */ AMPERSAND, /* ADDRESSOP or ANDOP */ BADCHAR, COLON, /* also COLONOP */ COMMA, /* also COMMAOP */ DECSYM, /* PREDECOP or POSTDECOP */ EOFSYM, HYPHEN, /* NEGOP or SUBOP */ INCSYM, /* PREINCOP or POSTINCOP */ LBRACE, LBRACKET, LPAREN, RBRACE, RBRACKET, RPAREN, SEMICOLON, STAR, /* INDIRECTOP or MULOP */ WHITESPACE, /* The next group of entries consists of all operator codes. These codes must be contiguous so they can be used as (offsetted) array indexes. The group is ordered by operator-precedence (this is not necessary). The first part of it overlaps the previous group. */ /* Assign-abops (level 1) belong here but are at end to improve switch. */ #define FIRSTOP CONDOP CONDOP, /* level 2 */ OROP, /* level 5 */ EOROP, /* level 6 */ ANDOP, /* level 7 */ GTOP, /* level 9 */ LTOP, ADDOP, /* level 11 */ DIVOP, /* level 12 */ MODOP, LOGNOTOP, /* level 13 */ NOTOP, STRUCELTOP, /* level 14 */ STRUCPTROP, /* End of symbols that appear in symofchar[]. */ ASSIGNOP, /* level 1 - assign ops must be contiguous */ ADDABOP, ANDABOP, DIVABOP, EORABOP, MODABOP, MULABOP, ORABOP, SLABOP, SRABOP, SUBABOP, COMMAOP, /* level 0 */ COLONOP, /* level 2 */ LOGOROP, /* level 3 */ LOGANDOP, /* level 4 */ EQOP, /* level 8 */ NEOP, GEOP, /* level 9 */ LEOP, SLOP, /* level 10 */ SROP, SUBOP, /* level 11 */ MULOP, /* level 12 */ ADDRESSOP, /* level 13 */ CASTOP, INDIRECTOP, NEGOP, PREDECOP, PREINCOP, POSTDECOP, POSTINCOP, FUNCOP, /* level 14 */ LISTOP, ROOTLISTOP, LEAF, /* special */ PTRADDABOP, PTRADDOP, PTRSUBOP, /* end of operator codes (they must stay contiguous) */ #define LASTOP PTRSUBOP ENUMDECL, NULLDECL, SIGNDECL, STRUCTDECL, TYPEDECL, TYPEDEFNAME, UNIONDECL, UNSIGNDECL, AUTODECL, EXTERNDECL, REGDECL, STATICDECL, TYPEDEFDECL, ASMSYM, BREAKSYM, CASESYM, CONTSYM, DEFAULTSYM, DEFINEDSYM, DOSYM, ELSESYM, FORSYM, GOTOSYM, IFSYM, RETURNSYM, SIZEOFSYM, SWITCHSYM, WHILESYM, ASMCNTL, DEFINECNTL, ENDASMCNTL, INCLUDECNTL, LINECNTL, UNDEFCNTL, WARNINGCNTL, ERRORCNTL, ELIFCNTL, /* "IF" controls must be contiguous */ ELSECNTL, ENDIFCNTL, IFCNTL, IFDEFCNTL, IFNDEFCNTL }; EXTERN op_pt arg1op; /* LISTOP, or ROOTLISTOP if arg1inreg */ EXTERN struct { union { char *s; value_t v; double d; } value; struct typestruct *type; } constant; /* value of last constant scanned */ /* sym tells type */ EXTERN char funcname[NAMESIZE]; /* name of current function for unique labels */ EXTERN char gs2name[2 + NAMESIZE]; /* 2 reserved for namespace keys */ #define gsname (gs2name + 2) /* before last identifier */ EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */ EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */ EXTERN sym_t sym; /* current symbol */ extern sym_t symofchar[]; /* table to convert chars to their symbols */ EXTERN bool_t expect_statement; /* If set #asm needs to clear the recursive * pending operations. ie: if stmts. */ dev86-0.16.17/bcc/gencode.h0000644000000000000000000001000610065301133015051 0ustar rootroot00000000000000/* gencode.h - code generation for bcc */ /* Copyright (C) 1992 Bruce Evans */ #ifdef MC6809 # define CANABXCUTOFF 7 /* favour ABX over MUL before this */ #endif #define EXPRLEVEL 126 /* level for symbols in exptree, > real levs */ #define OFFKLUDGELEVEL 127 /* level for expr sym with offset from name */ #define OPERANDSEPARATOR ',' /* char separating operands */ #define OPSEPARATOR '\t' /* char separating op string and operand */ EXTERN uoffset_T arg1size; /* size of 1st arg to function */ /* zero after allocation of 1st arg */ EXTERN store_pt callee1mask; /* calleemask with doubleregs masked if nec */ EXTERN uoffset_T dataoffset; /* amount of initialized data so far */ #ifdef DBNODE EXTERN bool_t dbnodeon; /* nonzero to print debugging messages */ /* depends on zero init */ #endif #ifdef FRAMEPOINTER EXTERN store_pt framelist; /* bit pattern for frame and saved regs */ EXTERN store_pt frame1list; /* framelist with doubleregs masked if nec */ EXTERN offset_T framep; /* hardware relative frame ptr */ #endif EXTERN uoffset_T func1saveregsize; /* choice of next two values */ EXTERN uoffset_T funcdsaveregsize; /* funcsaveregsize adjusted for doubles */ EXTERN uoffset_T funcsaveregsize; /* tot size of framelist/calleemask regs */ #ifdef I80386 EXTERN bool_t i386_32; /* nonzero to generate 386 32 bit code */ /* depends on zero init */ #endif #ifdef DYNAMIC_LONG_ORDER EXTERN bool_t long_big_endian; /* nonzero if high long word is first */ /* depends on zero init */ #endif EXTERN offset_T lowsp; /* low water sp (collects locals in switch) */ #ifdef POSINDEPENDENT EXTERN bool_t posindependent; /* nonzero to generate pos-independent code */ /* depends on zero init */ #endif EXTERN bool_t printf_fp; /* nonzero if *printf called with FP arg */ EXTERN bool_t regarg; /* nonzero to show unloaded register arg */ /* depends on zero init */ EXTERN store_t reguse; /* registers in use */ EXTERN bool_t scanf_fp; /* nonzero if *scanf called with ptr-to-FP */ EXTERN offset_T softsp; /* software sp (leads sp during declares) */ EXTERN offset_T sp; /* hardware relative stack ptr */ /* depends on zero init */ EXTERN store_t regfuse; /* registers in use in function. */ #ifdef FRAMEPOINTER EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */ #endif EXTERN struct switchstruct *switchnow; /* currently active switch */ /* depends on NULL init */ EXTERN bool_t optimise; /* nonzero to add optimisation code */ /* variables to be initialised to nonzero */ extern store_pt allindregs; /* mask (in) for index registers */ extern store_pt allregs; /* mask (in) for registers */ extern bool_t arg1inreg; /* nonzero to pass 1st arg in reg */ extern store_pt calleemask; /* mask (in) for regs to be saved by callee */ extern bool_t callersaves; /* nonzero to make caller save regs */ extern char *callstring; /* opcode string for call */ extern store_pt doubleargregs; /* mask (in) for regs for 1st arg if double */ extern store_pt doubleregs; /* mask (in) for regs to temp contain double */ extern store_pt doublreturnregs; /* mask (in) for regs for returning double */ extern offset_T jcclonger; /* amount jcc long jumps are longer */ extern offset_T jmplonger; /* amount long jumps is longer */ extern char *jumpstring; /* opcode string for jump */ extern char *regpulllist; /* reg names and sizes (0 store_t bit first) */ extern char *regpushlist; /* reg names and sizes (0 store_t bit last) */ extern store_pt regregs; /* mask (in) for regs which can be reg vars */ /* register names */ extern char *acclostr; extern char *accumstr; extern char *badregstr; #ifdef I8088 extern char *dreg1str; extern char *dreg1bstr; extern char *dreg2str; #endif extern char *ireg0str; extern char *ireg1str; extern char *ireg2str; extern char *localregstr; #ifdef I8088 extern char *stackregstr; #endif /* register sizes */ extern uoffset_T accregsize; #ifdef FRAMEPOINTER extern uoffset_T frameregsize; #endif extern uoffset_T maxregsize; extern uoffset_T opregsize; extern uoffset_T pshregsize; extern uoffset_T returnadrsize; dev86-0.16.17/bcc/loadexp.c0000644000000000000000000001025506456134233015120 0ustar rootroot00000000000000/* loadexp.c - load expressions for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "table.h" #include "type.h" PUBLIC value_t constexpression() { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; struct symstruct *symptr; etmark = etptr; exprmark = exprptr; exp = assignment_exp(); etptr = etmark; exprptr = exprmark; if (exp->tag == LEAF && (symptr = exp->left.symptr)->storage == CONSTANT && symptr->type->scalar & ISCALAR) return symptr->offset.offv; error("constant expression required"); return 1; } PUBLIC void initexpression(type) struct typestruct *type; { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; struct nodestruct *lhs; struct symstruct *symptr; uoffset_T value; if (gvarsymptr->storage != GLOBAL) reslocals(); exprmark = exprptr; etmark = etptr; exp = assignment_exp(); if (gvarsymptr->storage != GLOBAL) { lhs = leafnode(exprsym(gvarsymptr)); if (!(lhs->nodetype->constructor & (ARRAY | FUNCTION | VOID))) lhs->flags = LVALUE; makeleaf(node(ASSIGNOP, lhs, exp)); } else if (exp->tag != LEAF || ((symptr = exp->left.symptr)->storage != CONSTANT && (symptr->storage != GLOBAL || symptr->indcount != 0 || type->scalar & DLONG)) || (type->constructor | (symptr->type->constructor & ~FUNCTION)) & ~(ARRAY | POINTER)) error("initializer too complicated"); else { if ((symptr->type->scalar | type->scalar) & RSCALAR) { /* Can only afford castnode if result known constant. */ exp = castnode(type, exp); symptr = exp->left.symptr; } if (type->scalar & RSCALAR) { if (type->scalar & FLOAT) { float val; val = *symptr->offset.offd; deflong(((uoffset_T *) &val)[0]); } else { deflong(((uoffset_T *) symptr->offset.offd)[0]); deflong(((uoffset_T *) symptr->offset.offd)[1]); } etptr = etmark; /* XXX - stuff from end of function */ exprptr = exprmark; return; } if (type->typesize == 1) defbyte(); else if (type->typesize == 2) defword(); #ifdef I8088 else if (!(type->scalar & DLONG)) defdword(); #endif switch (symptr->storage) { case CONSTANT: value = (uoffset_T) symptr->offset.offv; if (type->scalar & DLONG) { deflong(value); break; } /* XXX - put sizes in type struct to avoid tests */ if (type->scalar & CHAR) value &= CHMASKTO; else if (type->scalar & SHORT) value &= shortmaskto; else if (type->scalar & INT) value &= intmaskto; /* XXX - no longmaskto */ outnhex(value); break; case GLOBAL: if (symptr->flags & LABELLED) { outlabel(symptr->name.label); outplus(); outnhex((uoffset_T) symptr->offset.offi); break; } if (*symptr->name.namep == 0) /* constant address */ { outnhex((uoffset_T) symptr->offset.offi); break; } outccname(symptr->name.namep); if (symptr->offset.offi != 0) { if (symptr->offset.offi > 0) outplus(); outshex(symptr->offset.offi); } outnl(); break; } } etptr = etmark; exprptr = exprmark; } PUBLIC struct typestruct *loadexpression(targreg, targtype) store_pt targreg; struct typestruct *targtype; { struct nodestruct *etmark; struct nodestruct *exp; struct symstruct *exprmark; etmark = etptr; exprmark = exprptr; exp = expression(); if (targtype != NULL) exp = castnode(targtype, exp); makeleaf(exp); if (targtype == NULL) /* this is for a switch */ { targtype = exp->left.symptr->type; if (!(targtype->scalar & (CHAR | INT)) && (targtype->scalar & (LONG | DLONG)) != LONG) { if (targtype->scalar & SHORT) targtype = promote(targtype); else { error("non-integral selector in switch"); targtype = itype; } makeleaf(exp = castnode(targtype, exp)); } } load(exp->left.symptr, targreg); /* resets stack if value was there */ etptr = etmark; exprptr = exprmark; return exp->left.symptr->type; } dev86-0.16.17/bcc/softop.c0000644000000000000000000001352410065235203014766 0ustar rootroot00000000000000/* softop.c - software operations for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "gencode.h" #include "reg.h" #include "scan.h" #include "sizes.h" #include "type.h" /*----------------------------------------------------------------------------- softop(operation code, source leaf, target leaf) handles binary operations which are not done in hardware if the result type is (unsigned) long, float or double, all the work is immediately passed on to routines in other files. Otherwise: source and target may be either char, int or unsigned int they are not cast to ints or unsigneds before they get here considerable effort goes into avoiding unnecessary pushes -----------------------------------------------------------------------------*/ PUBLIC void softop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_t regpushed; store_t regmark; scalar_t resultscalar; scalar_t sscalar; scalar_t tscalar; value_t sourceval; bool_t uflag; store_t workreg; if ((tscalar = target->type->scalar) & DLONG) { longop(op, source, target); return; } if (tscalar & RSCALAR) { floatop(op, source, target); return; } sscalar = source->type->scalar; resultscalar = tscalar; uflag = tscalar & UNSIGNED; if (op != SLOP && op != SROP) { resultscalar |= sscalar; uflag |= sscalar & UNSIGNED; } #ifdef MC6809 if ((op_t) op == MULOP && sscalar & CHAR && tscalar & CHAR && (source->storage != CONSTANT || (uvalue_t) source->offset.offv > 2)) { if (source->storage & WORKDATREGS) push(source); load(target, DREG); outldmulreg(); outadr(source); outmulmulreg(); target->storage = DREG; target->type = iscalartotype(resultscalar); return; } #endif if (source->storage == CONSTANT) { extend(target); #ifdef I8088 if (op == MULOP || op == SLOP) loadany(target); else #endif load(target, DREG); target->type = iscalartotype(resultscalar); sourceval = source->offset.offv; switch ((op_t) op) { case DIVOP: if (diveasy(sourceval, uflag)) return; break; case MODOP: if (modeasy(sourceval, uflag)) { if ((uvalue_t) sourceval <= MAXUCHTO + 1) { target->storage = BREG; target->type = ctype; if (uflag) target->type = uctype; } return; } break; case MULOP: if (muleasy((uvalue_t) sourceval, target->storage)) return; load(target, DREG); break; case SLOP: slconst(sourceval, target->storage); return; case SROP: srconst(sourceval, uflag); return; } sscalar = (source->type = iscalartotype(resultscalar))->scalar; } /* to load source first if it is CHAR: */ /* need work register if target is in WORKDATREGS */ /* use OPREG unless it will become overloaded later */ /* to preserve source while target is loaded: */ /* if source is in WORKDATREGS, put it in OPREG, */ /* unless target is OPREG-indirect */ /* otherwise, if source is in WORKDATREGS, put it in work reg not OPREG */ /* also assign a work reg if source is already in OPREG and target needs one */ regpushed = (regmark = reguse) & OPREG; workreg = OPREG; if ((sscalar & CHAR && target->storage & WORKDATREGS && source->storage == OPREG && source->indcount != 0) || ((sscalar & CHAR || source->storage & WORKDATREGS) && target->storage == OPREG && target->indcount != 0) || #ifdef MC6809 /* for -Wall */ ( #endif (source->storage == OPREG && target->storage == GLOBAL && target->indcount == 0) #ifdef MC6809 && posindependent) #endif ) { if ((regmark | OPREG) == allindregs) regpushed |= (workreg = OPWORKREG); else { reguse |= OPREG; workreg = getindexreg(); } } pushlist(regpushed); /* no more pushes */ reguse = allindregs; /* error if another reg unexpectedly needed */ if (sscalar & CHAR) { if (target->storage & WORKDATREGS) { extend(target); if (source->storage == workreg) exchange(source, target); else transfer(target, workreg); } extend(source); if (target->storage != OPREG && (target->storage != GLOBAL || target->indcount != 0 #ifdef MC6809 || !posindependent #endif )) workreg = OPREG; } if (source->storage & WORKDATREGS) { if (target->storage == OPREG && target->indcount == 0) exchange(source, target); else { transfer(source, workreg); workreg = OPREG; } } if (target->storage == GLOBAL && target->indcount == 0 #ifdef MC6809 && posindependent #endif ) load(target, workreg); /* source and target now in position to be loaded without any more registers */ extend(target); load(target, DREG); #if defined(I8088) if ((op_t) op != DIVOP && (op_t) op != MODOP ) { load(source, DATREG1); /* CX */ switch ((op_t) op) { case MULOP: outop2str("imul\t"); outnregname(DATREG1); break; case SLOP: outop2str("shl\t"); outregname(DREG); outnstr(",cl"); break; case SROP: if (uflag) outop2str("shr\t"); else outop2str("sar\t"); outregname(DREG); outnstr(",cl"); break; } } else #endif { load(source, OPREG); switch ((op_t) op) { case DIVOP: #ifdef I8088 if (uflag) call("idiv_"); else { #ifdef I80386 if (i386_32) outnop1str("cdq"); else #endif outnop1str("cwd"); outop2str("idiv\t"); outregname(INDREG0); } #else call("idiv"); #endif break; case MODOP: call("imod"); break; case MULOP: #ifdef I8088 call("imul_"); #else call("imul"); #endif break; case SLOP: call("isl"); break; case SROP: call("isr"); break; } if (uflag) outbyte('u'); outnl(); } target->type = iscalartotype(resultscalar); poplist(regpushed); reguse = regmark; } dev86-0.16.17/bcc/preproc.c0000644000000000000000000005145207775363557015164 0ustar rootroot00000000000000/* preprocessor routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "input.h" #include "os.h" #include "output.h" #include "parse.h" #include "sc.h" #include "scan.h" #include "table.h" #include "type.h" /* blanksident() - return nonzero if at blanks followed by an identifier */ PUBLIC bool_pt blanksident() { blanks(); return isident(); } #ifdef BUILTIN_CPP #define MAX_IF 32 #define MAX__LINE__ 10 /* enough for 32-bit source unsigneds */ #define MAX_MACRO 32 #define MAX_PARAM 127 /* max char with no sign on all machines */ /* Definition types. These are kept in the 'storage' member of struct * symstruct and must be distinct from 'LOCAL' because dumplocs() doesn't * check. */ enum { DEF_LINE, /* __LINE__ keyword */ DEF_NONE /* nothing special */ }; struct ifstruct { bool_t elseflag; bool_t ifflag; }; struct macroposition { char *maclineptr; char **paramlist; char *paramspot; bool_t inparam; indn_t nparam; struct symstruct *symptr; }; PRIVATE char dummyparam[] = { EOL, 0 }; PRIVATE fastin_t iflevel; /* depends on zero init */ PRIVATE struct ifstruct ifstate; /* elseflag depends on zero init */ PRIVATE struct ifstruct ifstack[MAX_IF]; PRIVATE struct macroposition macrostack[MAX_MACRO]; FORWARD void asmcontrol P((void)); FORWARD void warningcntl P((void)); FORWARD void errorcntl P((void)); FORWARD void control P((void)); FORWARD void defineorundefinestring P((char *str, bool_pt defineflag)); FORWARD void elifcontrol P((void)); FORWARD void elsecontrol P((void)); FORWARD void endif P((void)); FORWARD fastin_pt getparnames P((void)); FORWARD void ifcontrol P((sym_pt ifcase)); FORWARD void undef P((void)); /* asmcontrol() - process #asm */ PRIVATE void asmcontrol() { #ifdef ASM_BARE char treasure; /* to save at least one leading blank */ #endif asmmode = TRUE; if (expect_statement) return; if (orig_cppmode) outnstr("#asm"); else { outnstr("!BCC_ASM"); dumplocs(); } #ifndef ASM_BARE cppscan(1); #else while (TRUE) { skipline(); skipeol(); if (eofile) { eofin("#asm"); break; } if (SYMOFCHAR(ch) == SPECIALCHAR) specialchar(); treasure = 0; if (SYMOFCHAR(ch) == WHITESPACE) treasure = ch; blanks(); if (ch == '#') { if (ctext) { register char *lptr; comment(); if (treasure != 0) outbyte(treasure); lptr = lineptr; while (*lptr++ != EOL) /* XXX - handle COEOL too */ outbyte(ch); outnl(); } gch1(); docontrol(); if (!asmmode) break; } else { if (treasure != 0) outbyte(treasure); while (ch != EOL) /* XXX - handle COEOL too */ { outbyte(ch); gch1(); } outnl(); } } #endif if (orig_cppmode) outnstr("#endasm"); else outnstr("!BCC_ENDASM"); } PUBLIC void checknotinif() { while (iflevel != 0) { if (ifstate.ifflag) eofin("true #conditional"); else eofin("false #conditional"); endif(); } } /* warningcntl() - process #warning */ PRIVATE void warningcntl() { char estr[256], *ep = estr; if (!orig_cppmode) { *ep++ = '%'; *ep++ = 'w'; } while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; if (!orig_cppmode) error(estr); else { outstr("#warning"); outnstr(estr); } } /* errorcntl() - process #error */ PRIVATE void errorcntl() { char estr[256], *ep = estr; while( ch != EOL ) { if (ep < estr+sizeof(estr)-2 ) *ep++ = ch; gch1(); } *ep = 0; if (!orig_cppmode) error(estr); else { outstr("#error"); outnstr(estr); } } /* control() - select and switch to control statement */ PRIVATE void control() { char sname[NAMESIZE + 1]; sym_t ctlcase; struct symstruct *symptr; if (ctext && asmmode) { comment(); outudec(input.linenumber); outbyte(' '); outline(lineptr); } sname[0] = '#'; /* prepare for bad control */ sname[1] = 0; while (blanksident()) { if ((gsymptr = findlorg(gsname)) == NULL || gsymptr->flags != DEFINITION) { strcat(sname, gsname); break; } entermac(); } if (sname[1] == 0 && ch == EOL) return; if (SYMOFCHAR(ch) == INTCONST) { linecontol(); return; } if ((symptr = findlorg(sname)) == NULL) { if (ifstate.ifflag) error(" bad control"); return; } ctlcase = symptr->offset.offsym; if (ifstate.ifflag == FALSE && (ctlcase < ELIFCNTL || ctlcase > IFNDEFCNTL)) return; switch (ctlcase) { case ASMCNTL: if (asmmode) { if (ifstate.ifflag) error(" bad control"); } else asmcontrol(); break; case DEFINECNTL: define(); break; case ELIFCNTL: elifcontrol(); break; case ELSECNTL: elsecontrol(); break; case ENDASMCNTL: if (!asmmode) { if (ifstate.ifflag) error(" bad control"); } asmmode = FALSE; break; case ENDIFCNTL: endif(); break; case IFCNTL: case IFDEFCNTL: case IFNDEFCNTL: ifcontrol(symptr->offset.offsym); break; case INCLUDECNTL: include(); break; case LINECNTL: { linecontol(); break; } case UNDEFCNTL: undef(); break; case WARNINGCNTL: warningcntl(); break; case ERRORCNTL: errorcntl(); break; } } /* define() - process #define */ /* MACRO storage. A symbol recording the macro name is added to the symbol table. This overrides all current scopes of the name (put at head of hash chain). The flags are set to DEFINITION. The indcount is 0 if no parameters, else 1 + number of parameters. The offset field points to the macro string. The macro string is null-terminated but EOL-sentineled. It consists of EOL-terminated substrings followed by parameter numbers, e.g., junk(x,y)=-x+y is stored as '-', EOL, 1, '+', EOL, 2, EOL, 0. Here 1 is for the 1st parameter (start at 1 so 0 can terminate). EOL acts as a sentinel for the scanner. This choice works well because EOL cannot occur in a macro string. */ PUBLIC void define() { char sname[NAMESIZE]; char quote; struct symstruct **hashptr; struct symstruct *locmark = NULL; /* for -Wall */ char *macstring; fastin_t nparnames; char *oldstring; struct symstruct *symptr; if (!blanksident()) { error("illegal macro name"); return; } strcpy(sname, gsname); /* will overwrite gsname if parameters */ if (ch == '(') { locmark = locptr; newlevel(); /* temp storage for parameter names */ nparnames = getparnames() + 1; } else nparnames = 0; blanks(); macstring = charptr; quote = 0; while (ch != EOL) { if (charptr >= char1top) /* check room for char and end of string */ macstring = growobject(macstring, 2); if (nparnames && isident()) { if ((symptr = findlorg(gsname)) != NULL && symptr->level == level) { #ifdef TS ++ts_n_macstring_param; ts_s_macstring += 2; #endif *charptr++ = EOL; /* end current string */ *charptr++ = symptr->indcount; /* param to insert */ } else { if (charptr + strlen(gsname) >= chartop) /* null too */ macstring = growobject(macstring, strlen(gsname) + 1); #ifdef TS ++ts_n_macstring_ident; ts_s_macstring += strlen(gsname);; #endif strcpy(charptr, gsname); charptr += strlen(gsname); /* discard null */ } continue; } if (ch == '\\') { gch1(); *charptr = '\\'; *(charptr + 1) = ch; #ifdef TS ++ts_n_macstring_quoted; ts_s_macstring += 2; #endif charptr += 2; gch1(); continue; } if (quote) { if (ch == quote) quote = 0; } else if (ch == '"' || ch == '\'') quote = ch; else if (ch == '/') { if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR) { gch1(); ch = *--lineptr = '/'; /* pushback */ } if (*(lineptr + 1) == '*') { gch1(); skipcomment(); #if 0 /* comment is space in modern cpp's but they have '##' too */ ch = *--lineptr = ' '; #else continue; #endif } } #ifdef TS ++ts_n_macstring_ordinary; ++ts_s_macstring; #endif *charptr++ = ch; gch1(); } { register char *rcp; /* strip trailing blanks, but watch out for parameters */ for (rcp = charptr; rcp > macstring && SYMOFCHAR(*(rcp - 1)) == WHITESPACE && (--rcp == macstring || *(rcp - 1) != EOL); ) charptr = rcp; } if (charptr+1 >= char1top) macstring = growobject(macstring, 3); #ifdef TS ++ts_n_macstring_term; ts_s_macstring += 3; #endif *charptr++ = ' '; /* Added to prevent tail recursion on expansion */ *charptr++ = EOL; *charptr++ = 0; if (nparnames) { oldlevel(); locptr = locmark; } /* if (asmmode) equ(sname, macstring); */ if ((symptr = findlorg(sname)) != NULL && symptr->flags == DEFINITION) { if (strcmp(macstring, oldstring = symptr->offset.offp) != 0) error("%wredefined macro"); if (strlen(macstring) > strlen(oldstring = symptr->offset.offp)) symptr->offset.offp = macstring; else { strcpy(oldstring, macstring); /* copy if == to avoid test */ charptr = macstring; } return; } symptr = qmalloc(sizeof (struct symstruct) + strlen(sname)); #ifdef TS ++ts_n_defines; ts_s_defines += sizeof (struct symstruct) + strlen(sname); #endif addsym(sname, vtype, symptr); symptr->storage = DEF_NONE; symptr->indcount = nparnames; symptr->flags = DEFINITION; symptr->level = GLBLEVEL; symptr->offset.offp = macstring; if (*(hashptr = gethashptr(sname)) != NULL) { symptr->next = *hashptr; symptr->next->prev = &symptr->next; } *hashptr = symptr; symptr->prev = hashptr; } PRIVATE void defineorundefinestring(str, defineflag) char *str; /* "name[=def]" or "name def" */ bool_pt defineflag; { char *fakeline; unsigned len; bool_t old_eof; len = strlen(str); strcpy(fakeline = (char *) ourmalloc(3 + len + 2 + 2) + 3, str); /* 3 pushback, 2 + 2 guards */ #ifdef TS ts_s_fakeline += 3 + len + 2 + 2; ts_s_fakeline_tot += 3 + len + 2 + 2; #endif { register char *endfakeline; endfakeline = fakeline + len; endfakeline[0] = EOL; /* guards any trailing backslash */ endfakeline[1] = EOL; /* line ends here or before */ } old_eof = eofile; eofile = TRUE; /* valid after first EOL */ ch = *(lineptr = fakeline); if (defineflag) { if (blanksident()) /* if not, let define() produce error */ { blanks(); if (ch == '=') *lineptr = ' '; else if (ch == EOL) { register char *lptr; lptr = lineptr; lptr[0] = ' '; lptr[1] = '1'; /* 2 extra were allocated for this & EOL */ lptr[2] = EOL; } } ch = *(lineptr = fakeline); define(); } else undef(); eofile = old_eof; #ifdef TS ts_s_fakeline_tot -= len + 2 + 2; #endif ourfree(fakeline - 3); } PUBLIC void definestring(str) char *str; /* "name[=def]" or "name def" */ { defineorundefinestring(str, TRUE); } /* docontrol() - process control statement, loop till "#if" is true */ PUBLIC void docontrol() { while (TRUE) { control(); skipline(); if (ifstate.ifflag) return; while (TRUE) { skipeol(); if (eofile) return; blanks(); if (ch == '#') { gch1(); break; } skipline(); } } } /* elifcontrol() - process #elif */ PRIVATE void elifcontrol() { if (iflevel == 0) { error("elif without if"); return; } if (ifstate.elseflag) { register struct ifstruct *ifptr; ifptr = &ifstack[(int)--iflevel]; ifstate.elseflag = ifptr->elseflag; ifstate.ifflag = ifptr->ifflag; ifcontrol(IFCNTL); } else { ifstate.ifflag = ifstate.elseflag; ifstate.elseflag = FALSE; } } /* elsecontrol() - process #else */ PRIVATE void elsecontrol() { if (iflevel == 0) { error("else without if"); return; } ifstate.ifflag = ifstate.elseflag; ifstate.elseflag = FALSE; } /* endif() - process #endif */ PRIVATE void endif() { if (iflevel == 0) { error("endif without if"); return; } { register struct ifstruct *ifptr; ifptr = &ifstack[(int)--iflevel]; ifstate.elseflag = ifptr->elseflag; ifstate.ifflag = ifptr->ifflag; } } /* entermac() - switch line ptr to macro string */ PUBLIC void entermac() { char quote; struct symstruct *symptr; char **paramhead; char **paramlist; int ngoodparams; int nparleft; int lpcount; if (maclevel >= MAX_MACRO) { limiterror("macros nested too deeply (33 levels)"); return; } symptr = gsymptr; symptr->name.namea[0] |= 0x80; /* SMUDGE macro definition */ ngoodparams = 0; paramhead = NULL; if (symptr->indcount != 0) { nparleft = symptr->indcount - 1; if (nparleft == 0) paramhead = NULL; else paramhead = ourmalloc(sizeof *paramlist * nparleft); paramlist = paramhead; #ifdef TS ++ts_n_macparam; ts_s_macparam += sizeof *paramlist * nparleft; ts_s_macparam_tot += sizeof *paramlist * nparleft; #endif blanks(); while (ch == EOL && !eofile) { skipeol(); blanks(); } if (ch != '(') { if (nparleft > 0) /* macro has params, doesn't match bare word */ { symptr->name.namea[0] &= 0x7f; /* UnSMUDGE macro definition */ outstr(symptr->name.namea); return; } error("missing '('"); } else { gch1(); while (nparleft) { --nparleft; ++ngoodparams; *(paramlist++) = charptr; quote = 0; lpcount = 1; while (TRUE) { if (ch == '\\') { gch1(); if (charptr >= char1top) *(paramlist - 1) = growobject(*(paramlist - 1), 2); #ifdef TS ++ts_n_macparam_string_quoted; ++ts_s_macparam_string; ++ts_s_macparam_string_tot; #endif *charptr++ = '\\'; } else if (quote) { if (ch == quote) quote = 0; } else if (ch == '"' || ch == '\'') quote = ch; else if (ch == '/') { if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR) { gch1(); ch = *--lineptr = '/'; /* pushback */ } if (*(lineptr + 1) == '*') { gch1(); skipcomment(); ch = *--lineptr = ' '; /* pushback */ } } else if (ch == '(') ++lpcount; else if ((ch == ')' && --lpcount == 0) || (ch == ',' && lpcount == 1)) break; if (ch == EOL) ch = ' '; if (charptr >= char1top) *(paramlist - 1) = growobject(*(paramlist - 1), 2); #ifdef TS ++ts_n_macparam_string_ordinary; ++ts_s_macparam_string; ++ts_s_macparam_string_tot; #endif *charptr++ = ch; if (*lineptr == EOL) { skipeol(); /* macro case disposed of already */ if (SYMOFCHAR(ch) == SPECIALCHAR) specialchar(); if (eofile) break; } else gch1(); } #ifdef TS ++ts_n_macparam_string_term; ++ts_s_macparam_string; ++ts_s_macparam_string_tot; #endif *charptr++ = EOL; { register char *newparam; register char *oldparam; unsigned size; oldparam = *(paramlist - 1); size = (/* size_t */ unsigned) (charptr - oldparam); newparam = ourmalloc(size); #ifdef TS ts_s_macparam_string_alloced += size; ts_s_macparam_string_alloced_tot += size; #endif memcpy(newparam, oldparam, size); *(paramlist - 1) = newparam; #ifdef TS ts_s_macparam_string_tot -= charptr - oldparam; #endif charptr = oldparam; } if (ch == ',') gch1(); else break; } } blanks(); while (ch == EOL && !eofile) { skipeol(); blanks(); } if (eofile) eofin("macro parameter expansion"); if (nparleft) { error("too few macro parameters"); do *(paramlist++) = dummyparam; while (--nparleft); } if (ch == ')') gch1(); else if (ch == ',') { error("too many macro parameters"); /* XXX - should read and discard extra parameters. Also check * for eof at end. */ while (ch != ')') { if (ch == EOL) { skipeol(); if (eofile) break; continue; } gch1(); } } else error("missing ')'"); } if (symptr->storage == DEF_LINE) { char *str; str = pushudec(symptr->offset.offp + MAX__LINE__, input.linenumber); memcpy(symptr->offset.offp, str, /* size_t */ (unsigned) (symptr->offset.offp + MAX__LINE__ + 1 + 1 - str)); } { register struct macroposition *mpptr; mpptr = ¯ostack[maclevel]; mpptr->paramlist = paramhead; mpptr->maclineptr = lineptr; ch = *(lineptr = symptr->offset.offp); mpptr->inparam = FALSE; mpptr->nparam = ngoodparams; mpptr->symptr = symptr; mpptr->symptr->name.namea[0] |= 0x80; /* SMUDGE macro definition */ ++maclevel; } /* comment(); outstr("MACRO (level "); outudec((unsigned) maclevel); outstr(") "); outline(lineptr); */ } /* getparnames() - get parameter names during macro definition, return count */ PRIVATE fastin_pt getparnames() { fastin_t nparnames; struct symstruct *symptr; nparnames = 0; gch1(); while (blanksident()) { if ((symptr = findlorg(gsname)) != NULL && symptr->level == level) error("repeated parameter"); symptr = addloc(gsname, itype); if (nparnames >= MAX_PARAM) limiterror("too many macro parameters (128)"); else ++nparnames; /* number params from 1 */ symptr->indcount = nparnames; /* param number */ blanks(); if (ch == ',') gch1(); } if (ch != ')') error("missing ')'"); else gch1(); return nparnames; } /* ifcontrol - process #if, #ifdef, #ifndef */ PRIVATE void ifcontrol(ifcase) sym_pt ifcase; { bool_t iftrue; struct symstruct *symptr; if (iflevel >= MAX_IF) { limiterror("#if's nested too deeply (33 levels)"); return; } { register struct ifstruct *ifptr; ifptr = &ifstack[(int)iflevel++]; ifptr->elseflag = ifstate.elseflag; ifptr->ifflag = ifstate.ifflag; ifstate.elseflag = FALSE; /* prepare for !(if now)||(if future)*/ } if (ifstate.ifflag) { if ((sym_t) ifcase != IFCNTL) { iftrue = FALSE; if (blanksident() && (symptr = findlorg(gsname)) != NULL && symptr->flags == DEFINITION) iftrue = TRUE; } else { incppexpr = TRUE; nextsym(); iftrue = constexpression() != 0; incppexpr = FALSE; } if ((!iftrue && (sym_t) ifcase != IFNDEFCNTL) || (iftrue && (sym_t) ifcase == IFNDEFCNTL)) { ifstate.elseflag = TRUE; ifstate.ifflag = FALSE; } } } /* ifinit() - initialise if state */ PUBLIC void ifinit() { ifstate.ifflag = TRUE; } PUBLIC int ifcheck() { return (ifstate.ifflag == TRUE); } /* leavemac() - leave current and further macro substrings till not at end */ PUBLIC void leavemac() { register struct macroposition *mpptr; do { mpptr = ¯ostack[maclevel - 1]; if (mpptr->inparam) { lineptr = ++mpptr->paramspot; mpptr->inparam = FALSE; } else { mpptr->symptr->name.namea[0] &= 0x7F;/* UnSMUDGE macro definition */ ch = *++lineptr; /* gch1() would mess up next param == EOL-1 */ if (ch != 0) { mpptr->paramspot = lineptr; lineptr = mpptr->paramlist[ch - 1]; mpptr->inparam = TRUE; } else { lineptr = mpptr->maclineptr; if (mpptr->nparam != 0) { register char **paramlist; #ifdef TS ts_s_macparam_tot -= sizeof *paramlist * mpptr->nparam; #endif paramlist = mpptr->paramlist; do { #ifdef TS ts_s_macparam_string_alloced_tot -= strchr(*paramlist, EOL) - *paramlist + 1; #endif ourfree(*paramlist++); } while (--mpptr->nparam != 0); ourfree(mpptr->paramlist); } --maclevel; } } } while ((ch = *lineptr) == EOL && maclevel != 0); } PUBLIC void predefine() { definestring("__BCC__ 1"); definestring("__LINE__ 0123456789"); /* MAX__LINE__ digits */ findlorg("__LINE__")->storage = DEF_LINE; } PUBLIC char *savedlineptr() { return macrostack[0].maclineptr; } PUBLIC void skipcomment() { /* Skip current char, then everything up to '*' '/' or eof. */ gch1(); do { while (TRUE) { { register char *reglineptr; reglineptr = lineptr; symofchar['*'] = SPECIALCHAR; while (SYMOFCHAR(*reglineptr) != SPECIALCHAR) ++reglineptr; symofchar['*'] = STAR; lineptr = reglineptr; if (*reglineptr == '*') break; ch = *reglineptr; } specialchar(); if (ch == EOL) { skipeol(); if (eofile) break; } else if (ch != '*') gch1(); } gch1(); if (eofile) { eofin("comment"); return; } } while (ch != '/'); gch1(); } /* skipline() - skip rest of line */ PUBLIC void skipline() { while (TRUE) { blanks(); if (ch == EOL) return; if (ch == '\\') { gch1(); if (ch == EOL) /* XXX - I think blanks() eats \EOL */ return; gch1(); /* XXX - escape() better? */ } else if (ch == '"' || ch == '\'') { stringorcharconst(); charptr = constant.value.s; } else gch1(); } } /* undef() - process #undef */ PRIVATE void undef() { struct symstruct *symptr; if (blanksident() && (symptr = findlorg(gsname)) != NULL && symptr->flags == DEFINITION) delsym(symptr); } PUBLIC void undefinestring(str) char *str; { defineorundefinestring(str, FALSE); } #endif dev86-0.16.17/bcc/proto.h0000644000000000000000000002776610065301261014637 0ustar rootroot00000000000000/* proto.h - extern functions for bcc */ /* Copyright (C) 1992 Bruce Evans */ /* assign.c */ void assign P((struct symstruct *source, struct symstruct *target)); void cast P((struct typestruct *type, struct symstruct *target)); void extend P((struct symstruct *target)); /* codefrag.c */ void adjsp P((label_no label)); void clrBreg P((void)); void comment P((void)); void ctoi P((void)); void defbyte P((void)); void deflong P((uoffset_T value)); void defword P((void)); void defdword P((void)); void even P((void)); void negDreg P((void)); void comDreg P((void)); void outadd P((void)); void outaddsp P((void)); void outcalladr P((void)); void outcmp P((void)); void outdec P((void)); void outdword P((void)); void outfail P((void)); void outinc P((void)); void outindleft P((void)); void outindright P((void)); void outindstackreg P((void)); void outldaccum P((void)); void outldmulreg P((void)); void outlea P((void)); void outleasp P((void)); void outload P((void)); void outmulmulreg P((void)); void outopsep P((void)); void outpshs P((void)); void outpuls P((void)); void outreturn P((void)); void outstore P((void)); void outsub P((void)); void outtest P((void)); void outword P((void)); void sctoi P((void)); void stoi P((void)); void ustoi P((void)); void outABX P((void)); void outdirectpage P((void)); void outextended P((void)); void outncspregname P((void)); void outindframereg P((void)); void adc0 P((void)); void addconst P((offset_T offset, store_pt reg)); void adjlc P((offset_T offset, store_pt reg)); void andconst P((offset_T offset)); void bssseg P((void)); label_no casejump P((void)); void common P((char *name)); void cseg P((void)); void defnulls P((uoffset_T nullcount)); label_no defstr P((char *sptr, char *stop, bool_pt dataflag)); bool_pt diveasy P((value_t divisor, bool_pt uflag)); void dpseg P((void)); void dseg P((void)); void equ P((char *name, char *string)); void equlab P((label_no label, offset_T offset)); void globl P((char *name)); void import P((char *name)); void itol P((store_pt reg)); void lcommlab P((label_no label)); void lcommon P((char *name)); void lea P((offset_T offset, store_pt sourcereg, store_pt targreg)); void loadconst P((offset_T offset, store_pt reg)); int lslconst P((value_t shift, store_pt reg)); int lsrconst P((value_t shift, store_pt reg, bool_pt uflag)); bool_pt modeasy P((value_t divisor, bool_pt uflag)); bool_pt muleasy P((uvalue_t factor, store_pt reg)); void negreg P((store_pt reg)); char *opstring P((op_pt op)); void outccname P((char *name)); void outhiaccum P((void)); void outimmadr P((offset_T offset)); void outimadj P((offset_T offset, store_pt targreg)); void outimmed P((void)); void outjumpstring P((void)); void outnccname P((char *name)); void outncimmadr P((offset_T offset)); void outoffset P((offset_T offset)); void public P((char *name)); void private P((char *name)); void regexchange P((store_pt sourcereg, store_pt targreg)); void regtransfer P((store_pt sourcereg, store_pt targreg)); void sbc0 P((void)); void set P((char *name, offset_T value)); void sl1 P((store_pt reg)); void slconst P((value_t shift, store_pt reg)); void srconst P((value_t shift, bool_pt uflag)); void uitol P((store_pt reg)); void restoreopreg P((void)); void saveopreg P((void)); /* dbnode.c */ void dbitem P((struct symstruct *item)); void dbtype P((struct typestruct *type)); void dbnode P((struct nodestruct *exp)); void dbnodeswap P((void)); /* declare.c */ void colon P((void)); void decllist P((void)); void lparen P((void)); void needvarname P((void)); void program P((void)); void rbrace P((void)); void rbracket P((void)); void rparen P((void)); void semicolon P((void)); struct typestruct *typename P((void)); /* express.c */ struct nodestruct *assignment_exp P((void)); struct nodestruct *expression P((void)); /* exptree.c */ struct nodestruct *castnode P((struct typestruct *type, struct nodestruct *nodeptr)); void etreeinit P((void)); struct nodestruct *leafnode P((struct symstruct *source)); struct nodestruct *node P((op_pt t, struct nodestruct *p1, struct nodestruct *p2)); /* floatop.c */ bool_pt f_indirect P((struct symstruct *target)); void float1op P((op_pt op, struct symstruct *source)); void floatop P((op_pt op, struct symstruct *source, struct symstruct *target)); void fpush P((struct symstruct *source)); void justpushed P((struct symstruct *target)); /* function.c */ void call P((char *name)); void function P((struct symstruct *source)); void ldregargs P((void)); void loadretexpression P((void)); void listo P((struct symstruct *target, offset_T lastargsp)); void listroot P((struct symstruct *target)); void popframe P((void)); void reslocals P((void)); void ret P((void)); /* gencode.c */ void bileaf P((struct nodestruct *exp)); fastin_pt bitcount P((uvalue_t number)); void codeinit P((void)); fastin_pt highbit P((uvalue_t number)); void makeleaf P((struct nodestruct *exp)); /* genloads.c */ void addoffset P((struct symstruct *source)); void address P((struct symstruct *source)); void exchange P((struct symstruct *source, struct symstruct *target)); store_pt getindexreg P((void)); void indexadr P((struct symstruct *source, struct symstruct *target)); void indirec P((struct symstruct *source)); void load P((struct symstruct *source, store_pt targreg)); void loadany P((struct symstruct *source)); void loadreg P((struct symstruct *source, store_pt targreg)); void makelessindirect P((struct symstruct *source)); void movereg P((struct symstruct *source, store_pt targreg)); void onstack P((struct symstruct *target)); void outadr P((struct symstruct *adr)); void outcregname P((store_pt reg)); void outncregname P((store_pt reg)); void outnregname P((store_pt reg)); void outregname P((store_pt reg)); void outshortregname P((store_pt reg)); void pointat P((struct symstruct *target)); void poplist P((store_pt reglist)); void push P((struct symstruct *source)); void pushlist P((store_pt reglist)); void pushreg P((store_pt reg)); void storereg P((store_pt sourcereg, struct symstruct *target)); void struc P((struct symstruct *source, struct symstruct *target)); void transfer P((struct symstruct *source, store_pt targreg)); /* glogcode.c */ void cmp P((struct symstruct *source, struct symstruct *target, ccode_t *pcondtrue)); void condop P((struct nodestruct *exp)); void jumpfalse P((struct nodestruct *exp, label_no label)); void jumptrue P((struct nodestruct *exp, label_no label)); void logop P((struct nodestruct *exp)); /* hardop.c */ void add P((struct symstruct *source, struct symstruct *target)); void incdec P((op_pt op, struct symstruct *source)); void neg P((struct symstruct *target)); void not P((struct symstruct *target)); void op1 P((op_pt op, struct symstruct *source, struct symstruct *target)); void ptrsub P((struct symstruct *source, struct symstruct *target)); void sub P((struct symstruct *source, struct symstruct *target)); /* input.c */ void closein P((void)); void errorloc P((void)); void gch1 P((void)); void include P((void)); void openio P((int argc, char **argv)); void skipeol P((void)); void specialchar P((void)); void linecontol P((void)); /* label.c */ void bumplc P((void)); void bumplc2 P((void)); void bumplc3 P((void)); void clearfunclabels P((void)); void clearlabels P((char *patchbuf, char *patchtop)); void clearswitchlabels P((void)); uoffset_T getlc P((void)); void deflabel P((label_no label)); label_no gethighlabel P((void)); label_no getlabel P((void)); void jump P((label_no label)); void lbranch P((ccode_pt cond, label_no label)); struct symstruct *namedlabel P((void)); void outcond P((ccode_pt cond)); void outlabel P((label_no label)); void outnlabel P((label_no label)); void sbranch P((ccode_pt cond, label_no label)); void unbumplc P((void)); /* loadexp.c */ value_t constexpression P((void)); void initexpression P((struct typestruct *type)); struct typestruct *loadexpression P((store_pt targreg, struct typestruct *targtype)); /* longop.c */ void longop P((op_pt op, struct symstruct *source, struct symstruct *target)); void long1op P((op_pt op, struct symstruct *target)); void outlongendian P((void)); /* output.c */ void bugerror P((char *message)); void closeout P((void)); void error P((char *message)); void error2error P((char *message1, char *message2)); void fatalerror P((char *message)); void finishup P((void)); void flushout P((void)); void limiterror P((char *message)); void initout P((void)); void openout P((char *oname)); void outbyte P((int ch)); void outcomma P((void)); void outcpplinenumber P((unsigned nr, char *fname, char *str)); void outhex P((uoffset_T num)); void outhexdigs P((uoffset_T num)); void outline P((char *s)); void outminus P((void)); void outnl P((void)); void outnbyte P((int byte)); void outnhex P((uoffset_T num)); void outnop1str P((char *s)); void outnop2str P((char *s)); void outnstr P((char *s)); void outop0str P((char *s)); void outop1str P((char *s)); void outop2str P((char *s)); void outop3str P((char *s)); void outplus P((void)); void outshex P((offset_T num)); void outstr P((char *s)); void outtab P((void)); void outudec P((unsigned num)); #ifndef I8088 void outuvalue P((uvalue_t num)); void outvalue P((value_t num)); #endif char *pushudec P((char *s, unsigned num)); void setoutbufs P((void)); /* preproc.c */ void blanks P((void)); bool_pt blanksident P((void)); void checknotinif P((void)); void define P((void)); void definestring P((char *str)); void docontrol P((void)); void entermac P((void)); void ifinit P((void)); int ifcheck P((void)); void leavemac P((void)); void predefine P((void)); char *savedlineptr P((void)); void skipcomment P((void)); void skipline P((void)); void undefinestring P((char *str)); /* preserve.c */ void changesp P((offset_T newsp, bool_pt absflag)); void loadpres P((struct symstruct *source, struct symstruct *target)); void modstk P((offset_T newsp)); void pres2 P((struct symstruct *source, struct symstruct *target)); void preserve P((struct symstruct *source)); store_pt preslval P((struct symstruct *source, struct symstruct *target)); void recovlist P((store_pt reglist)); void savereturn P((store_pt savelist, offset_T saveoffset)); /* sc.c */ int main P((int argc, char **argv)); /* scan.c */ void cppscan P((int asmonly)); void eofin P((char *message)); bool_pt isident P((void)); void nextsym P((void)); void stringorcharconst P((void)); /* softop.c */ void softop P((op_pt op, struct symstruct *source, struct symstruct *target)); /* state.c */ void compound P((void)); void outswoffset P((offset_T offset)); void outswstacklab P((void)); void doasm P((void)); /* table.c */ struct symstruct *addglb P((char *name, struct typestruct *type)); struct symstruct *addloc P((char *name, struct typestruct *type)); struct symstruct *addlorg P((char *name, struct typestruct *type)); void addsym P((char *name, struct typestruct *type, struct symstruct *symptr)); struct symstruct *constsym P((value_t intconst)); void delsym P((struct symstruct *symptr)); void dumpglbs P((void)); void dumplocs P((void)); void dumpstrings P((void)); struct symstruct *exprsym P((struct symstruct *symptr)); struct symstruct *findlorg P((char *name)); struct symstruct *findstruct P((char *name)); struct symstruct **gethashptr P((char *sname)); void growheap P((unsigned size)); void *growobject P((void *object, unsigned extra)); label_no holdstr P((char *sptr, char *stop)); void newlevel P((void)); void oldlevel P((void)); void ourfree P((void *ptr)); void *ourmalloc P((unsigned nbytes)); void outofmemoryerror P((char *message)); void *qmalloc P((unsigned size)); void swapsym P((struct symstruct *sym1, struct symstruct *sym2)); void syminit P((void)); /* type.c */ struct typestruct *addstruct P((char *structname)); struct typestruct *iscalartotype P((scalar_pt scalar)); struct typestruct *newtype P((void)); void outntypechar P((struct typestruct *type)); struct typestruct *pointype P((struct typestruct *type)); struct typestruct *prefix P((constr_pt constructor, uoffset_T size, struct typestruct *type)); struct typestruct *promote P((struct typestruct *type)); struct typestruct *tosigned P((struct typestruct *type)); struct typestruct *tounsigned P((struct typestruct *type)); void typeinit P((void)); dev86-0.16.17/bcc/input.h0000644000000000000000000000252110065244336014622 0ustar rootroot00000000000000/* input.h - input for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define FAKE_INBUFSIZE_1_NOT #ifdef FAKE_INBUFSIZE_1 #include FILE *fdopen(); #endif struct fcbstruct /* file control block structure */ { fd_t fd; /* file descriptor */ #ifdef FAKE_INBUFSIZE_1 FILE *fp; #endif unsigned linenumber; /* current line in file */ int lineoffset; /* offset to start of current line in buf */ char *lineptr; /* current spot in line */ char *limit; /* end of used part of input buffer */ struct fbufstruct *includer; /* buffer of file which included current one */ }; EXTERN bool_t asmmode; /* nonzero when processing assembler code */ /* depends on zero init */ EXTERN char ch; /* current char */ EXTERN bool_t eofile; /* nonzero after end of main file reached */ /* depends on zero init */ EXTERN struct fcbstruct input; /* current input file control block */ /* input.lineptr is not kept up to date */ EXTERN char *lineptr; /* ptr to current char */ #ifdef BUILTIN_CPP EXTERN bool_t cppmode; /* nonzero if acting as cpp not as compiler */ EXTERN maclev_t maclevel; /* nest level of #defined identifiers */ /* depends on zero init */ EXTERN bool_t orig_cppmode; /* same as cppmode ex. not varied while in # */ EXTERN bool_t virtual_nl; /* For -C and asm, don't print first nl */ #endif dev86-0.16.17/bcc/gencode.c0000644000000000000000000004127410065301114015056 0ustar rootroot00000000000000/* gencode.c - generate code for an expression tree for bcc */ /* Copyright (C) 1992 Bruce Evans */ #define islvalop(op) \ (((op) >= ASSIGNOP && (op) <= SUBABOP) || (op) == PTRADDABOP) #include "bcc.h" #include "align.h" #include "condcode.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "type.h" #undef EXTERN #define EXTERN #include "gencode.h" #include "sizes.h" #define FIRSTOPDATA GTOP #if MAXINDIRECT <= 1 # define istooindirect(t) ((t)->indcount > MAXINDIRECT) #else # define istooindirect(t) ((t)->indcount >= MAXINDIRECT && \ ((t)->indcount > MAXINDIRECT || \ (t)->type->typesize > maxregsize || \ (t)->type->constructor & FUNCTION)) #endif #ifdef I8088 #if NOTFINISHED PUBLIC store_pt allregs = BREG | DREG | DATREG1 | DATREG2 | INDREG0 | INDREG1 | INDREG2; #else PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2; #endif PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2; PUBLIC uoffset_T alignmask = ~(uoffset_T) 0x0001; PUBLIC bool_t arg1inreg = FALSE; PUBLIC store_pt calleemask = INDREG1 | INDREG2; PUBLIC bool_t callersaves = FALSE; PUBLIC char *callstring = "call\t"; PUBLIC store_pt doubleargregs = DREG | INDREG0 | DATREG1 | DATREG2; PUBLIC store_pt doubleregs = DREG | INDREG0 | DATREG1 | DATREG2; PUBLIC store_pt doublreturnregs = DREG | INDREG0 | DATREG1 | DATREG2; PUBLIC offset_T jcclonger = 3; PUBLIC offset_T jmplonger = 1; PUBLIC char *jumpstring = "br \t"; PUBLIC char *regpulllist = "f2ax2ax2bx2si2di2bp2qx2qx2cx2dx2"; PUBLIC char *regpushlist = "dx2cx2qx2qx2bp2di2si2bx2ax2ax2f2"; #if NOTFINISHED PUBLIC store_pt regregs = INDREG1 | INDREG2 | DATREG1 | DATREG2; #else PUBLIC store_pt regregs = INDREG1 | INDREG2; #endif PUBLIC char *acclostr = "al"; PUBLIC char *accumstr = "ax"; PUBLIC char *badregstr = "qx"; PUBLIC char *dreg1str = "cx"; PUBLIC char *dreg1bstr = "cl"; PUBLIC char *dreg2str = "dx"; PUBLIC char *ireg0str = "bx"; PUBLIC char *ireg1str = "si"; PUBLIC char *ireg2str = "di"; #ifdef FRAMEPOINTER PUBLIC char *localregstr = "bp"; #else PUBLIC char *localregstr = "sp"; #endif PUBLIC char *stackregstr = "sp"; #endif #ifdef MC6809 PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2; PUBLIC uoffset_T alignmask = ~(uoffset_T) 0x0000; PUBLIC bool_t arg1inreg = TRUE; PUBLIC store_pt calleemask = INDREG1 | INDREG2; PUBLIC bool_t callersaves = TRUE; PUBLIC char *callstring = "JSR\t>"; PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2; PUBLIC offset_T jcclonger = 2; PUBLIC offset_T jmplonger = 1; PUBLIC char *jumpstring = "JMP\t>"; PUBLIC char *regpulllist = "CC1B1D2X2U2Y2DP1PC2"; PUBLIC char *regpushlist = "PC2DP1Y2U2X2D2B1CC1"; PUBLIC store_pt regregs = INDREG1 | INDREG2; PUBLIC char *acclostr = "B"; PUBLIC char *accumstr = "D"; PUBLIC char *badregstr = "Q"; PUBLIC char *ireg0str = "X"; PUBLIC char *ireg1str = "U"; PUBLIC char *ireg2str = "Y"; PUBLIC char *localregstr = "S"; #endif PUBLIC uoffset_T accregsize = 2; #ifdef FRAMEPOINTER PUBLIC uoffset_T frameregsize = 2; #endif PUBLIC uoffset_T maxregsize = 2; PUBLIC uoffset_T opregsize = 2; PUBLIC uoffset_T pshregsize = 2; PUBLIC uoffset_T returnadrsize = 2; #ifndef MC6809 PUBLIC uvalue_t intmaskto = 0xFFFFL; PUBLIC uvalue_t maxintto = 0x7FFFL; PUBLIC uvalue_t maxlongto = 0x7FFFFFFFL; PUBLIC uvalue_t maxoffsetto = 0x7FFFL; PUBLIC uvalue_t maxshortto = 0x7FFFL; PUBLIC uvalue_t maxuintto = 0xFFFFL; PUBLIC uvalue_t maxushortto = 0xFFFFL; PUBLIC uvalue_t shortmaskto = 0xFFFFL; #endif PRIVATE store_pt callermask; PRIVATE offset_T lastargsp; PRIVATE smalin_t opdata[] = { /* GTOP, LTOP, ADDOP, DIVOP, */ GT, LT, 0, 0, /* MODOP, LOGNOTOP, NOTOP, STRUCELTOP, */ 0, 0, 0, 0, /* STRUCPTROP, ASSIGNOP, ADDABOP, ANDABOP, */ 0, 0, 0, ANDOP, /* DIVABOP, EORABOP, MODABOP, MULABOP, */ DIVOP, EOROP, MODOP, MULOP, /* ORABOP, SLABOP, SRABOP, SUBABOP, */ OROP, SLOP, SROP, 0, /* COMMAOP, COLONOP, LOGOROP, LOGANDOP, */ 0, 0, 0, 0, /* EQOP, NEOP, GEOP, LEOP, */ EQ, NE, GE, LE, }; FORWARD void abop P((op_pt op, struct symstruct *source, struct symstruct *target)); FORWARD void smakeleaf P((struct nodestruct *exp)); FORWARD void tcheck P((struct nodestruct *exp)); PRIVATE void abop(op, source, target) op_pt op; struct symstruct *source; struct symstruct *target; { store_pt regmark; store_pt regpushed; store_pt regtemp; struct symstruct temptarg; regpushed = preslval(source, target); temptarg = *target; if ((source->type->scalar ^ target->type->scalar) & (DLONG | RSCALAR) && op != SLABOP && op != SRABOP) /* XXX - perhaps not float */ { pres2(target, source); cast(source->type, &temptarg); } switch (op) { case ADDABOP: add(source, &temptarg); break; case ANDABOP: case EORABOP: case ORABOP: op1((opdata - FIRSTOPDATA)[op], source, &temptarg); break; case DIVABOP: case MODABOP: case MULABOP: case SLABOP: case SRABOP: softop((opdata - FIRSTOPDATA)[op], source, &temptarg); break; case PTRADDABOP: regtemp = 0; if ((reguse & allindregs) == allindregs) { /* free a temporary index not used for source or target */ regmark = reguse; reguse = source->storage | temptarg.storage; pushreg(regtemp = getindexreg()); reguse = regmark & ~regtemp; } indexadr(source, &temptarg); if (regtemp) { load(&temptarg, DREG); recovlist(regtemp); } break; case SUBABOP: sub(source, &temptarg); break; } assign(&temptarg, target); recovlist(regpushed); } PUBLIC void bileaf(exp) struct nodestruct *exp; { bool_t commutop; bool_t tookaddress; store_t regmark; struct nodestruct *indchase; struct nodestruct *left; struct nodestruct *right; struct symstruct *source; struct symstruct *target; left = exp->left.nodeptr; if ((right = exp->right) == NULL) { makeleaf(left); #ifdef DBNODE dbnode(exp); #endif return; } switch (exp->tag) { case ADDOP: case ANDOP: case EOROP: case OROP: case EQOP: case NEOP: case MULOP: commutop = TRUE; break; case FUNCOP: makeleaf(left); if ((target = left->left.symptr)->storage & allregs && right->tag != LEAF && target->flags != REGVAR) { if (target->indcount == 0) push(target); else { --target->indcount; push(target); ++target->indcount; } } default: commutop = FALSE; break; } regmark = reguse; if (right->tag != LEAF) { if (left->tag != LEAF && commutop && left->weight > right->weight) { exp->left.nodeptr = right; right = exp->right = left; left = exp->left.nodeptr; #ifdef DBNODE dbnodeswap(); #endif } makeleaf(right); } else if (left->tag != LEAF) makeleaf(left); source = right->left.symptr; if (left->tag != LEAF) { for (indchase = left; indchase->tag == INDIRECTOP || indchase->tag == STRUCELTOP; indchase = indchase->left.nodeptr) ; tookaddress = FALSE; if (source->storage & allindregs || indchase->tag != LEAF) { if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP) { address(source); tookaddress = TRUE; } if (source->storage & allindregs && source->indcount == 0 && (source->type->scalar & (DLONG | RSCALAR) || (left->tag == FUNCOP && source->flags != REGVAR))) push(source); /* XXX - perhaps not float */ else preserve(source); } makeleaf(left); if (tookaddress) indirec(source); } target = left->left.symptr; if (istooindirect(source)) { /* want to makelessindirect(source) */ /* this uses source->storage if that is a free index */ /* otherwise, must preserve target if that is an index */ tookaddress = FALSE; if (!(source->storage & ~reguse & allindregs) && target->storage & allindregs) { /* want to pres2(source, target) */ /* this requires target to be < MAXINDIRECT indirect */ /* it is safe to makelessindirect(target) */ /* since source is not a free index */ if (islvalop(exp->tag) && target->indcount != 0) { address(target); tookaddress = TRUE; } if (istooindirect(target)) makelessindirect(target); pres2(source, target); } makelessindirect(source); if (tookaddress) indirec(target); } if (istooindirect(target)) { tookaddress = FALSE; if (!(target->storage & ~reguse & allindregs) && source->storage & allindregs) { if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP) { address(source); tookaddress = TRUE; } pres2(target, source); } makelessindirect(target); if (tookaddress) indirec(source); } reguse = regmark; #ifdef DBNODE dbnode(exp); #endif if (commutop && ((target->storage == CONSTANT && !(target->type->scalar & (DLONG | RSCALAR))) || source->storage & ALLDATREGS || (source->type->scalar & (DLONG | RSCALAR) && source->indcount == 0 && target->indcount != 0))) { exp->left.nodeptr = right; exp->right = left; #ifdef DBNODE dbnodeswap(); #endif } } PUBLIC fastin_pt bitcount(number) register uvalue_t number; { register fastin_pt count; for (count = 0; number != 0; number >>= 1) if (number & 1) ++count; return count; } PUBLIC void codeinit() { #ifdef I80386 if (i386_32) { /* Need DATREG2 for doubles although handling of extra data regs is * not finished. * XXX - might need more regs for 16-bit mode doubles or floats. */ allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG1B | DATREG2; #if NOTFINISHED allindregs = INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG2; #else allindregs = INDREG0 | INDREG1 | INDREG2; #endif alignmask = ~(uoffset_T) 0x00000003; calleemask = INDREG0 | INDREG1 | INDREG2; doubleargregs = DREG | DATREG2; doubleregs = DREG | DATREG2; doublreturnregs = DREG | DATREG2; jcclonger = 4; jmplonger = 3; regpulllist = "fd4eax4eax4ebx4esi4edi4ebp4qx4qx4ecx4edx4"; regpushlist = "edx4ecx4qx4qx4ebp4edi4esi4ebx4eax4eax4fd4"; accumstr = "eax"; dreg1str = "ecx"; dreg2str = "edx"; ireg0str = "ebx"; ireg1str = "esi"; ireg2str = "edi"; #ifdef FRAMEPOINTER localregstr = "ebp"; #else localregstr = "esp"; #endif stackregstr = "esp"; opregsize = returnadrsize = pshregsize = maxregsize = #ifdef FRAMEPOINTER frameregsize = #endif accregsize = 4; intmaskto = (unsigned long) 0xFFFFFFFFL; maxintto = 0x7FFFFFFFL; maxoffsetto = 0x7FFFFFFFL; maxuintto = (unsigned long) 0xFFFFFFFFL; } #endif #ifdef POSINDEPENDENT if (posindependent) { # ifdef MC6809 callstring = "LBSR\t"; jumpstring = "LBRA\t"; # endif } #endif if (callersaves) calleemask = 0; callermask = ~calleemask; #ifdef FRAMEPOINTER funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize + frameregsize; funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs) * maxregsize + frameregsize; framelist = FRAMEREG | calleemask; #else funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize; funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs) * maxregsize; #endif } PUBLIC fastin_pt highbit(number) register uvalue_t number; { register fastin_pt bit; for (bit = -1; number != 0; number >>= 1) ++bit; return bit; } PUBLIC void makeleaf(exp) struct nodestruct *exp; { ccode_t condtrue; op_pt op; store_t regmark; offset_T saveargsp = 0; /* for -Wall */ store_t savelist = 0; /* for -Wall */ offset_T saveoffset = 0; /* for -Wall */ struct symstruct *source; offset_T spmark; struct symstruct *structarg = 0; /* for -Wall */ struct symstruct *target; if ((op_t) (op = exp->tag) == LEAF) { target = exp->left.symptr; if (istooindirect(target)) makelessindirect(target); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == INDIRECTOP || (op_t) op == STRUCELTOP) { smakeleaf(exp); target = exp->left.symptr; if (istooindirect(target)) makelessindirect(target); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == COMMAOP) { spmark = sp; makeleaf(exp->left.nodeptr); modstk(spmark); makeleaf(exp->right); exp->tag = LEAF; exp->left.symptr = exp->right->left.symptr; #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == CONDOP) { condop(exp); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } if ((op_t) op == LOGANDOP || (op_t) op == LOGNOTOP || (op_t) op == LOGOROP) { logop(exp); #ifdef SELFTYPECHECK tcheck(exp); #endif return; } regmark = reguse; if ((op_t) op == FUNCOP) { saveargsp = lastargsp; lastargsp = savelist = 0; if (exp->nodetype->constructor & STRUCTU) { modstk(sp - (offset_T) exp->nodetype->typesize); onstack(structarg = constsym((value_t) 0)); } else { if (exp->nodetype->scalar & DOUBLE) { if (regmark & doublreturnregs) savelist = doublreturnregs; } else if (regmark & RETURNREG) /* XXX size long == float ? */ savelist = exp->nodetype->scalar & DLONG ? LONGRETURNREGS : RETURNREG; if (savelist != 0) modstk(saveoffset = sp - exp->nodetype->typesize); } pushlist(regmark & callermask); } spmark = sp; bileaf(exp); if (exp->right != NULL) source = exp->right->left.symptr; else source = NULL; target = exp->left.nodeptr->left.symptr; switch ((op_t) op) { case ADDABOP: case ANDABOP: case DIVABOP: case EORABOP: case SUBABOP: case MODABOP: case MULABOP: case ORABOP: case PTRADDABOP: case SLABOP: case SRABOP: abop(op, source, target); break; case ADDOP: add(source, target); break; case ADDRESSOP: address(target); break; case ANDOP: case EOROP: case OROP: op1(op, source, target); break; case ASSIGNOP: assign(source, target); break; case CASTOP: cast(source->type, target); break; case DIVOP: case MODOP: case MULOP: case SLOP: case SROP: softop(op, source, target); break; case EQOP: case GEOP: case GTOP: case LEOP: case LTOP: case NEOP: condtrue = (opdata - FIRSTOPDATA)[op]; cmp(source, target, &condtrue); break; case FUNCOP: /* kludge update pushed regs */ /* may only work for si, di */ /* -2 skips for ax and bx */ /* need dirtymask to mostly avoid this */ savereturn(regmark & callermask & regregs, spmark - 2 * (offset_T) pshregsize); if (exp->nodetype->constructor & STRUCTU) { address(structarg); push(structarg); } function(target); break; case INDIRECTOP: indirec(target); break; case LISTOP: listo(target, lastargsp); lastargsp = sp; break; case NEGOP: neg(target); break; case NOTOP: not(target); break; case POSTDECOP: case POSTINCOP: case PREDECOP: case PREINCOP: incdec(op, target); break; case PTRADDOP: indexadr(source, target); break; case PTRSUBOP: ptrsub(source, target); break; case ROOTLISTOP: listroot(target); lastargsp = sp; break; case STRUCELTOP: struc(source, target); break; case SUBOP: sub(source, target); break; } if (target->storage == LOCAL && target->offset.offi < spmark && target->flags == TEMP) spmark = target->offset.offi; #if 1 /* XXX - why does sp get changed without this? */ if ((op_t) op != ROOTLISTOP) #endif modstk(spmark); if ((op_t) op == FUNCOP) { lastargsp = saveargsp; if (savelist != 0) { savereturn(savelist, saveoffset); onstack(target); target->offset.offi = saveoffset; } recovlist(regmark & callermask); } reguse = regmark; exp->tag = LEAF; exp->left.symptr = target; if (istooindirect(target)) makelessindirect(target); #ifdef SELFTYPECHECK tcheck(exp); #endif } PRIVATE void smakeleaf(exp) struct nodestruct *exp; { struct nodestruct *left; left = exp->left.nodeptr; if (left->tag == INDIRECTOP || left->tag == STRUCELTOP) smakeleaf(left); else if (left->tag != LEAF) makeleaf(left); if (exp->tag == INDIRECTOP) indirec(left->left.symptr); else { if (left->left.symptr->indcount > MAXINDIRECT + 1) makelessindirect(left->left.symptr); struc(exp->right->left.symptr, left->left.symptr); } exp->tag = LEAF; exp->left.symptr = left->left.symptr; } #ifdef SELFTYPECHECK PRIVATE void tcheck(exp) register struct nodestruct *exp; { register struct symstruct *target; if (exp->nodetype != (target = exp->left.symptr)->type) { { bugerror("botched nodetype calculation"); #ifdef DBNODE comment(); outstr("runtime type is "); dbtype(target->type); outstr(", calculated type is "); dbtype(exp->nodetype); outnl(); #endif } } } #endif /* SELFTYPECHECK */ dev86-0.16.17/bcc/exptree.c0000644000000000000000000006470610057421147015145 0ustar rootroot00000000000000/* exptree.c - expression tree routines for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" #include "byteord.h" #include "gencode.h" #include "parse.h" #include "reg.h" #include "sc.h" #include "scan.h" #include "sizes.h" #include "type.h" #ifdef VERY_SMALL_MEMORY #define ETREESIZE 300 #else #define ETREESIZE 1200 #endif #define errtype itype #define redtype ctype #define uredtype uctype PRIVATE struct nodestruct etree[ETREESIZE]; /* expression tree */ PRIVATE struct nodestruct *ettop; FORWARD void badlvalue P((struct nodestruct *nodeptr)); FORWARD void binconvert P((struct nodestruct *nodeptr)); FORWARD void castiright P((struct nodestruct *nodeptr)); FORWARD void etreefull P((void)); FORWARD void fixnode P((struct nodestruct *nodeptr)); FORWARD bool_pt isconst0 P((struct nodestruct *nodeptr)); FORWARD bool_pt isnodecharconst P((struct nodestruct *nodeptr)); FORWARD void needint P((struct nodestruct *nodeptr)); FORWARD void neednonstruct P((struct nodestruct *nodeptr)); FORWARD void needscalar P((struct nodestruct *nodeptr)); FORWARD void needspv P((struct nodestruct *nodeptr)); FORWARD struct typestruct *nodetype P((struct nodestruct *nodeptr)); FORWARD int redscalar P((struct nodestruct *nodeptr)); FORWARD struct nodestruct *unconvert P((struct nodestruct *nodeptr)); PRIVATE void badlvalue(nodeptr) struct nodestruct *nodeptr; { error("invalid lvalue"); fixnode(nodeptr); } PRIVATE void binconvert(nodeptr) register struct nodestruct *nodeptr; { bool_t bothscalar; value_t divisor; scalar_t lscalar; register struct nodestruct *right; scalar_t rscalar; rscalar = (right = nodeptr->right)->nodetype->scalar; lscalar = nodeptr->left.nodeptr->nodetype->scalar; if ((bothscalar = lscalar | rscalar) & RSCALAR) { nodeptr->nodetype = dtype; if (!(lscalar & DOUBLE)) nodeptr->left.nodeptr = castnode(dtype, nodeptr->left.nodeptr); if (!(rscalar & DOUBLE)) nodeptr->right = castnode(dtype, right); } else if (!(bothscalar & DLONG) && ((nodeptr->tag == ANDOP && (redscalar(nodeptr->left.nodeptr) | redscalar(right)) & CHAR) || ((nodeptr->tag == EOROP || nodeptr->tag == OROP) && redscalar(nodeptr->left.nodeptr) & redscalar(right) & CHAR) || (nodeptr->tag == MODOP && right->tag == LEAF && right->left.symptr->storage == CONSTANT && (divisor = right->left.symptr->offset.offv, (uvalue_t) divisor <= MAXUCHTO + 1) && bitcount((uvalue_t) divisor) <= 1))) { /* result fits in char and extends correctly */ if (bothscalar & UNSIGNED) nodeptr->nodetype = uredtype; else nodeptr->nodetype = redtype; } else if (bothscalar & LONG) { nodeptr->nodetype = ltype; if (bothscalar & UNSIGNED) nodeptr->nodetype = ultype; if (bothscalar & (DLONG | SHORT | INT)) { /* XXX - otherwise both are long, or one is long with the same * size as int and the other is char, and we want the lower level * routines to handle the char. */ if (!(lscalar & LONG)) nodeptr->left.nodeptr = castnode(nodeptr->nodetype, nodeptr->left.nodeptr); if (!(rscalar & LONG)) nodeptr->right = castnode(nodeptr->nodetype, right); } } #ifdef I80386 else if (i386_32 && bothscalar & SHORT) { nodeptr->nodetype = itype; if (bothscalar & UNSIGNED) nodeptr->nodetype = uitype; if (lscalar & SHORT) nodeptr->left.nodeptr = castnode(nodeptr->nodetype, nodeptr->left.nodeptr); if (rscalar & SHORT) nodeptr->right = castnode(nodeptr->nodetype, right); } #endif else if (bothscalar & UNSIGNED) nodeptr->nodetype = uitype; else nodeptr->nodetype = itype; } PRIVATE void castiright(nodeptr) struct nodestruct *nodeptr; { nodeptr->right = castnode(itype, nodeptr->right); } PUBLIC struct nodestruct *castnode(type, nodeptr) struct typestruct *type; struct nodestruct *nodeptr; { struct symstruct *symptr; (symptr = constsym((value_t) 0))->type = type; return node(CASTOP, nodeptr, leafnode(symptr)); } PRIVATE void etreefull() { #if ETREESIZE == 1200 limiterror("expression too complex (1201 nodes)"); #else limiterror("expression too complex (ETREESIZE)"); #endif } PUBLIC void etreeinit() { ettop = (etptr = etree) + ETREESIZE; } PRIVATE void fixnode(nodeptr) register struct nodestruct *nodeptr; { nodeptr->tag = LEAF; nodeptr->flags = nodeptr->weight = 0; nodeptr->left.symptr = constsym((value_t) 0); /* this has type errtype */ nodeptr->nodetype = errtype; } PRIVATE bool_pt isconst0(nodeptr) register struct nodestruct *nodeptr; { register struct symstruct *symptr; return nodeptr->tag == LEAF && (symptr = nodeptr->left.symptr)->storage == CONSTANT && symptr->offset.offv == 0 && symptr->type->scalar & ISCALAR; } PRIVATE bool_pt isnodecharconst(nodeptr) register struct nodestruct *nodeptr; { register struct symstruct *symptr; if (nodeptr->tag == LEAF && (symptr = nodeptr->left.symptr)->storage == CONSTANT && ischarconst(symptr->offset.offv) && symptr->type->scalar & ISCALAR) return TRUE; return FALSE; } PUBLIC struct nodestruct *leafnode(source) struct symstruct *source; { register struct nodestruct *leafptr; if ((leafptr = etptr++) >= ettop) etreefull(); leafptr->tag = LEAF; leafptr->flags = leafptr->weight = 0; leafptr->nodetype = source->type; leafptr->left.symptr = source; leafptr->right = NULL; return leafptr; } PRIVATE void needint(nodeptr) struct nodestruct *nodeptr; { if (!(nodeptr->nodetype->scalar & ISCALAR)) { error("need integral type"); fixnode(nodeptr); } } PRIVATE void neednonstruct(nodeptr) struct nodestruct *nodeptr; { if (nodeptr->nodetype->constructor & STRUCTU) { error("need non-structure type"); fixnode(nodeptr); } } PRIVATE void needscalar(nodeptr) struct nodestruct *nodeptr; { if (!nodeptr->nodetype->scalar) { error("need scalar"); fixnode(nodeptr); } } PRIVATE void needspv(nodeptr) struct nodestruct *nodeptr; { if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION | STRUCTU)) { error("need scalar or pointer or void"); fixnode(nodeptr); } } PUBLIC struct nodestruct *node(t, p1, p2) op_pt t; struct nodestruct *p1; struct nodestruct *p2; { #if MAXREGS != 1 weight_t rightweight; #endif double dsourceval = 0; /* for -Wall */ double dtargval = 0 ; /* for -Wall */ bool_t lflag; scalar_t lscalar; struct nodestruct *pswap; struct symstruct *source = NULL; /* for -Wall */ value_t sourceval = 0 ; /* for -Wall */ struct symstruct *target; offset_T targszdelta; value_t targval = 0; /* for -Wall */ scalar_t rscalar = 0; /* for -Wall */ bool_t uflag; switch ((op_t) t) { case ADDABOP: if (p1->nodetype->constructor & (ARRAY | POINTER)) t = PTRADDABOP; break; case ADDOP: if (p2->nodetype->constructor & (ARRAY | POINTER)) { pswap = p1; p1 = p2; p2 = pswap; } if (p1->nodetype->constructor & (ARRAY | POINTER)) t = PTRADDOP; break; case CONDOP: /* Change structs to struct pointers so condop() doesn't have to know * about structs. */ if (p2->nodetype->constructor & STRUCTU) { p2 = node(COLONOP, node(ADDRESSOP, p2->left.nodeptr, NULLNODE), node(ADDRESSOP, p2->right, NULLNODE)); return node(INDIRECTOP, node(CONDOP, p1, p2), NULLNODE); } break; case FUNCOP: if (p1->nodetype->constructor & (ARRAY | POINTER)) p1 = node(INDIRECTOP, p1, NULLNODE); break; case SUBABOP: if (p1->nodetype->constructor & (ARRAY | POINTER)) { t = PTRADDABOP; p2 = node(NEGOP, p2, NULLNODE); break; } case SUBOP: #if 0 /* This works but sometimes pessimizes the code by converting small * constants into large negative constants. It makes the most * difference for longs by avoiding stack tangles. longop could be * more careful. Only the case (regpair) - constant is naturally * tangled. */ if (p2->tag == LEAF && p2->nodetype->scalar && (source = p2->left.symptr)->storage == CONSTANT) { if (source->type->scalar & RSCALAR) *source->offset.offd = -*source->offset.offd; else source->offset.offv = -source->offset.offv; return node((op_t) t == SUBOP ? ADDOP : ADDABOP, p1, p2); } #endif if (p1->nodetype->constructor & (ARRAY | POINTER)) { if (p2->nodetype->nexttype == p1->nodetype->nexttype) t = PTRSUBOP; else { t = PTRADDOP; p2 = node(NEGOP, p2, NULLNODE); } } break; } if (((op_t) t == PTRADDABOP || (op_t) t == PTRADDOP) && p1->nodetype->nexttype->constructor & (FUNCTION | VOID)) error("arithmetic on pointer to function or void"); if (p1->tag != LEAF) goto node1; target = p1->left.symptr; switch ((op_t) t) { case ADDRESSOP: if (target->indcount == 0 && target->flags == REGVAR) error("register variable addressed"); else if (target->type->constructor & ARRAY) { if (target->indcount != 0) bugerror("botched array indirection count"); target->type = pointype(target->type); } else if (!(p1->flags & LVALUE)) badlvalue(p1); else { address(target); /* change p1, no code generated */ if (target->indcount == 2) /* XXX - MAXINDIRECT? */ /* just became direct enough */ p1->weight = 1; } p1->flags &= ~LVALUE; p1->nodetype = target->type; return p1; case CASTOP: needspv(p2); if (p1->nodetype == p2->nodetype) { p1->flags &= ~LVALUE; return p1; } if ((rscalar = p2->nodetype->scalar) & ISCALAR) neednonstruct(p1); else if (rscalar & RSCALAR) needscalar(p1); else /* POINTER */ neednonstruct(p1); /* H & S say functions & arrays must match */ if (((lscalar = p1->nodetype->scalar) | rscalar) & RSCALAR) { if (target->storage != CONSTANT) goto node1; if (lscalar & RSCALAR && !(rscalar & RSCALAR)) { double val; /* XXX: Gcc warns about ansi vs k&r problem with this */ static double MAXULONG = (double)0xFFFFFFFFL +1; val = *target->offset.offd; if (val > maxlongto) val -= MAXULONG; target->offset.offv = (value_t) val; } if (!(lscalar & RSCALAR) && rscalar & RSCALAR) { value_t val; val = target->offset.offv; target->offset.offd = qmalloc(sizeof *target->offset.offd); if (lscalar & UNSIGNED) *target->offset.offd = (uvalue_t) val; else *target->offset.offd = val; } } if (target->storage == CONSTANT) { if (rscalar & CHAR) { target->offset.offv &= CHMASKTO; if (p2->nodetype == sctype && target->offset.offv&((~CHMASKTO)>>1)) target->offset.offv |= ~CHMASKTO; } else if (rscalar & SHORT) { target->offset.offv &= shortmaskto; if (!(rscalar & UNSIGNED) && target->offset.offv > maxshortto) target->offset.offv -= (maxushortto + 1); } else if (rscalar & INT) { target->offset.offv &= intmaskto; if (!(rscalar & UNSIGNED) && target->offset.offv > maxintto) target->offset.offv -= (maxuintto + 1); } else if (rscalar & FLOAT) *target->offset.offd = (float) *target->offset.offd; } else if ((targszdelta = ((p1->nodetype->constructor & (ARRAY | POINTER)) ? ptypesize : p1->nodetype->typesize) - p2->nodetype->typesize) == 0) ; else if (target->indcount == 1 && targszdelta > 0 && target->flags != REGVAR) { #if DYNAMIC_LONG_ORDER if (long_big_endian) #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN # if INT_BIG_ENDIAN target->offset.offi += targszdelta; # else { if (lscalar & DLONG) target->offset.offi += itypesize; /* discard msword */ } # endif #endif #if DYNAMIC_LONG_ORDER else #endif #if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0 # if INT_BIG_ENDIAN { if (rscalar & CHAR) target->offset.offi += ctypesize; } # else ; # endif #endif } else goto node1; p1->flags &= ~LVALUE; p1->nodetype = target->type = p2->nodetype; return p1; case INDIRECTOP: if (!(target->type->constructor & (ARRAY | POINTER))) error("illegal indirection"); else { indirec(target); if (target->indcount == 3) /* XXX - MAXINDIRECT + 1? */ /* just became too indirect */ p1->weight = 1; p1->flags |= LVALUE; p1->nodetype = target->type; } return p1; case STRUCELTOP: /* p2 known leaf */ if (target->indcount != 1) break; /* struc() would generate code */ struc(p2->left.symptr, target); p1->flags |= LVALUE; p1->nodetype = target->type; return p1; } if (target->indcount != 0) goto node1; lscalar = target->type->scalar; if (target->storage == CONSTANT) { if (lscalar & RSCALAR) dtargval = *target->offset.offd; else targval = target->offset.offv; switch ((op_t) t) { case COMMAOP: return p2; case CONDOP: if ((lscalar & RSCALAR && dtargval != FALSE) || (!(lscalar & RSCALAR) && targval != FALSE)) { p2->left.nodeptr->nodetype = p2->nodetype; return p2->left.nodeptr; } p2->right->nodetype = p2->nodetype; return p2->right; case LOGANDOP: if ((lscalar & RSCALAR && dtargval != FALSE) || (!(lscalar & RSCALAR) && targval != FALSE)) break; p1->nodetype = target->type = itype; return p1; case LOGOROP: if ((lscalar & RSCALAR && dtargval == FALSE) || (!(lscalar & RSCALAR) && targval == FALSE)) break; target->offset.offv = TRUE; p1->nodetype = target->type = itype; return p1; } } switch ((op_t) t) { case COLONOP: case FUNCOP: case LISTOP: case ROOTLISTOP: goto node1; case PTRADDOP: if (p2->tag == LEAF && (source = p2->left.symptr)->storage == CONSTANT && source->type->scalar & ISCALAR) { indexadr(source, target); p1->flags &= ~LVALUE; p1->nodetype = target->type; return p1; } } if (target->storage != CONSTANT || !((lscalar & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP) || (p2 != NULL && (p2->tag != LEAF || (source = p2->left.symptr)->storage != CONSTANT || (!((rscalar = source->type->scalar) & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP)))) goto node1; lflag = lscalar & LONG; uflag = lscalar & UNSIGNED; if (p2 != NULL) { if (rscalar & RSCALAR) dsourceval = *source->offset.offd; else { sourceval = source->offset.offv; lflag |= rscalar & LONG; uflag |= rscalar & UNSIGNED; } } if (lscalar & RSCALAR || (p2 != NULL && rscalar & RSCALAR)) { if (!(lscalar & RSCALAR)) { if (uflag) dtargval = (uvalue_t) targval; else dtargval = targval; } if (p2 != NULL && !(rscalar & RSCALAR)) { if (rscalar & UNSIGNED) dsourceval = (uvalue_t) sourceval; else dsourceval = sourceval; } switch ((op_t) t) { case ADDOP: dtargval += dsourceval; break; case DIVOP: if (dsourceval == 0) { error("divison by 0"); dsourceval = 1; } dtargval /= dsourceval; break; case EQOP: targval = dtargval == dsourceval; goto intconst; case GEOP: targval = dtargval >= dsourceval; goto intconst; case GTOP: targval = dtargval > dsourceval; goto intconst; case LEOP: targval = dtargval <= dsourceval; goto intconst; case LOGANDOP: targval = dtargval && dsourceval; goto intconst; case LOGNOTOP: targval = !dtargval; goto intconst; case LOGOROP: targval = dtargval || dsourceval; goto intconst; case LTOP: targval = dtargval < dsourceval; goto intconst; case MULOP: dtargval *= dsourceval; break; case NEGOP: dtargval = -dtargval; break; case NEOP: targval = dtargval != dsourceval; goto intconst; case SUBOP: dtargval -= dsourceval; break; } /* XXX - leaks memory */ target->offset.offd = qmalloc(sizeof *target->offset.offd); *target->offset.offd = dtargval; p1->nodetype = target->type = dtype; return p1; } switch ((op_t) t) { case ADDOP: targval += sourceval; break; case ANDOP: targval &= sourceval; break; case DIVOP: if (sourceval == 0) { error("divison by 0"); sourceval = 1; } if (uflag) targval = (uvalue_t) targval / sourceval; else targval /= sourceval; break; case EOROP: targval ^= sourceval; break; case EQOP: targval = targval == sourceval; break; case GEOP: if (uflag) targval = (uvalue_t) targval >= sourceval; else targval = targval >= sourceval; goto intconst; case GTOP: if (uflag) targval = (uvalue_t) targval > sourceval; else targval = targval > sourceval; goto intconst; case LEOP: if (uflag) targval = (uvalue_t) targval <= sourceval; else targval = targval <= sourceval; goto intconst; case LOGANDOP: targval = targval && sourceval; goto intconst; case LOGNOTOP: targval = !targval; goto intconst; case LOGOROP: targval = targval || sourceval; goto intconst; case LTOP: if (uflag) targval = (uvalue_t) targval < sourceval; else targval = targval < sourceval; goto intconst; break; case MODOP: if (sourceval == 0) { error("modulo by 0"); sourceval = 1; } if (uflag) targval = (uvalue_t) targval % sourceval; else targval %= sourceval; break; case MULOP: targval *= sourceval; break; case NEGOP: targval = -targval; break; case NEOP: targval = targval != sourceval; goto intconst; case NOTOP: targval = ~targval; break; case OROP: targval |= sourceval; break; case PTRSUBOP: if (targval < sourceval) targval = -((uvalue_t) (sourceval - targval) / target->type->nexttype->typesize); else targval = (uvalue_t) (targval - sourceval) / target->type->nexttype->typesize; uflag = FALSE; break; case SLOP: targval <<= sourceval; /* assume shiftcount treated as unsigned */ lflag = lscalar & LONG; uflag = lscalar & UNSIGNED; break; case SROP: if (uflag) targval = (uvalue_t) targval >> sourceval; else targval >>= sourceval; lflag = lscalar & LONG; uflag = lscalar & UNSIGNED; break; case SUBOP: targval -= sourceval; break; } if (lflag) { target->type = ltype; if (uflag) target->type = ultype; } else { targval &= intmaskto; if (uflag) target->type = uitype; else { target->type = itype; if (targval > maxintto) targval -= (maxuintto + 1); } } target->offset.offv = targval; p1->nodetype = target->type; return p1; intconst: target->offset.offv = targval; p1->nodetype = target->type = itype; return p1; node1: { register struct nodestruct *nodeptr; register struct nodestruct *regp2; if ((nodeptr = etptr++) >= ettop) etreefull(); regp2 = p2; nodeptr->tag = t; nodeptr->left.nodeptr = p1; nodeptr->right = regp2; if ((op_t) t == FUNCOP) nodeptr->weight = MAXREGS + 1; else { #if MAXREGS == 1 if ((nodeptr->weight = p1->weight) <= MAXREGS && (regp2 == NULL || (nodeptr->weight = regp2->weight) < MAXREGS)) nodeptr->weight = MAXREGS; #else nodeptr->weight = p1->weight; if (regp2 == NULL) rightweight = 1; /* could do POST-ops with 0 */ else /* 0 more approp for LIST-ops but 1 OK */ rightweight = regp2->weight; if (nodeptr->weight < rightweight) nodeptr->weight = rightweight; else if (nodeptr->weight == rightweight && nodeptr->weight < MAXREGS) ++nodeptr->weight; #endif } nodeptr->nodetype = nodetype(nodeptr); return nodeptr; } } PRIVATE struct typestruct *nodetype(nodeptr) struct nodestruct *nodeptr; { scalar_t bothscalar; scalar_t lscalar; scalar_t rscalar; struct nodestruct *left; struct nodestruct *right; struct typestruct *targtype; if (nodeptr->tag == LEAF) return nodeptr->left.symptr->type; targtype = (left = nodeptr->left.nodeptr)->nodetype; right = nodeptr->right; switch (nodeptr->tag) { case FUNCOP: if (!(targtype->constructor & FUNCTION)) { error("call of non-function"); fixnode(nodeptr); return errtype; } return targtype->nexttype; case INDIRECTOP: if (!(targtype->constructor & (ARRAY | POINTER))) { error("illegal indirection"); fixnode(nodeptr); return errtype; } nodeptr->flags |= LVALUE; return targtype->nexttype; case LISTOP: case ROOTLISTOP: nodeptr->left.nodeptr = unconvert(left); return promote(targtype); case CASTOP: needspv(right); case COMMAOP: case CONDOP: return right->nodetype; case STRUCELTOP: nodeptr->flags |= LVALUE; return right->nodetype; case ADDRESSOP: if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } return pointype(targtype); case LOGNOTOP: neednonstruct(left); return redtype; case NEGOP: needscalar(left); return promote(left->nodetype); case NOTOP: needint(left); return promote(left->nodetype); case PREDECOP: case PREINCOP: case POSTDECOP: case POSTINCOP: neednonstruct(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } break; case ANDOP: case EOROP: case MODOP: case OROP: needint(left); needint(right); /* fall through to redundant check and code to cast to same types */ case ADDOP: case DIVOP: case MULOP: case SUBOP: needscalar(left); needscalar(right); binconvert(nodeptr); return nodeptr->nodetype; case PTRADDABOP: if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } case PTRADDOP: /* right type conversion to same size as ptr */ needint(right); if (right->nodetype->scalar & LONG) castiright(nodeptr); break; case PTRSUBOP: /* already checked */ return itype; case SLOP: /* right type conversion always to int */ case SROP: /* ulong strictly to unsigned but no matter */ needint(left); needint(right); if (right->nodetype->scalar & LONG) castiright(nodeptr); return promote(left->nodetype); case LTOP: case LEOP: case GTOP: case GEOP: case EQOP: case LOGOROP: case LOGANDOP: case NEOP: neednonstruct(left); neednonstruct(right); nodeptr->left.nodeptr = left = unconvert(left); nodeptr->right = right = unconvert(right); #ifdef MAYBE_DO_LATER /* OK if pointers fit in uitype */ if (left->nodetype->constructor & POINTER) nodeptr->left.nodeptr = left = castnode(uitype, left); if (right->nodetype->constructor & POINTER) nodeptr->right = right = castnode(uitype, right); #endif binconvert(nodeptr); return redtype; case COLONOP: if (isnodecharconst(left) && isnodecharconst(right)) { targtype = (targtype->scalar | right->nodetype->scalar) & UNSIGNED ? uctype : ctype; left = castnode(targtype, left); right = castnode(targtype, right); } nodeptr->left.nodeptr = left = unconvert(left); nodeptr->right = right = unconvert(right); targtype = left->nodetype; if ( #ifdef I80386 i386_32 || #endif ( targtype->scalar & FLOAT ) == 0) if (targtype == right->nodetype) return targtype; /* XXX - reduced from promote(targtype) */ if ((lscalar = targtype->scalar) != 0 && (rscalar = right->nodetype->scalar) != 0) { /* promote minimally without using binconvert for char/short */ if ((bothscalar = lscalar | rscalar) & (LONG | RSCALAR)) { binconvert(nodeptr); return nodeptr->nodetype; } if (bothscalar & INT || (lscalar ^ rscalar) & UNSIGNED) targtype = itype; else if (bothscalar & SHORT) targtype = stype; else targtype = ctype; if (bothscalar & UNSIGNED) targtype = tounsigned(targtype); if ((!(bothscalar & INT) || (left->tag == LEAF && lscalar & INT)) || (right->tag == LEAF && rscalar & INT)) { /* this is correct even when the if fails (the casts have to */ /* be considered at a lower level) but gives worse code */ if (left->nodetype != targtype) nodeptr->left.nodeptr = castnode(targtype, left); if (right->nodetype != targtype) nodeptr->right = castnode(targtype, right); } return targtype; /* XXX - reduced from promote(targtype) */ } if (targtype->constructor & POINTER && (isconst0(right) || (right->nodetype->constructor & POINTER && right->nodetype->nexttype->constructor & VOID))) return targtype; if (right->nodetype->constructor & POINTER && (isconst0(left) || (targtype->constructor & POINTER && targtype->nexttype->constructor & VOID))) return right->nodetype; error("mismatched types"); fixnode(left); /* XXX - better to fix the CONDOP */ fixnode(right); return errtype; case ASSIGNOP: if (right->nodetype->constructor & VOID) { error("assignment of void"); fixnode(right); } if (targtype->constructor & (ARRAY | FUNCTION | VOID)) { error("assignment to array, function or void"); fixnode(nodeptr); return errtype; } if ((targtype->constructor | right->nodetype->constructor) & STRUCTU && targtype != right->nodetype) { error("assignment to/from struct/union of a different type"); fixnode(nodeptr); return errtype; } if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } #if 0 /* XXX - this is done at the lowest levels, with too many chances for * errors. */ if (targtype != right->nodetype) nodeptr->right = castnode(left->nodetype, right); #endif break; case ANDABOP: case EORABOP: case MODABOP: case ORABOP: needint(right); needint(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } /* fall through to redundant check and code to cast to same types */ case ADDABOP: case SUBABOP: case DIVABOP: case MULABOP: needscalar(right); needscalar(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } rscalar = right->nodetype->scalar; if ((lscalar = (targtype = left->nodetype)->scalar) & RSCALAR) { if (!(rscalar & DOUBLE)) nodeptr->right = castnode(dtype, right); } else if (lscalar & LONG) { if (!(rscalar & LONG)) nodeptr->right = castnode(rscalar & UNSIGNED ? ultype : targtype, right); } #ifdef I80386 else if (i386_32 && lscalar & INT) { if (rscalar & SHORT) nodeptr->right = castnode(rscalar & UNSIGNED ? uitype : targtype, right); } #endif break; case SLABOP: case SRABOP: needint(right); needint(left); if (!(left->flags & LVALUE)) { badlvalue(nodeptr); return errtype; } if (!(right->nodetype->scalar & INT)) castiright(nodeptr); break; } return left->nodetype; } PRIVATE int redscalar(nodeptr) register struct nodestruct *nodeptr; { if (isnodecharconst(nodeptr)) return CHAR; return nodeptr->nodetype->scalar; } PRIVATE struct nodestruct *unconvert(nodeptr) struct nodestruct *nodeptr; { if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION)) return castnode(pointype(nodeptr->nodetype->constructor & ARRAY ? nodeptr->nodetype->nexttype : nodeptr->nodetype), nodeptr); return nodeptr; } dev86-0.16.17/bcc/bcc-cc1.c0000644000000000000000000000065610065304676014664 0ustar rootroot00000000000000/* bcc-cc1.c - "pass 1" for bcc */ /* Copyright (C) 1992 Bruce Evans */ #include "bcc.h" PUBLIC int main(argc, argv) int argc; char **argv; { debug(1, "Start"); growheap(0); /* init order is important */ syminit(); etreeinit(); #ifdef BUILTIN_CPP ifinit(); predefine(); #endif openio(argc, argv); codeinit(); typeinit(); program(); finishup(); /* NOTREACHED */ return 0; } dev86-0.16.17/bin86/0000755000000000000000000000000007774532311013517 5ustar rootroot00000000000000dev86-0.16.17/bin86/ChangeLog0000644000000000000000000000660007302421243015257 0ustar rootroot00000000000000 This file is NOT the current changelog. Please see the Changes file in the directory above (the main directory of the Dev86 package). Robert de Bath. Fri Jun 11 13:08:27 BST 1999 Robert de Bath (rdebath@poboxes.com) * objdump86 program included. * Updated for libc6 * As86 fixes for multi-segment (The linker can't really cope tho) Sat Mar 13 16:45:42 GMT 1999 Robert de Bath (rdebath@poboxes.com) * Vsn 0.15.0, more documentation! * Linker can now generate QMAGIC 386 executables. Fri Jul 31 09:33:18 BST 1998 Robert de Bath (rdebath@poboxes.com) * version 0.14.4, This package is based on the ELKS dev86 package of the same version number. * Improved documentation (There's actually a man page!) * The linker will produce either Linux-8086, DOS-COM or Native Linux-386 OMAGIC executable files. * The assembler has many instruction fixes: jmp near, jmpi dword x,y, org, use32/use16 ... etc and can also read source from stdin. * Assembler macros work. * The assembler command 'include' works. * Conditionals and string conditionals work. * Various additions for multi-segment work. * The assembler can create bare binary files with simple ASCII symbol files, these are ideal for generating encapsulated binaries and a simple script for doing this is included. * The assembler will generate warning messages when 386 instructions are used with the assembler in an 8086 mode. * Many minor bug fixes and portability fixes. Sat Nov 16 18:38:14 1995 H.J. Lu (hjl@gnu.ai.mit.edu) * version 0.4 is released. * Makefile (CFLAGS): add _POSIX_SOURCE. * as/as.c, as/flag.h, as/genlist.c, as/pops.c,v, as/readsrc.c: change warn to warning. Fri Jun 16 02:02:03 1995 Michael Shields (shields@tembel.org) * as/Makefile (endian.h): Don't rely on . being in $PATH. Tue May 16 22:01:05 1995 H.J. Lu (hjl@nynexst.com) * version 0.3 is released. * Makefile: fix a few typos. * as/const.h: include "endian.h". (LOW_BYTE): check the byte order. * as/Makefile (endian.h): new target. (const.h): depend on endian.h. * as/det_endian.c: new from glibc. Sat Mar 18 16:39:19 1995 Francois-Rene Rideau (rideau@clipper.ens.fr) * as/pops.c (doif): support nested conditionals. Mon Nov 21 22:48:26 1994 H.J. Lu (hlu@nighthawk) * version 0.2 is released. * Makefile (MFLAGS): new. add BINDIR and CC. Fri Nov 18 22:25:24 1994 Package Maintainer (opt@calum.csclub.uwaterloo.ca) * ./as/Makefile: * ./as/const.h: * ./as/proto.h: * ./as/readsrc.c: * ./as/type.h: * ./ld/Makefile: * ./ld/align.h: * ./ld/config.h: * ./ld/type.h: * ./ld/typeconv.c: remove endian dependency. Thu Mar 3 15:12:23 1994 H.J. Lu (hlu@nighthawk) * version 0.1 is released. * Makefile: new. * a.out.h/bsd-a.out.h (struct exec): use short form if __linux__ is defined. * as/Makefile: minor changes. (CLFAGS): add -I../a.out.h. * ld/Makefile: minor changes. (CLFAGS): add -I../a.out.h. * ld/io.c (MY_STAT_H): don't define it if __linux__ is defined. * ld/ld.c (flag['z']): initialized to 0 if __linux__ is defined. * ld/obj.h (roundup): * ld/writebin.c (roundup): ld/readobj.c (roundup): change that to ld_roundup to avoid the conflict with the system's roundup. * ld/writebin.c: cleanup for the latest Linux C library. (FILEHEADERLENGTH): change to sizeof (struct exec). don't write a_trsize and its friends. dev86-0.16.17/bin86/README-0.40000644000000000000000000000535406560300457014701 0ustar rootroot00000000000000To build this real mode as/ld for x86, just edit Makefile and then do make install It is only tested under SunOS 4.1.3 and Linux. H.J. Lu hjl@nynexst.com 11/21/94 ------ We seem to have cross bin86 for Solaris working. The most important changes involve alignment (it needs to be on) and byte ordering. Some of the patches just eliminate compiler warnings (conversion of pointer to integer without a cast, etc.) and some (in the Makefiles) reflect the local setup, and can probably be ignored (the change to $BINDIR, for example). - Ian (iagoldbe@csclub.uwaterloo.ca) ---- I modified it for the latest Linux C library 4.5.21 and released it as bin86 0.1. It is only tested for building the Linux kernel and is not intended for any other purposes. To build it under Linux, just type make all make install It is not tested for cross-compiling. If you have any patches for cross-compiling, please send them to me. Thanks. H.J. Lu hjl@nynexst.com 03/03/94 ------------- This is the as86 and ld86 distribution written by Bruce Evans. It's copyright Bruce Evans, all rights reserved although you may use and copy it for your personal use. It's a complete 8086 assembler and loader which can make 32-bit code for the 386+ processors (under linux it's used only to create the 16-bit bootsector and setup binaries). The syntax is not compatible with the GNU assembler, but closer to intel syntax ("wrong" order of operands etc). Hints for compiling: - you'll need the a.out.h-files from the a.out.h directory for the linker. These aren't really part of the distribution, but I included them for ease of setup (in case you need to crosscompile etc). Do a cp a.out.h/* ld/ or similar before compiling the linker. - the assembler needs the typeconv.o file produced by the linker compilation. So compile the linker first, and then do a cp ld/typeconv.o as/ before making the assembler. This distribution also contains some test-files etc that aren't actually needed, but as they also give some idea of the assembler syntax, I left them in. The directories are as follows: as - the assembler sources (minus typeconv.c) ld - linker sources bcc - bruce evans' cc frontend sources (the actual compiler isn't included). bccfp - assembly floating point routines written by bruce evans. Note that these use integer register returns, and won't work with the linux libraries. They can be used as examples of as86 code. a.out.h - header files for crosscompilation. Note that I am NOT the author of this package, but I'll forward any comments to bruce evans and I'll try to answer any questions about the assembler/linker I can. I just made it available as bde doesn't have ftp capability right now. Bruce Evans does have mail as . Linus Torvalds dev86-0.16.17/bin86/Makefile0000644000000000000000000000210707774532310015156 0ustar rootroot00000000000000 CFLAGS=-O2 -D_POSIX_SOURCE LDFLAGS= DIRS=ld as PREFIX=/usr/local BINDIR=$(PREFIX)/bin LIBDIR=$(PREFIX)/lib MANDIR=$(PREFIX)/man/man1 SUF=86 INSTALL_OPT=-m 755 INSTALL_OPTS=-m 755 -s MAN_OPTS =-m 644 MFLAGS= "LIBS=$(LIBS)" \ "CFLAGS=$(CFLAGS)" \ "LDFLAGS=$(LDFLAGS)" \ "BINDIR=$(BINDIR)" \ "LIBDIR=$(LIBDIR)" \ "CC=$(CC)" all: set -e ; for d in $(DIRS); do \ (cd $$d && $(MAKE) $(MFLAGS) $@;); \ done install: all install $(INSTALL_OPTS) as/as86 $(BINDIR)/as$(SUF) install $(INSTALL_OPTS) ld/ld86 $(BINDIR)/ld$(SUF) install $(INSTALL_OPTS) ld/objdump86 $(BINDIR)/objdump$(SUF) install $(MAN_OPTS) man/*.1 $(MANDIR) ln -sf objdump$(SUF) $(BINDIR)/nm$(SUF) ln -sf objdump$(SUF) $(BINDIR)/size$(SUF) depend clean clobber: set -e ; for d in $(DIRS); do \ (cd $$d && $(MAKE) $(MFLAGS) $@;); \ done ungrab: ../as/as.c rm -rf as ld man grab: cp -a ../as ../ld . rm -f ld/ar.h && cp -p ../libc/include/ar.h ld/ar.h mkdir man cp -p ../man/ld86.1 man cp -p ../man/as86.1 man touch -r ../Changes . as ld man dev86-0.16.17/bin86/README0000644000000000000000000000146706560365274014413 0ustar rootroot00000000000000 This is a simple assember and linker for 8086 - 80386 machine code. There have been a large number of changes since bin86-0.4 so I strongly suggest you read the manpages. To install: make PREFIX=/usr install or make PREFIX=/usr/local install This version has been tested under Linux, older versions were also tested and working under SunOS and AIX. ------------- This is based on the as86 and ld86 distribution written by Bruce Evans. Bruce has released this under the GPL and the changes I've made are also under the same license The BCC components that were distributed in this package are now in the dev86 package along with a working C compiler and libc for 8086 ELKS, DOS and standalone code. The most recent address I have for Bruce is Robert de Bath 1998/7/31 dev86-0.16.17/bootblocks/0000755000000000000000000000000010174732445014730 5ustar rootroot00000000000000dev86-0.16.17/bootblocks/i86_funcs.c0000644000000000000000000001012507616723004016675 0ustar rootroot00000000000000 #include "monitor.h" #ifndef NOMONITOR int x86 = 3; /* CPU major number */ char *x86_name = ""; /* and it's name */ int x86_emu = 0; /* Is this a PC emulator ? */ int x86_fpu = 0; #endif int x86_test = 0; /* In test mode */ unsigned boot_mem_top = 0x2000; /* Default 128k, the minimum */ long main_mem_top = 0; /* K of extended memory */ void cpu_check() { #ifndef NOMONITOR static char *name_808x[] = { "8088", "8086", "80C88", "80C86", "NEC V20", "NEC V30", "808x Clone" }; static char *name_8018x[] = { "80188", "80186", "8018x Clone" }; static char cpubuf[] = "80x86+"; int c, major; c = cputype(0); x86_fpu = (c < 0); major = ((c >> 8) & 0x1F); c &= 0xFF; x86 = (major&0xF); if (major == 0) { if (c > 6) c = 6; x86_name = name_808x[c]; } else if (major == 1) { if (c > 3) c = 3; x86_name = name_8018x[c]; } else { cpubuf[2] = (major&0xF)+'0'; cpubuf[5] = (major > 15 ? '+' : '\0'); x86_name = cpubuf; if (c & 0x01) x86_emu = 1; /* Already in protected mode !!! */ } x86_test = x86_emu; if (x86<3) x86_test = 1; #endif #ifdef __STANDALONE__ if (__argr.x.cflag) x86_test = 1; #else x86_test = 1; #endif } void mem_check() { if (x86_test) { main_mem_top = 0; return; } #asm int 0x12 ! Amount of boot memory mov cl,#6 sal ax,cl ! In segments mov [_boot_mem_top],ax mov ah,#0x88 ! Next check for extended int 0x15 jnc got_ext ! Error! is_xt: xor ax,ax got_ext: mov word ptr [_main_mem_top+2],#0 mov [_main_mem_top],ax #endasm /* Try int $15 EAX=$E820 */ { struct e820_dat { unsigned long base_lo, base_hi; unsigned long len_lo, len_hi; long addr_type; } e820_item; long epoll = 0; do { e820_item.addr_type = 0; #asm mov eax,#$E820 mov ebx,.mem_check.epoll[bp] mov ecx,#20 mov edx,#$534D4150 push ds pop es lea di,.mem_check.e820_item[bp] int $15 jnc got_e820 xor ebx,ebx got_e820: mov .mem_check.epoll[bp],ebx #endasm if (e820_item.addr_type == 1 && e820_item.base_hi == 0 && e820_item.base_lo == 0x100000L) { /* XXX Later ... */ if (e820_item.len_hi) main_mem_top = 0x40000; else main_mem_top = (e820_item.len_lo >> 10); return; } } while(epoll); } /* Try int $15 EAX=$E801 */ { unsigned int mem_64, mem_16; /* For int $15,AX=$E801 */ #asm mov ax,#$E801 int $15 jc no_e801 mov .mem_check.mem_16[bp],ax mov .mem_check.mem_64[bp],bx #endasm main_mem_top = ((unsigned long)mem_64<<6) + mem_16; #asm no_e801: #endasm } } #define RIGHTS (0x93000000L) static struct { char gdt0[8]; char gdt1[8]; unsigned short src_len; long src_seg; unsigned short spad; unsigned short dst_len; long dst_seg; unsigned short dpad; char gdt4[8]; char gdt5[8]; } GDT = { "","", 0xFFFF, RIGHTS, 0, 0xFFFF, RIGHTS, 0, "" }; mem_write(buffer, baseaddr, sectno, sectcount) void * buffer; long baseaddr; unsigned sectno, sectcount; { if(x86_test) return 0; /* In an EMU we can't write to high mem but we'll pretend we can for debuggering */ baseaddr += ((long)sectno<<9); if( baseaddr < 0xA0000L ) { __movedata(__get_ds(), buffer, (unsigned)(baseaddr>>4), (unsigned)(baseaddr&0xF), sectcount * 512); return 0; } GDT.src_seg = RIGHTS + (unsigned)buffer + ((long)__get_ds()<<4); GDT.dst_seg = RIGHTS + baseaddr; return asm_copy(sectcount << 8); } mem_read(buffer, baseaddr, sectno) void * buffer; long baseaddr; int sectno; { if(x86_test) return 3; baseaddr += ((long)sectno<<9); GDT.dst_seg = RIGHTS + (unsigned)buffer + ((long)__get_ds()<<4); GDT.src_seg = RIGHTS + baseaddr; return asm_copy(256); } static asm_copy(length) { #asm #if !__FIRST_ARG_IN_AX__ mov bx,sp mov ax,[bx+2] #endif push es push si mov cx,ax mov ah,#$87 push ds pop es mov si,#_GDT int $15 jc err xor ax,ax err: mov al,ah xor ah,ah pop si pop es #endasm } dev86-0.16.17/bootblocks/fs_tar.c0000644000000000000000000001454407431464147016365 0ustar rootroot00000000000000 #include "monitor.h" #define HEADER_SIZE 512 #define NAME_SIZE 100 #define BLOCK_BOUNDARY 20 typedef union { char hdr_block[HEADER_SIZE]; struct m { char m_name[NAME_SIZE]; char m_mode[8]; char m_uid[8]; char m_gid[8]; char m_size[12]; char m_time[12]; char m_checksum[8]; char m_linked; char m_link[NAME_SIZE]; char m_ustar[8]; char m_uname[32]; char m_gname[32]; char m_major[8]; /* GNU fields */ char m_minor[8]; char m_atime[12]; char m_ctime[12]; char m_offset[12]; /* An so forth */ } member; } HEADER; long tar_convert(); int valid_tar_checksum(); void tar_set_drive(); static int disk_size = 0; struct tx { char name[NAME_SIZE]; int first_sectno; int cur_sectno; int sectcount; int diskoffset; long file_length; } tar_status; tar_open_file(fname) char * fname; { HEADER * sptr; #ifndef NOCOMMAND int dodir = 0; #endif int sectno; sptr = read_sector(0); /* Is it a tar disk ? */ if( !valid_tar_checksum(sptr) ) return -1; tar_set_drive(); #ifndef NOCOMMAND if( strcmp(fname, ".") == 0 ) dodir=1; else #endif { if( tar_status.diskoffset == 0 && strcmp(fname, tar_status.name) == 0 ) return tar_rewind_file(); } tar_close_file(); for(sectno=0;;) { long fl, v; if(sectno) sptr = read_sector(sectno); if(!sptr || !*sptr->member.m_name) break; if( !valid_tar_checksum(sptr) ) { printf("Checksum error on tar header\n"); return -1; } fl = tar_convert(sptr->member.m_size, 12); v = (fl+511)/512 + 1; if( sptr->member.m_linked != 0 && sptr->member.m_linked != '0' ) ; #ifndef NOCOMMAND else if( dodir ) printf("%s %d tape blocks\n", sptr->member.m_name, (int)v-1); #endif else if( strcmp(fname, sptr->member.m_name, NAME_SIZE) == 0 ) { strncpy(tar_status.name, sptr->member.m_name, NAME_SIZE); tar_status.first_sectno = sectno+1; tar_status.cur_sectno = sectno+1; tar_status.file_length = fl; tar_status.sectcount = v-1; tar_status.diskoffset = 0; return 0; } if( v < 1 || (sectno += v) > disk_size ) break; } return -1; } tar_rewind_file() { if( tar_status.name[0] == '\0' || tar_status.diskoffset != 0 ) { tar_close_file(); return -1; } tar_status.cur_sectno = tar_status.first_sectno; return 0; } tar_close_file() { tar_status.name[0] = 0; tar_status.first_sectno = -1; tar_status.cur_sectno = -1; tar_status.file_length = -1; tar_status.diskoffset = -1; return 0; } long tar_file_length() { if( tar_status.name[0] == '\0' ) return -1; return tar_status.file_length; } tar_read_block(buffer) char * buffer; { char * ptr; HEADER * sptr; int i; if( tar_status.name[0] == '\0' ) return -1; for(i=0; i<2; i++) { if( tar_status.cur_sectno - tar_status.first_sectno >= tar_status.sectcount ) { memset(buffer, '\0', 512); } else { if( tar_status.cur_sectno >= tar_status.diskoffset+disk_size ) { int k; tar_status.diskoffset += disk_size-2; for(;;) { printf("Please insert next disk and press return:"); fflush(stdout); while( (k=(getch() & 0x7F)) != '\r' && k != '\n') if( k == 27 || k == 3 ) { printf("... Aborting\n"); return -1; } printf("\n"); sptr = read_sector(0); if( !valid_tar_checksum(sptr) ) { printf("Checksum failed reading volume label\n"); continue; } tar_set_drive(); sptr = read_sector(1); if( !valid_tar_checksum(sptr) || sptr->member.m_linked != 'M' || 512*(long)(tar_status.cur_sectno-tar_status.first_sectno) != tar_convert(sptr->member.m_offset, 12) ) { printf("Wrong disk inserted, "); continue; } break; } ptr = read_sector(tar_status.cur_sectno-tar_status.diskoffset); } else ptr = read_sector(tar_status.cur_sectno-tar_status.diskoffset); if( ptr == 0 ) return -1; memcpy(buffer, ptr, 512); } buffer+=512; tar_status.cur_sectno++; } return 0; } long tar_convert(str, type) char str[]; int type; { register long ac = 0L; register int i; for (i = 0; i < type; i++) { if (str[i] >= '0' && str[i] <= '7') { ac <<= 3; ac += (long) (str[i] - '0'); } } return ac; } valid_tar_checksum(sptr) register HEADER * sptr; { register char *ptr; int ac = 0; ptr = sptr->hdr_block; while (ptr < sptr->hdr_block+sizeof(sptr->hdr_block)) if( ptr < sptr->member.m_checksum || ptr >= sptr->member.m_checksum+sizeof(sptr->member.m_checksum)) ac += (*ptr++ & 0xFF); else ptr++, (ac += ' '); ac -= tar_convert(sptr->member.m_checksum, sizeof(sptr->member.m_checksum)); return ac == 0; } void tar_set_drive() { #ifdef __STANDALONE__ disk_spt = __argr.x.si; /* Choose some formats, note Boot block only sees a few SPT. * 9x40=360k, 15x80=1200k, 18x80=1440k, 21x82=1722k, 36x80=2880k */ if( disk_spt <= 9 ) disk_cyls = 40; if( disk_spt == 21 || disk_spt > 36 ) disk_cyls = 82; else if( disk_spt == 32 ) disk_cyls = 1024; else disk_cyls = 80; #else disk_spt = 18; /* Testing only */ disk_cyls= 80; #endif disk_heads=2; disk_size = disk_spt*disk_cyls*disk_heads; } #if 0 #asm !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! These are the number of sectors per track that will be scanned for. ! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on ! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. disksizes: .byte 36,21,18,15,9 ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. export _probe_sectors _probe_sectors: mov si,#disksizes ! table of sizes to try probe_loop: lodsb cbw ! extend to word mov _disk_spt, ax cmp al,#9 je got_sectors ! if all else fails, try 9 xchg ax, cx ! cx = track and sector xor dx, dx ! drive 0, head 0 mov bx,#probe_buf ! address after setup (es = cs) mov ax,#0x0201 ! service 2, 1 sector int 0x13 jc probe_loop ! try next value got_sectors: ret #endasm #endif dev86-0.16.17/bootblocks/noboot.s0000644000000000000000000000076706571436015016426 0ustar rootroot00000000000000 org $7c00 include sysboot.s org dos_sysid .ascii "PANIC" ! System ID org codestart xor ax,ax mov ds,ax mov ss,ax mov sp,ax jmpi code,#0 code: ! SI = pointer to error message mov si,#boot_message nextc: lodsb cmp al,#0 jz eos mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp nextc eos: ! Wait for a key then reboot xor ax,ax int $16 jmpi $0,$FFFF ! Wam! Try or die! export boot_message boot_message: .asciz "PANIC! NO OS Found!\r\n" dev86-0.16.17/bootblocks/fs_dos.c0000644000000000000000000002100307473704021016342 0ustar rootroot00000000000000 #include "monitor.h" #ifdef BUFFER_FAT #define read_fat_sector read_sector #endif #define DOS_SECT(P) get_uint(P,0x0B) #define DOS_CLUST(P) get_byte(P,0x0D) #define DOS_RESV(P) get_uint(P,0x0E) #define DOS_NFAT(P) get_byte(P,0x10) #define DOS_NROOT(P) get_uint(P,0x11) #define DOS_MAXSECT(P) get_uint(P,0x13) #define DOS_MEDIA(P) get_byte(P,0x15) #define DOS_FATLEN(P) get_uint(P,0x16) #define DOS_SPT(P) get_uint(P,0x18) #define DOS_HEADS(P) get_uint(P,0x1A) #define DOS_HIDDEN(P) get_long(P,0x1C) #define DOS4_MAXSECT(P) get_long(P,0x20) #define DOS4_PHY_DRIVE(P) get_byte(P,0x24) #define DOS4_SERIAL(P) get_long(P,0x27) #define DOS4_FATTYPE(P) get_uint(P,0x39) /* These assume alignment is not a problem */ #define get_byte(P,Off) *((unsigned char*)((char*)(P)+(Off))) #define get_uint(P,Off) *((unsigned short*)((char*)(P)+(Off))) #define get_long(P,Off) *((long*)((char*)(P)+(Off))) typedef long Tsect; static int read_bootblock(); static int dir_nentry, dir_sect; static Tsect dos_clust0, dos_spc; static int dos_fatpos, dos_fatlen, dos_fattype; static int last_serial = 0; #ifndef BUFFER_FAT static char * read_fat_sector(); static int sector_no = 0; static char sector_buf[512]; #endif #ifdef BUFFER_FAT static char * fat_buf = 0; int use_fatbuf = 0; #endif static struct filestatus { char fname[12]; unsigned short first_cluster; unsigned short cur_cluster; unsigned short sector_no; /* Max filesize = 32M */ long file_length; } cur_file = { "", 0, 0, 0 }; dos_open_file(fname) char * fname; { char conv_name[12]; char *s, *d; int i; int dodir = 0; /* Get the superblock */ if( read_bootblock() < 0 ) return -1; if(strcmp(fname, ".") == 0) dodir = 1; else { /* Convert the name to MSDOS directory format */ strcpy(conv_name, " "); for(s=fname, d=conv_name; *s && *d && *s != '.' && *s != ' '; s++) { if( islower(*s) ) *d++ = toupper(*s); else *d++ = *s; } while( *s && *s != '.' ) s++; strcpy(d=(conv_name+8), " "); if( *s == '.' ) { for(s++; *s && *d; s++) { if( islower(*s) ) *d++ = toupper(*s); else *d++ = *s; } } /* Already opened ? Then just rewind it */ if( cur_file.first_cluster && strcmp(cur_file.fname, conv_name) == 0 ) return dos_rewind_file(); } memset(&cur_file, '\0', sizeof(cur_file)); #ifdef BUFFER_FAT if( !dodir && dos_fattype == 12 ) { /* Read in and buffer the FAT */ if( fat_buf ) free(fat_buf); fat_buf = malloc(dos_fatlen * 512); if( fat_buf == 0 ) use_fatbuf = 0; else { use_fatbuf = 1; for(i=0; i ' ' && *d <= '~' ) switch(d[11]&0x18) { case 0: printf("%-8.8s %-3.3s %10ld", d, d+8, get_long(d,28)); dtime=1; break; case 0x10: printf("%-8.8s %-3.3s ", d, d+8); dtime=1; break; case 8: if( (d[11] & 7) == 0 ) { printf("%-11.11s ", d); dtime=1; } break; } if( dtime ) { printf(" %02d/%02d/%04d %02d:%02d", (get_uint(d,24)&0x1F), ((get_uint(d,24)>>5)&0xF), ((get_uint(d,24)>>9)&0x7F)+1980, ((get_uint(d,22)>>11)&0x1F), ((get_uint(d,22)>>5)&0x3F) ); if( more_char('\n') < 0 ) break; } #endif } else if( memcmp(d, conv_name, 11) == 0 && (d[11]&0x18) == 0 ) { /* Name matches and is normal file */ strcpy(cur_file.fname, conv_name); cur_file.first_cluster = get_uint(d,26); cur_file.file_length = get_long(d,28); cur_file.cur_cluster = cur_file.first_cluster; cur_file.sector_no = 0; #ifdef DEBUG fprintf(stderr, "Opened first cluster %d, len %ld\n", cur_file.first_cluster, cur_file.file_length ); #endif return 0; } } return -1; } dos_rewind_file() { /* Is there an opened file ? */ if( cur_file.fname[0] == 0 ) return -1; cur_file.sector_no = 0; cur_file.cur_cluster = cur_file.first_cluster; return 0; } dos_close_file() { #ifdef BUFFER_FAT if( fat_buf ) free(fat_buf); fat_buf = 0; #endif memset(&cur_file, '\0', sizeof(cur_file)); reset_disk(); return 0; } long dos_file_length() { /* Is there an opened file ? */ if( cur_file.fname[0] == 0 ) return -1; return cur_file.file_length; } dos_read_block(buffer) char * buffer; { int s; char * ptr; /* Is there an opened file ? */ if( cur_file.fname[0] == 0 ) { #ifdef DEBUG fprintf(stderr, "File is not currently open!\n"); #endif return -1; } /* Are we before the EOF ? */ if( ( dos_fattype == 12 && cur_file.cur_cluster >= 0xFF0 ) || ( dos_fattype == 16 && (cur_file.cur_cluster&0xFFF0) == 0xFFF0 ) || cur_file.cur_cluster < 2 ) { #ifdef DEBUG fprintf(stderr, "Hit end of file; cluster 0x%03x\n", cur_file.cur_cluster); #endif return -1; } for(s=0; s<2; s++) { Tsect sectno; if( ( dos_fattype == 12 && cur_file.cur_cluster >= 0xFF0 ) || ( dos_fattype == 16 && (cur_file.cur_cluster&0xFFF0) == 0xFFF0 ) || cur_file.cur_cluster < 2 ) { memset(buffer, '\0', 512); buffer += 512; continue; } sectno = dos_clust0 + cur_file.cur_cluster * dos_spc + cur_file.sector_no % dos_spc; ptr = read_sector(sectno); if( ptr == 0 ) return -1; memcpy(buffer, ptr, 512); cur_file.sector_no++; if( cur_file.sector_no % dos_spc == 0 ) { if( dos_fattype == 12 ) { int odd = (cur_file.cur_cluster&1); unsigned int val, val2; val = cur_file.cur_cluster + (cur_file.cur_cluster>>1); #ifdef BUFFER_FAT if( use_fatbuf ) val2 = get_uint(fat_buf, val); else #endif { ptr = read_fat_sector(dos_fatpos+(val/512)); if( ptr == 0 ) return -1; if( val%512 == 511 ) { val2 = (ptr[511]&0xFF); ptr = read_fat_sector(dos_fatpos+(val/512)+1); if( ptr == 0 ) return -1; val2 |= (ptr[0]<<8); } else val2 = get_uint(ptr, (val%512)); } if( odd ) val2>>=4; val2 &= 0xFFF; cur_file.cur_cluster = val2; } else { ptr = read_fat_sector(dos_fatpos+(cur_file.cur_cluster/256)); if( ptr == 0 ) return -1; cur_file.cur_cluster = get_uint(ptr, (cur_file.cur_cluster%256*2)); } } buffer += 512; } return 0; } static int read_bootblock() { char * sptr; int rv, media_byte = 0; #ifndef BUFFER_FAT sector_no = 0; #endif sptr = read_sector(1); if( sptr == 0 ) return -1; media_byte = *(unsigned char*)sptr; /* Valid media byte ? */ if( (media_byte & 0xF0) != 0xF0 ) return -1; sptr = read_sector(0); if( sptr == 0 ) return -1; if( DOS_MEDIA(sptr) != media_byte ) return -1; if( DOS_SPT(sptr) > 63 ) return -1; if( DOS_SECT(sptr) != 512 ) return -1; if( last_serial != DOS4_SERIAL(sptr) ) dos_close_file(); last_serial = DOS4_SERIAL(sptr); /* Collect important data */ dir_sect = DOS_RESV(sptr) + DOS_NFAT(sptr)*DOS_FATLEN(sptr); dir_nentry = DOS_NROOT(sptr); dos_fatpos = DOS_RESV(sptr); dos_fatlen = DOS_FATLEN(sptr); dos_spc = DOS_CLUST(sptr); dos_fattype = DOS4_FATTYPE(sptr); switch(dos_fattype) { case '1'+'6'*256: dos_fattype = 16; break; case '1'+'2'*256: default: dos_fattype = 12; break; } if( dos_spc < 1 ) dos_spc = 1; dos_clust0 = dir_sect + (dir_nentry+15)/16 - 2*dos_spc; if( disk_cyls == 0 ) { disk_spt = DOS_SPT(sptr); disk_heads = DOS_HEADS(sptr); } return 0; } #ifndef BUFFER_FAT static char * read_fat_sector(sector) int sector; { char * p; if( sector == sector_no ) return sector_buf; p = read_sector(sector); if(p) { memcpy(sector_buf, p, 512); sector_no = sector; return sector_buf; } else return 0; } #endif dev86-0.16.17/bootblocks/bb_init1.s0000644000000000000000000000036007617002151016572 0ustar rootroot00000000000000ORGADDR=0x0600 .org ORGADDR entry start public start start: cld xor ax,ax mov si,#$7C00 mov di,#ORGADDR mov ss,ax mov sp,si ! ax, di or si push ax pop ds push ax pop es mov cx,#256 rep movsw jmpi go,#0 go: dev86-0.16.17/bootblocks/unix.c0000644000000000000000000001111407712261100016042 0ustar rootroot00000000000000 #include "monitor.h" #ifdef __ELKS__ kbhit() { return 0; } getch() { return 3; } static int phy_fd = -1; static open_fd() { phy_fd = open("/tmp/ramdisk", 0); if( phy_fd < 0 ) { fprintf(stderr, "Cannot open /dev/ramdisk\n"); phy_fd= -2; } } _bios_disk_read(drive, cyl, head, sect, len, buffer) int drive, cyl, head, sect, len; char *buffer; { extern long lseek(); int rv = 0; long offset; int i; extern int disk_spt; int spt = 18; if( phy_fd == -1 ) open_fd(); if( phy_fd < 0 ) return -1; if( len <= 0 ) return -1; if( disk_spt > 1 ) spt = disk_spt; offset = (((cyl*2 + head)*(long)spt + sect-1)*512L); fprintf(stderr, "PHY_READ(d%d, c%d, h%d, s%d, l%d, b%d) (Sect=%ld)\n", drive, cyl, head, sect, len, buffer, offset/512); if( lseek(phy_fd, offset, 0) < 0 ) perror("Phyread lseek error\n"); for(i=0; i< len; i++) { rv = read(phy_fd, buffer, 512); if( rv < 0 ) perror("Phyread read error\n"); buffer+=512; } if( rv < 0 ) return -1; return 0; } _bios_disk_reset() { } motor_running() { return 1; } #if 0 putsect(buffer, address) char * buffer; int address; { fprintf(stderr, "Sector write from DS:%04x to 0000:%04x00\n", buffer, address); return 0; } #endif #endif /* crctab calculated by Mark G. Mendel, Network Systems Corporation */ static unsigned short crctab[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; /* * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. * NOTE: First srgument must be in range 0 to 255. * Second argument is referenced twice. * * Programmers may incorporate any or all code into their programs, * giving proper credit within the source. Publication of the * source routines is permitted so long as proper credit is given * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg, * Omen Technology. */ #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp) static unsigned short crc = 0; reset_crc() { crc = 0; } addcrc(buffer, len) unsigned char * buffer; int len; { while(len>0) { crc = updcrc((*buffer++), crc); len--; } } display_crc(str) char * str; { if( str ) printf("%s 0x%04x\n", str, crc); return crc; } dev86-0.16.17/bootblocks/monitor.h0000644000000000000000000000213007617131773016571 0ustar rootroot00000000000000 #include #include #include #include #include #include "i86_funcs.h" #include "readfs.h" #define X_TARFLOPPY #define X_DOSFLOPPY #define X_CALC_CRC #ifdef __STANDALONE__ #define NO_COLOUR extern union REGS __argr; #endif #ifdef TARFLOPPY #define SINGLEFS #define open_file tar_open_file #define rewind_file tar_rewind_file #define close_file tar_close_file #define file_length tar_file_length #define read_block tar_read_block #endif #ifdef MINFLOPPY #define SINGLEFS #define open_file min_open_file #define rewind_file min_rewind_file #define close_file min_close_file #define file_length min_file_length #define read_block min_read_block #endif #ifdef DOSFLOPPY #define SINGLEFS #define open_file dos_open_file #define rewind_file dos_rewind_file #define close_file dos_close_file #define file_length dos_file_length #define read_block dos_read_block #endif #ifdef SINGLEFS /* #define NOCOMMAND */ #define NOMONITOR #endif #ifdef __STANDALONE__ #undef putchar #define putchar putch #define printf cprintf #define fflush(x) #endif dev86-0.16.17/bootblocks/tarboot.s0000644000000000000000000002451607431537461016601 0ustar rootroot00000000000000! ! This is floppy bootblock to load the first item from a tar file. ! ! The tar file is constructed with a GNU TAR label at the start ! which is replaced with this by the makeboot.c program. ! ! The first item must be a Linux-8086 executable compiled with the -Ms option ! ! Copyright (C) 1996 Robert de Bath, distributed under the GPL Version 2. ! BOOTADDR= 0x7C00 ! The address that the boot seg is loaded. RELADDR = 0x0600 ! This is floppy, so we can relocate to 'super' address ! It appears the 0500 is also ok as that's DOS memory ! But then where can we get 200 bytes of stack! STACK = 0x0600 ! Inital stack, 0 makes bad_magic LOADSEG = 0x0080 ! Segment for program load, this must be 512b aligned ! The first 32 bytes are the a.out header. DEBUG=1 ! Print dots ... !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- macro locn if *-start>?1 fail! ?1 endif .blkb ?1 + start-* mend ! On startup from a floppy boot it`s probably best if we assume _nothing_ ! that we don`t have to ... ! ! So, `start` is, erm, right here :-) ! The boot block is re-loaded from the floppy for relocation. !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- use16 org RELADDR start: ! Don't even _think_ of changing this unless you're 110% sure! .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 .byte 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 block start .asciz "ENIAC" .byte $C0 endb ! All right, I'll help, you can use any of these chars: ! "/?@ABCDEFGHIJKLMNO" ! Others are likely to cause ... problems. !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Beware; the assumption is this code is relocatable. xor ax,ax mov ds,ax mov es,ax mov ss,ax if STACK = 0 mov sp,ax else mov sp,#STACK ! Stack location endif cld ! ASSUME ds=ss=es=cs=0 keep_trying1: ! Get the tar block after this program, and relocate this code. mov ax,#$0202 ! Read 2 sectors mov bx,#start ! Where this _should_ be mov cx,#$0001 ! From sector 1 xor dx,dx ! Of the floppy drive head zero int $13 jc keep_trying1 jmpi going,#0 going: ! OK. Code will now be run at correct address. if DEBUG call pboot endif mov al,tar_link cmp al,#'0 jnz nogood ! Make sure next item is file. call probe_floppy call get_size ! Get number of clicks in di test di,di jz nogood ! If it`s zero .. Hmm if STACK = 0 mov sp,#overstack ! Real bad magic :-) endif call load_sectors ! This requires that we have been relocated, so we can't call it too soon. nogood: push cs pop es hcode: mov ax,#$0201 ! Read 1 sector mov bx,#BOOTADDR ! into the boot area mov cx,#1 ! sector 1 mov dx,#$0080 ! hard drive head zero int $13 jc hcode ! Keep trying forever! jmpi BOOTADDR,#0 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! These are the number of sectors per track that will be scanned for. ! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on ! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. disksizes: .byte 36,32,21,18,15,9 ! End of part 1 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This is important bits of the TAR Block. ! The chksum field will need to be changed if any mods are done to this ! file so that the bare header is a TAR file. If it's installed using ! makeboot that program will correct the sum as it also changes the time. locn(100) blk_mode: .asciz " 4111" blk_uid: .blkb 8 blk_gid: .blkb 8 blk_size: .blkb 12 blk_mtime: .asciz "6141567743 " if DEBUG blk_chksum: .asciz " 142273" else blk_chksum: .asciz " 127270" endif blk_link: .byte 'V ! Sneaks here, overlay zero init vars on tar data. block blk_mode public sectors sectors: .blkw 1 ! bios_disk: .blkb 12 ! BPB for FD0 head: .word 0 ! current head track: .word 0 ! current track endb !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This code taken from the Linux bootsector and adjusted to suit ! ! Many BIOS's default disk parameter tables will not ! recognize multi-sector reads beyond the maximum sector number ! specified in the default diskette parameter tables - this may ! mean 7 sectors in some cases. ! ! Since single sector reads are slow and out of the question, ! we must take care of this by creating new parameter tables ! (for the first disk) in RAM. We will set the maximum sector ! count to 36 - the most we will encounter on an ED 2.88. ! ! High doesn't hurt. Low does. ! ! Segments are as follows: ds=es=ss=cs=0 ! probe_floppy: mov di,#bios_disk mov bx,#0x78 ! 0:bx is parameter table address push ds lds si,[bx] ! ds:si is source mov cl,#6 ! copy 12 bytes cld push di rep movsw pop di pop ds movb 4[di],*36 ! patch sector count mov [bx],di mov 2[bx],es ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. mov si,#disksizes ! table of sizes to try probe_loop: lodsb cbw ! extend to word mov sectors, ax cmp al,#9 je got_sectors ! if all else fails, try 9 xchg ax, cx ! cx = track and sector xor dx, dx ! drive 0, head 0 mov bx,#probe_buf ! address after setup (es = cs) mov ax,#0x0201 ! service 2, 1 sector int 0x13 jc probe_loop ! try next value got_sectors: ret !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This function reads the size of the first file in the TAR image. It's ! stored in octal in the tar header that was loaded just after this block. get_size: mov di,#tar_size xor dx,dx xor bx,bx xor cx,cx next_dig: mov al,[di] and al,#$F8 cmp al,#'0 jne no_dig mov al,[di] and al,#$07 mov cl,#3 mul_loop: sal bx,#1 ! Double prec * 8 rcl dx,#1 loop mul_loop or bl,al no_dig: inc di cmp di,#tar_mtime jne next_dig add bx,#15 ! How many clicks ? adc dx,cx ! AKA zero mov cl,#4 div_loop: shr dx,#1 rcr bx,#1 loop div_loop mov di,bx ret overstack: !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This is good so far, is it an 8086 a.out file ? ! If so start it. go_go_go: xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 mov si,[sectors] ! Save for monitor.out mov bx,#LOADSEG mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di] cmp ax,#0x0301 ! Right magic ? jnz bad_magic ! Yuk ... mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx ! Partition offset. inc bx inc bx ! bx = initial CS add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=* bad_magic: push bx ! jmpi 0,#LOADSEG+2 push di retf !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This isn't in a normal volume lable, no problem it leaves more space. ! ! locn(257) ! blk_magic: .ascii "ustar " ! .blkb 1 ! blk_uname: .ascii "TarBoot/Copyright" ! blk_uname_end: ! .blkb 32+blk_uname-blk_uname_end ! blk_gname: .ascii "R de Bath" ! blk_gname_end: ! .blkb 32+blk_gname-blk_gname_end ! blk_devmaj: .blkb 8 ! blk_devmin: .blkb 8 ! !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- if DEBUG dot: mov al,#'. putc: push bx mov bx,#7 mov ah,#$E int $10 pop bx ret endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This code taken from the Linux bootsector and adjusted to suit ! ! This routine loads the system at address LOADSEG, making sure ! no 64kB boundaries are crossed. We try to load it as fast as ! possible, loading whole tracks whenever we can. ! ! LOADSEG must be sector aligned and sectors will be loaded upto ! the next 64k boundry past the segment specified by DI. load_sectors: if LOADSEG & $F000 = 0 xor ax,ax else mov ax,#LOADSEG & $F000 ! segment to load to endif mov es,ax ! dx=sectors read of current track ! bx=offset in memory of block ! si=sectors read to block ! al=number to read read_it: mov dx,#2 ! Volume lable + tar header if LOADSEG & $0FFF = 0 xor si,si else mov si,#(LOADSEG & $FFF)>>5 endif add di,#LOADSEG rp_read: if DEBUG call dot endif mov ax,es cmp ax,di ! have we loaded all yet? jbe ok1_read jmp go_go_go ! Loaded, run it. ok1_read: mov ax,sectors ! nr of sectors/track sub ax,dx ! remaining of track mov cx,ax ! cx= remaining add cx,si ! boundary check cmp cl,#128 jbe ok2_read ! ! to much-> fill block mov ax,#128 ! ax=0 sub ax,si ! so much may be read ok2_read: mov bx,si mov cx,#9 shl bx,cl call read_track ! do it mov cx,ax ! cl=read blocks add ax,dx ! ax=new sectors cmp ax,sectors ! track done? jne ok3_read mov ax,#1 ! yes sub ax,head jne ok4_read ! next head inc track ! next track ok4_read: mov head,ax xor ax,ax ok3_read: mov dx,ax add si,cx cmp si,#128 jne rp_read mov ax,es add ah,#0x10 mov es,ax xor si,si jmp rp_read read_track: push dx push ax push bx mov cx,dx mov dx,track inc cx mov ch,dl mov dx,head mov dh,dl and dx,#0x0100 mov ah,#2 int 0x13 ! ah=02h al=nr sectors to read ! ch=cylinder ! cl=sector ! dh=head ! dl=drive ! es:bx=buffer jc bad_rt pop bx pop ax pop dx ret bad_rt: xor ah,ah xor dl,dl int 0x13 pop bx pop ax pop dx jmp read_track !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! This is the GNU-TAR 'isextended' field. It must be zero or gtar goes apeshit. locn(482) .byte 0 !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- if DEBUG pboot: mov si,#blk_load nextc: lodsb call putc cmp al,#0 jnz nextc ret endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This isn't a hard disk boot sector but give it an HD magic anyway. locn(510) .word 0xAA55 ! From here down is where we load stuff. locn(512) blk_load: ! Address of block load tar_name: .blkb 100 tar_mode: .blkb 8 tar_uid: .blkb 8 tar_gid: .blkb 8 tar_size: .blkb 12 tar_mtime: .blkb 12 tar_chksum: .blkb 8 tar_link: .blkb 1 ! "0" tar_linkname: .blkb 100 tar_magic: .blkb 8 ! "ustar " tar_uname: .blkb 32 tar_gname: .blkb 32 tar_devmaj: .blkb 8 tar_devmin: .blkb 8 tar_padd: locn(1024) probe_buf: .blkb 512 dev86-0.16.17/bootblocks/minix.h0000644000000000000000000001117306715507522016232 0ustar rootroot00000000000000/****************************************************************************/ /* Super block table. The root file system and every mounted file system * has an entry here. The entry holds information about the sizes of the bit * maps and inodes. The s_ninodes field gives the number of inodes available * for files and directories, including the root directory. Inode 0 is * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4 * for files and directories. The disk layout is: * * Item # blocks * boot block 1 * super block 1 * inode map s_imap_blocks * zone map s_zmap_blocks * inodes (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK * unused whatever is needed to fill out the current zone * data zones (s_nzones - s_firstdatazone) << s_log_zone_size * * A super_block slot is free if s_dev == NO_DEV. */ #define BLOCK_SIZE 1024 /* # bytes in a disk block */ /* Flag bits for i_mode in the inode. */ #define I_TYPE 0170000 /* this field gives inode type */ #define I_REGULAR 0100000 /* regular file, not dir or special */ #define I_BLOCK_SPECIAL 0060000 /* block special file */ #define I_DIRECTORY 0040000 /* file is a directory */ #define I_CHAR_SPECIAL 0020000 /* character special file */ #define I_SET_UID_BIT 0004000 /* set effective uid on exec */ #define I_SET_GID_BIT 0002000 /* set effective gid on exec */ #define ALL_MODES 0006777 /* all bits for user, group and others */ #define RWX_MODES 0000777 /* mode bits for RWX only */ #define R_BIT 0000004 /* Rwx protection bit */ #define W_BIT 0000002 /* rWx protection bit */ #define X_BIT 0000001 /* rwX protection bit */ #define I_NOT_ALLOC 0000000 /* this inode is free */ /* Type definitions */ typedef unsigned short unshort; /* must be 16-bit unsigned */ typedef unshort block_nr; /* block number */ typedef unshort inode_nr; /* inode number */ typedef unshort zone_nr; /* zone number */ typedef unshort bit_nr; /* if inode_nr & zone_nr both unshort, then also unshort, else long */ typedef unshort sect_nr; typedef long zone_type; /* zone size */ typedef unshort mask_bits; /* mode bits */ typedef unshort dev_nr; /* major | minor device number */ typedef char links; /* number of links to an inode */ typedef long real_time; /* real time in seconds since Jan 1, 1970 */ typedef long file_pos; /* position in, or length of, a file */ typedef short uid; /* user id */ typedef char gid; /* group id */ /* Tables sizes */ #define NR_ZONE_NUMS 9 /* # zone numbers in an inode */ #define NAME_SIZE 14 /* # bytes in a directory component */ /* Miscellaneous constants */ #define SUPER_MAGIC 0x137F /* magic number contained in super-block */ #define SUPER_MAGIC2 0x138F /* Secondary magic 30 char names */ #define BOOT_BLOCK (block_nr)0 /* block number of boot block */ #define SUPER_BLOCK (block_nr)1 /* block number of super block */ #define ROOT_INODE (inode_nr)1 /* inode number for root directory */ /* Derived sizes */ #define NR_DZONE_NUM (NR_ZONE_NUMS-2) /* # zones in inode */ #define INODES_PER_BLOCK (BLOCK_SIZE/sizeof(d_inode)) /* # inodes/disk blk */ #define NR_INDIRECTS (BLOCK_SIZE/sizeof(zone_nr)) /* # zones/indir blk */ #define INTS_PER_BLOCK (BLOCK_SIZE/sizeof(int)) /* # integers/blk */ struct super_block { inode_nr s_ninodes; /* # usable inodes on the minor device */ zone_nr s_nzones; /* total device size, including bit maps etc */ unshort s_imap_blocks; /* # of blocks used by inode bit map */ unshort s_zmap_blocks; /* # of blocks used by zone bit map */ zone_nr s_firstdatazone; /* number of first data zone */ short s_log_zone_size; /* log2 of blocks/zone */ file_pos s_max_size; /* maximum file size on this device */ short s_magic; /* magic number to recognize super-blocks */ } ; /* Type definitions local to the File System. */ typedef struct { /* directory entry */ inode_nr d_inum; /* inode number */ char d_name[NAME_SIZE]; /* character string */ } dir_struct; /* Declaration of the disk inode used in rw_inode(). */ typedef struct { /* disk inode. Memory inode is in "inotab.h" */ mask_bits i_mode; /* file type, protection, etc. */ uid i_uid; /* user id of the file's owner */ file_pos i_size; /* current file size in bytes */ real_time i_modtime; /* when was file data last changed */ gid i_gid; /* group number */ links i_nlinks; /* how many links to this file */ zone_nr i_zone[NR_ZONE_NUMS]; /* block nums for direct, ind, and dbl ind */ } d_inode; dev86-0.16.17/bootblocks/buffer.c0000644000000000000000000000656307474170551016362 0ustar rootroot00000000000000 #include "monitor.h" #ifndef MAXTRK #define MAXTRK 18 #endif int disk_drive = 0; int disk_spt = 7; int disk_heads = 0; int disk_cyls = 0; long disk_partition_offset = 0; static long bad_start = -1; static long buf_start = -1; static int buf_sec = 0; static int buf_len = 0; static char buffer[MAXTRK*512]; /* WARNING: This must be DMAable */ void reset_disk() { disk_spt = 7; /* Defaults for reading floppy boot area. */ disk_heads = 0; disk_cyls = 0; bad_start = -1; disk_partition_offset = 0; #ifdef __STANDALONE__ if( disk_drive == __argr.h.dl && __argr.x.si >= 9 && __argr.x.si <= 63 ) { disk_spt = __argr.x.si; disk_heads = 2; disk_cyls = 80; } if( disk_drive & 0x80 ) { /* Hard disk, get parameters from bios */ long dpt; int v; if( disk_drive == __argr.h.dl ) disk_partition_offset = __argr.x.cx + ((long)__argr.h.dh<<16); dpt = _bios_get_dpt(disk_drive); v = ((dpt>>16) & 0xFF); if( v != 0xFF && v > (disk_drive&0x7F) ) { disk_spt = (dpt & 0x3F); /* Max sector number 1-63 */ if( disk_spt == 0 ) disk_spt = 64; /* 1-64 ? */ disk_heads = ((dpt>>24) & 0xFF) + 1; /* Head count 1-256 */ disk_cyls = ((dpt>>8) & 0xFF) + ((dpt<<2) & 0x300) + 1; /* Cyls count, unchecked, only needs != 0, if AMI 386 bios can be * upto 4096 cylinder, otherwise BIOS limit is 1024 cyl. */ } } #endif } char * read_lsector(sectno) long sectno; { int tries; int rv = 0; int phy_s = 1; int phy_h = 0; int phy_c = 0; long bstart; if( sectno == 0 || disk_heads == 0 ) reset_disk(); if( disk_partition_offset > 0 ) sectno += disk_partition_offset; if( disk_spt < 1 || disk_heads < 1 ) phy_s = sectno; else { phy_s = sectno%disk_spt; phy_h = sectno/disk_spt%disk_heads; phy_c = sectno/disk_spt/disk_heads; bstart = (long)phy_c*disk_heads+phy_h; if (disk_spt > MAXTRK) { bstart = bstart * (disk_spt+MAXTRK-1)/MAXTRK; buf_sec = phy_s/MAXTRK; bstart = bstart + buf_sec; buf_sec *= MAXTRK; if (disk_spt > buf_sec+MAXTRK) buf_len = MAXTRK; else buf_len = disk_spt-buf_sec; } else { buf_sec = 0; buf_len = disk_spt; } if( bstart != buf_start && bstart != bad_start && buf_len > 1 ) { rv = _bios_disk_read(disk_drive,phy_c,phy_h,buf_sec+1,buf_len,buffer); if( rv == 0 ) buf_start = bstart; else { bad_start = bstart; buf_start = -1; } #ifdef DEBUG printf("Track read %d,%d,%d,%d,%d,%d -> %d\n", disk_drive,phy_c,phy_h,buf_sec+1,buf_len,buffer, rv); #endif } if( bstart == buf_start ) return buffer + (phy_s-buf_sec) * 512; } tries = 6; do { if( rv && tries<0) { int v; printf("Disk error 0x%02x %d:%d:%d:%d[%2d] -> 0x%04x[]\n", rv, disk_drive, phy_c, phy_h, phy_s+1, 1, buffer); printf("Retry ?"); v = (getch()&0x7F); printf("\n"); if (v == 3 || v == 27 || v == 'n' || v == 'N') return 0; tries = 6; } if (tries == 3) _bios_disk_reset(disk_drive); rv = _bios_disk_read(disk_drive, phy_c, phy_h, phy_s+1, 1, buffer); tries--; } while(rv); #ifdef DEBUG printf("Sector read %d,%d,%d,%d,%d,%d -> %d\n", disk_drive,phy_c,phy_h,phy_s+1,1,buffer, rv); #endif if(rv) return 0; else return buffer; } dev86-0.16.17/bootblocks/Makefile0000644000000000000000000000714610004447452016371 0ustar rootroot00000000000000 HOSTCC=cc HOSTCCFLAGS=-O BCC=bcc AS86=as86 DEFS= CC=$(BCC) CFLAGS=-ansi -Ms -Oi -O $(DEFS) LDFLAGS=-s -i -H0x10000 ASFLAGS=-0 -w MINIXDEFS=-DDOTS # CFLAGS=-ansi -Ms $(DEFS) # LST=-l $*.lst default: makeboot makeboot.com monitor.sys minix_elks.bin lsys.com all: bootbin bootsys default tgz bootsys: bootfile.sys boottar.sys bootminix.sys monitor.sys boot_win.sys CSRC=minix.c SSRC=sysboot.s tarboot.s skip.s mbr.s msdos.s noboot.s \ boot_fpy.s killhd.s bb_linux.s bb_init1.s bb_init2.s encap: $(SSRC:s=v) $(CSRC:c=v) minixhd.v msdos16.v bootbin: $(SSRC:s=bin) $(CSRC:c=bin) minixhd.bin msdos16.bin minix_elks.bin MOBJ=monitor.o commands.o i86_funcs.o relocate.o help.o bzimage.o \ buffer.o unix.o fs.o fs_tar.o fs_min.o fs_dos.o MSRC=monitor.c commands.c i86_funcs.c relocate.c help.c bzimage.c \ buffer.c unix.c fs.c fs_tar.c fs_min.c fs_dos.c MINC=i86_funcs.h readfs.h monitor.h BOOTBLOCKS=sysboot.v noboot.v skip.v msdos.v msdos16.v \ tarboot.v minix.v minixhd.v mbr.v killhd.v EXTRAS=minix.h zimage.s minix_elks.c lsys.c boot_win.c install: makeboot install -m 755 -s makeboot $(DIST)$(PREFIX)/bin/makeboot monitor.com: $(MOBJ) $(CC) $(CFLAGS) $(LDFLAGS) $(MONDEFS) -d $(MOBJ) -o monitor.com -M > monitor.sym monitor.out: $(MOBJ) $(CC) $(CFLAGS) $(LDFLAGS) $(MONDEFS) $(MOBJ) -o monitor.out -M > monitor.sym $(MOBJ): $(MINC) fs_min.o: minix.h bootfile.sys: $(MSRC) $(MINC) @rm -f $(MOBJ) make 'CFLAGS=$(CFLAGS) -DDOSFLOPPY' monitor.out mv monitor.out bootfile.sys @rm -f $(MOBJ) boottar.sys: $(MSRC) $(MINC) tarboot.bin @rm -f $(MOBJ) make 'CFLAGS=$(CFLAGS) -DTARFLOPPY' monitor.out mv monitor.out boottar.sys @rm -f $(MOBJ) bootminix.sys: $(MSRC) $(MINC) minix.bin @rm -f $(MOBJ) make 'CFLAGS=$(CFLAGS) -DMINFLOPPY' monitor.out mv monitor.out bootminix.sys @rm -f $(MOBJ) monitor.sys: $(MSRC) $(MINC) @rm -f $(MOBJ) make monitor.out mv monitor.out monitor.sys @rm -f $(MOBJ) monitor: $(MSRC) $(MINC) @rm -f $(MOBJ) make 'CFLAGS=-ansi $(DEFS)' monitor.out mv monitor.out monitor @rm -f $(MOBJ) bzimage.o: bzimage.c zimage.v minix.s: minix.c Makefile $(CC) -Mf -O -DTRY_FLOPPY $(MINIXDEFS) -S minix.c minix_elks.s: minix_elks.c Makefile minix.v $(CC) -Mf -O $(MINIXDEFS) -S minix_elks.c minixhd.s: minix.c Makefile $(CC) -Mf -O -DHARDDISK $(MINIXDEFS) -S minix.c -o minixhd.s msdos16.s: msdos.s sed 's/^fatbits=12/fatbits=16/' < msdos.s > msdos16.s mbr_dm.s: mbr.s sed -e 's/^diskman=0/diskman=1/' \ -e 's/^message=1/message=0/' \ -e 's/^mbrkey=1/mbrkey=0/' \ -e 's/^preboot=1/preboot=0/' \ < mbr.s > mbr_dm.s boot_win.sys: boot_win.c $(CC) -Ms -H0x6000 -s boot_win.c -o boot_win.sys makeboot: makeboot.c $(BOOTBLOCKS) $(HOSTCC) $(HOSTCCFLAGS) -o makeboot makeboot.c makeboot.com: makeboot.c $(BOOTBLOCKS) $(CC) -Md -O -o makeboot.com makeboot.c lsys.com: lsys.c msdos.v msdos16.v $(CC) -Md -O -o lsys.com lsys.c clean realclean: rm -f bootfile.sys boottar.sys bootminix.sys monitor.sys boot_win.sys rm -f monitor makeboot bootblocks.tar.gz rm -f minix.s minixhd.s minix_elks.s msdos16.s mbr_dm.s rm -f *.com *.o *.bin *.out *.lst *.sym *.v *.tmp tgz: minix.bin monitor.sys makeboot.com makeboot tar cfV bootblocks.tar ENIAC monitor.sys \ README Makefile \ $(MSRC) \ $(MINC) \ makeboot.c $(CSRC) \ $(SSRC) \ makeboot.com minix.bin \ $(EXTRAS) makeboot tar bootblocks.tar gzip -f9 bootblocks.tar distribution: tar czf /tmp/bootblocks.tar.gz \ README Makefile $(MSRC) $(MINC) makeboot.c $(CSRC) $(SSRC) $(EXTRAS) .SUFFIXES: .bin .v .s.bin: $(AS86) -w- -0 -b $*.bin -s $*.sym $*.s $(LST) .s.v: as86_encap $*.s $*.v $*_ $(ASFLAGS) $(LST) dev86-0.16.17/bootblocks/fs_min.c0000644000000000000000000001223506725753604016361 0ustar rootroot00000000000000 #include "monitor.h" #include "minix.h" /* #define DEBUG 1 /**/ #define SECTOR_SIZE 512 block_nr inode_tbl = 0; /* super.s_imap_blocks+super.s_zmap_blocks+2 */ static int fs_dir32 = 0; /* Using 30 char filenames ? */ struct file_pos { inode_nr inode; zone_nr seek_addr; file_pos i_size; /* current file size in bytes */ mask_bits i_mode; /* File type */ zone_nr i_zone[NR_ZONE_NUMS]; /* block numbers from inode */ } current_file = { 0,0 }; static int first_time = 1; static inode_nr current_dir = ROOT_INODE; static block_nr fs_ind = 0; static block_nr fs_block = 0; static char fs_buf[BLOCK_SIZE]; /* For storing inodes and ind sectors */ static min_inode_open(); #define b_super(x) ((struct super_block *)(x)) #define b_dir(x) ((dir_struct*)(x)) min_open_file(fname) char * fname; { char * sptr; if( disk_heads == 0 ) return -1; if( (sptr = read_sector(SUPER_BLOCK*BLOCK_SIZE/SECTOR_SIZE)) == 0 ) return -1; /* Check super */ if(b_super(sptr)->s_magic == SUPER_MAGIC ) fs_dir32 = 0; else if(b_super(sptr)->s_magic == SUPER_MAGIC2 ) fs_dir32 = 16; else return -1; inode_tbl = b_super(sptr)->s_imap_blocks+b_super(sptr)->s_zmap_blocks+2; /* Check for boot directory */ current_dir = ROOT_INODE; if( min_name_open("boot") >= 0 && current_file.i_mode == I_DIRECTORY ) current_dir = current_file.inode; #ifdef DEBUG fprintf(stderr, "Opening minix file <%d>/%s[1,%d]\n", current_dir,fname,fs_dir32+14); #endif return min_name_open(fname); } static min_name_open(fname) char * fname; { int do_dir = 0; char dirbuf[1024]; long len; int v; inode_nr file_inode = 0; if( strcmp(fname, ".") == 0 ) do_dir = 1; /* open current_dir inode */ if( min_inode_open(current_dir) < 0 ) return -1; /* scan for file */ for(len = min_file_length(); len>0; len-=1024) { if( min_read_block(dirbuf) < 0 ) break; for(v=0; v<1024; v+= 16+fs_dir32) { if( b_dir(dirbuf+v)->d_inum == 0 ) continue; #ifndef NOCOMMAND if( do_dir ) { if( b_dir(dirbuf+v)->d_name[0] == '.' ) continue; if( fs_dir32 ) printf("%.30s\n", b_dir(dirbuf+v)->d_name); else printf("%.14s\n", b_dir(dirbuf+v)->d_name); } else #endif if( strncmp(b_dir(dirbuf+v)->d_name, fname,14+fs_dir32) ==0) { file_inode = b_dir(dirbuf+v)->d_inum; break; } } } /* open */ if( file_inode ) { if( min_inode_open(file_inode) >= 0 ) return 0; } return -1; } static min_inode_open(inode) int inode; { int inode_sector = inode_tbl*BLOCK_SIZE/SECTOR_SIZE; d_inode * sptr = 0; int i; min_close_file(); inode--; inode_sector += inode/(SECTOR_SIZE/sizeof(d_inode)); if( (sptr = read_sector(inode_sector)) == 0 ) return -1; sptr += inode%(SECTOR_SIZE/sizeof(d_inode)); current_file.i_mode = (sptr->i_mode & I_TYPE); if( current_file.i_mode != I_REGULAR && current_file.i_mode != I_DIRECTORY ) return -1; current_file.i_size = sptr->i_size; for(i=0; ii_zone[i]; current_file.inode = inode+1; return 0; } min_rewind_file() { current_file.seek_addr = 0; return 0; } min_close_file() { if( current_file.inode == 0 ) return -1; current_file.inode = 0; current_file.seek_addr = 0; fs_ind = 0; return 0; } long min_file_length() { if( current_file.inode == 0 ) return -1; return current_file.i_size; } min_read_block(buffer) char * buffer; { block_nr block_no; if( current_file.seek_addr < NR_DZONE_NUM ) block_no = current_file.i_zone[current_file.seek_addr]; else if( current_file.seek_addr < NR_DZONE_NUM + NR_INDIRECTS ) { if( fs_block != current_file.i_zone[NR_DZONE_NUM] ) { block_no = current_file.i_zone[NR_DZONE_NUM]; read_fs_block(block_no, fs_buf); fs_block = current_file.i_zone[NR_DZONE_NUM]; fs_ind = 0; } block_no = ((zone_nr*)fs_buf)[current_file.seek_addr-NR_DZONE_NUM]; } else { int ind_block; ind_block = current_file.seek_addr - NR_DZONE_NUM - NR_INDIRECTS; if( fs_ind != ind_block/NR_INDIRECTS + 1 ) { block_no = current_file.i_zone[NR_DZONE_NUM+1]; read_fs_block(block_no, fs_buf); fs_block = current_file.i_zone[NR_DZONE_NUM+1]; block_no = ((zone_nr*)fs_buf)[ind_block/NR_INDIRECTS]; read_fs_block(block_no, fs_buf); fs_block = current_file.i_zone[NR_DZONE_NUM]; fs_ind = ind_block/NR_INDIRECTS + 1; } block_no = ((zone_nr*)fs_buf)[ind_block%NR_INDIRECTS]; } current_file.seek_addr++; read_fs_block(block_no, buffer); return 0; } read_fs_block(block_no, buffer) block_nr block_no; char * buffer; { long sector_no; char * sptr; if( block_no == 0 ) goto zappit; sector_no = ((long)block_no) * BLOCK_SIZE/SECTOR_SIZE; sptr = read_sector(sector_no); if( sptr ) memcpy(buffer, sptr, SECTOR_SIZE); else goto zappit; sptr = read_sector(sector_no+1); if( sptr ) memcpy(buffer+SECTOR_SIZE, sptr, SECTOR_SIZE); else goto zappit; return; zappit:; memset(buffer, '\0', 1024); } dev86-0.16.17/bootblocks/sysboot.s0000644000000000000000000000451607154266574016635 0ustar rootroot00000000000000 ! The master boot sector will have setup a stack, ! this is normally at 0:7c00 down. ! DS, SS, CS and ES will all have value 0 so the execution address is 0:7c00 ! On entry the register SI will be pointer to the partition entry that ! this sector was loaded from, DL is the drive. ! Also if it's a standard Master boot DH will be the head, CX will be the ! sector and cylinder, BX=7C00, AX=1, DI=7DFE, BP=SI. There's a reasonable ! chance that this isn't true though. ! The Master boot itself will have been loaded and run at $07c00 ! The BIOS must have setup a stack because interrupts are enabled ! Little else can be assumed because DOS doesn`t assume anything either sysboot_start: j codestart nop ! DOS appears to _require_ this to identify an MSDOS disk!! .blkb sysboot_start+3-* public dosfs_stat dos_sysid: .ascii "LINUX" ! System ID .byte 0,0,0 dosfs_stat: dos_sect: .blkw 1 ! Sector size dos_clust: .blkb 1 ! Cluster size dos_resv: .blkw 1 ! Res-sector dos_nfat: .blkb 1 ! FAT count dos_nroot: .blkw 1 ! Root dir entries dos_maxsect: .blkw 1 ! Sector count (=0 if large FS) dos_media: .blkb 1 ! Media code dos_fatlen: .blkw 1 ! FAT length dos_spt: .blkw 1 ! Sect/Track dos_heads: .blkw 1 ! Heads dos_hidden: .blkw 2 ! Hidden sectors ! Here down is DOS 4+ and probably not needed for floppy boots. dos4_maxsect: .blkw 2 ! Large FS sector count dos4_phy_drive: .blkb 1 ! Phys drive .blkb 1 ! Reserved .blkb 1 ! DOS 4 floppy_temp: dos4_serial: .blkw 2 ! Serial number dos4_label: .blkb 11 ! Disk Label (DOS 4+) dos4_fattype: .blkb 8 ! FAT type ! ! This is where the code will be overlaid, the default is a hang .blkb sysboot_start+0x3E-* public codestart codestart: j codestart ! Partition table public bootblock_magic .blkb sysboot_start+0x1BE-* partition_1: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1CE-* partition_2: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1DE-* partition_3: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1EE-* partition_4: .blkb 8 ! IN,SH,SS,ST,OS,EH,ES,ET .blkw 2 ! Linear position (0 based) .blkw 2 ! Linear length .blkb sysboot_start+0x1FE-* bootblock_magic: .word 0xAA55 dev86-0.16.17/bootblocks/commands.c0000644000000000000000000001163207431454374016704 0ustar rootroot00000000000000 #include "monitor.h" int cmd_type(ptr) char * ptr; { char * fname; char buffer[1024]; long len; while(*ptr == ' ') ptr++; if( (fname=ptr) == 0 ) return 0; while(*ptr & *ptr != ' ') ptr++; if( open_file(fname) >= 0 ) for(len=file_length(); len>0; len-=1024) { if( read_block(buffer) < 0 ) break; if( len > 1024 ) write(1, buffer, 1024); else write(1, buffer, len); } else printf("Cannot open file '%s'\n", fname); close_file(); return 0; } #ifndef NOCOMMAND extern unsigned int current_address; extern int number_base; int cmd_quit(args) char * args; { printf("Bye\n"); exit(0); } int cmd_nop(ptr) char * ptr; { } int cmd_dir(ptr) char * ptr; { open_file("."); return 0; } int cmd_more(ptr) char * ptr; { char * fname; char buffer[1024]; long len; int cc; char * sptr; while(*ptr == ' ') ptr++; if( (fname=ptr) == 0 ) return 0; while(*ptr & *ptr != ' ') ptr++; more_char(-1); if( open_file(fname) >= 0 ) for(len=file_length(); len>0; len-=1024) { if( read_block(buffer) < 0 ) break; if( len > 1024 ) cc = 1024; else cc = len; for(sptr=buffer; cc>0 ; cc--,sptr++) { if( more_char(*sptr & 0xFF) < 0 ) goto break_break; } } else printf("Cannot open file '%s'\n", fname); break_break:; close_file(); return 0; } more_char(ch) int ch; { static int line_number = 0; if( ch == -1 ) { line_number = 0; return 0; } if( (ch & 0xE0 ) || ch == '\n' ) putchar(ch); if( ch == '\n' && ++line_number == 24) { char buf[4]; printf("More ?"); fflush(stdout); if( read(0, buf, 1) <= 0 ) return -1; if( buf[0] == 3 || buf[0] == '\033' || buf[0] == 'q' || buf[0] == 'Q' ) return -1; if( buf[0] == '\r' ) line_number--; if( buf[0] == ' ' ) line_number=2; printf("\r \r"); } return 0; } more_strn(str, len) char * str; int len; { for(; len>0 && *str ; len--,str++) if( more_char( *str & 0xFF ) < 0 ) return -1; return 0; } #endif /**************************************************************************/ #ifndef NOMONITOR cmd_monhelp() { static char * helps[] = { "Monitor help\n", "zimage filename [args] Start Linux-386\n", "bzimage filename [args] Start Linux-386\n", "=filename [args] Start Linux-386\n", "quit Reboot\n", "help Display help file\n", "dir Display directory\n", "type Display file to screen\n", "more Display file to screen\n", "m[em] [address] Hexdump memory\n", "seg [val] Set/show default segment\n", "rel [segment] Relocate this program\n", "base [val] Set default number base (or 'n' cmd)\n", "init Re-init program\n", "r[egs] Display register values\n", 0 }; char **p = helps; more_char(-1); while(*p) if( more_strn(*p, strlen(*p)) <0 ) break; else p++; printf("\n"); return 0; } cmd_regs() { #ifdef __STANDALONE__ printf(": AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x", __argr.x.ax, __argr.x.bx, __argr.x.cx, __argr.x.dx, __argr.x.si, __argr.x.di); printf(" CF=%x", __argr.x.cflag); printf(" CS=%04x DS=%04x ES=%04x\n", __get_cs(), __get_ds(), __get_es()); #else printf("Only in standalone\n"); #endif } int cmd_memdump(ptr) char * ptr; { int count = 128; int i,j; int es = __get_es(); #define rmem(x) __peek_es( (x)+current_address ) getnum(&ptr, ¤t_address); getnum(&ptr, &count); for(i=0; i= ' ' && rmem(j) <= '~' ) putchar(rmem(j)); else putchar('.'); putchar('\n'); current_address += 16; current_address &= 0xFFFF; } #undef rmem } int cmd_seg(ptr) char * ptr; { int es = __get_es(); if( getnum(&ptr, &es) ) { __set_es(es); current_address = 0; } else printf("Current segment 0x%04x\n", es); return 0; } int cmd_set_base(ptr) { int obase = number_base; int nbase; number_base = 10; if( getnum(&ptr, &nbase) ) { if( nbase < 2 || nbase > 36 ) printf("Can't use that base\n"); else obase = nbase; } else printf("Current base is %d\n", obase); number_base = obase; return 0; } int cmd_rel(ptr) char * ptr; { int nseg = 0xFFFF; int cs = __get_cs(); getnum(&ptr, &nseg); relocator(nseg); if( __get_cs() == cs ) printf("Didn't relocate; CS=$%04x DS=$%04x\n", __get_cs(), __get_ds()); else printf("Relocated to CS=$%04x DS=$%04x\n", __get_cs(), __get_ds()); } #endif dev86-0.16.17/bootblocks/skip.s0000644000000000000000000000253007444643345016070 0ustar rootroot00000000000000! ! This floppy bootblock bypasses the floppy boot ... ! BOOTDISK = 0x80 ORGADDR = $0600 use16 org ORGADDR start: include sysboot.s org dos_sysid .ascii "BOOT C" ! System ID org codestart cli ! Assume _nothing_! cld mov bx,#$7C00 ! Pointer to start of BB. xor ax,ax ! Segs all to zero mov ds,ax mov es,ax mov ss,ax mov sp,bx ! SP Just below BB mov cx,#$100 ! Move 256 words mov si,bx ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw jmpi cont,#0 ! Set CS:IP correct. cont: sti ! Let the interrupts back in. mov si,#mesg call prtmsg mov di,#5 hcode: mov bx,#$7C00 ! Pointer to start of BB. mov ax,#$0201 ! Read 1 sector mov cx,#$0001 ! From sector 1 mov dx,#BOOTDISK ! Of the hard drive head zero int $13 jc error jmpi $7c00,0 error: mov si,#mesg2 call prtmsg dec di jz reboot mov si,#mesg3 call prtmsg jmp hcode prtmsg: lodsb cmp al,#0 jz EOS mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp prtmsg EOS: ret reboot: mov si,#mesg4 call prtmsg xor ax,ax int $16 jmpi $0,$FFFF ! Reboot. mesg2: .asciz "Disk error\r\n" mesg3: .asciz "Retrying\r\n" mesg4: .asciz "Press a key:" export mesg if BOOTDISK = 0x80 mesg: .asciz "Bypassing floppy boot\r\n" else mesg: .asciz "Booting drive two\r\n" endif dev86-0.16.17/bootblocks/boot_fpy.s0000644000000000000000000001233107474160557016745 0ustar rootroot00000000000000! This binary is for loading a dev86 a.out file from a floppy without ! a filesystem; to make a bootable disk just do: ! ! cat boot_fpy.bin monitor.out > /dev/fd0 ! ORGADDR=0x0600 EXEADDR=0x0800 ! This must be up to 0x7E0 or 0x0800 LOADSEG=0x0080 ! Must be 512b aligned for DMA ! Padding so you can join with 'cat'. .org EXEADDR-1 .byte 0 ! This marker is needed by many boot managers (and bochs) but the BIOS does ! NOT require it on a floppy. if EXEADDR=0x0800 .org ORGADDR+0x1FE .word 0xAA55 endif .org ORGADDR entry start public start start: xor ax,ax mov si,#$7C00 mov di,#ORGADDR mov ss,ax mov sp,di ! Or si or ax push ax pop ds push ax pop es mov cx,#256 cld rep movsw jmpi go,#0 go: ! Grrr, have to load sector 1 in by hand. if EXEADDR=0x0800 Loopi: mov ax,#$0201 ! Read 1 sector mov bx,#EXEADDR ! Into EXEADDR mov cx,#$0002 ! From sector 2 xor dx,dx ! Of the floppy drive head zero int $13 jc Loopi endif mov si,#Boot_message call puts mov ax,[a_text] ! How many sectors to load mov cl,#4 shr ax,cl mov bx,ax mov ax,[a_data] mov cl,#4 shr ax,cl add ax,bx add ax,#$1F mov cl,#5 shr ax,cl ! ax = sectors to read ! This routine starts by loading one sector at a time, with most ! modern PCs the processor is fast enough to keep up with single ! sector reads, in reality an 8Mhz 286 can keep up! ! But occasionally some older machines have really poor BIOSes ! (Some modern ones too) so once we know how many sectors to read ! we switch to reading a track at a time. But we only try it once ! for each track. Normally, as long as the load address is sector ! aligned, this will work every time but with some BIOSes we can't ! read a track without messing with the BPB so if the track read ! fails it's one try we fall back to sector reads. ! ! Overall this usually gives good performance, and with a BIOS that ! isn't completely broken and correctly formatted floppies will run ! at about 2.5 rotations per cylinder (1.25 per track). If you find ! your BIOS is one of the bad ones you'll have to format your disks ! to a 2:1 interleave. ! ! BTW: It's very easy to make superformat incorrectly calculate the ! inter-sector gaps so it ends up squeezing the sectors to the start ! of the track. This means that only a full track read is fast enough. ! I suggest you use fdformat as it always uses 'safe' parameters for ! a 1440k floppy. ! AX = count of sectors mov cx,#2 ! CX = First sector mov bx,#LOADSEG ! ES:BX = Where to load mov es,bx xor bx,bx ! Initial offset xor dx,dx ! DX = Drive 0 ! ax=cnt, dl=drv, ch=*, dh=*, cl=sec, es:bx=buffer. read_data: mov si,ax ! Save big count. xor ch,ch xor dh,dh mov maxsect,cl ! Save first sector. load_loop: mov di,#5 ! Error retry. sect_retry: mov ax,#$0201 ! ah=2, al=1, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer. int $13 jnc next_sect dec di ! Retry counter jz sect_error cmp cl,maxsect ! If this is first sector or previously ok sector jle sect_retry ! number then retry. mov maxsect,cl j inc_trk next_sect: mov ax,es ! Inc load address. add ax,#32 mov es,ax dec si ! Had enough ? jz all_loaded inc_sect: inc cl cmp cl,maxsect jnz load_loop inc_trk: ! Reached end of track, seek to next. mov cl,#1 xor dh,cl jnz load_track inc ch load_track: cmp si,maxsect ! Is the whole track needed ? jb load_loop ! no, goto load_loop for 1 by 1 ! Try to load the track _once_ only, if it fails go 1 by 1 again. mov ax,maxsect dec ax mov ah,#$02 ! ah=2, al=*, dl=drv, ch=cyl, dh=head, cl=sec, es:bx=buffer. int $13 jc load_loop mov ax,maxsect ! Ok that worked, update the pointers dec ax mov cl,#5 shl ax,cl mov di,es add ax,di mov es,ax inc si sub si,maxsect jnz inc_trk all_loaded: ! Now it's loaded turn off the floppy motor. mov dx,#0x3f2 xor al, al outb ! And start up the program. xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 mov si,dx ! Sect/track = 0 mov bx,#EXEADDR>>4 mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx ! Partition offset. inc bx inc bx ! bx = initial CS add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax ! AX=ds, BX=cs, CX=X, DX=X, SI=X, DI=0, BP=X, ES=X, DS=*, SS=*, CS=* bad_magic: push bx ! jmpi 0,#LOADSEG+2 push di retf sect_error: ! Disk error, wait then reboot. mov si,#reboot_msg call puts xor ax,ax ! Wait for the user. int $16 jmpi $0,$FFFF puts: lodsb cmp al,#0 jz EOS push bx mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 pop bx jmp puts EOS: ret maxsect: .word 0 reboot_msg: .asciz "Disk error, press a key to reboot:" Boot_message: .asciz "Boot sector loaded.\r\n" ! Check for overlap end_of_code: if end_of_code>hitme fail! Overlap at end_of_code endif .org EXEADDR hitme: magic: .space 2 ! A.out header btype: .space 2 headerlen: .space 4 a_text: .space 4 a_data: .space 4 a_bss: .space 4 a_entry: .space 4 a_total: .space 4 a_syms: .space 4 dev86-0.16.17/bootblocks/readfs.h0000644000000000000000000000205706436014414016344 0ustar rootroot00000000000000 /* Functions for reading from one file at a time in the root directory * of a raw filesystem. */ #ifdef __STDC__ #define P(x) x #else #define P(x) () #endif int open_file P((char * fname)); int rewind_file P((void)); int close_file P((void)); long file_length P((void)); int read_block P((char * buffer)); int tar_open_file P((char * fname)); int tar_rewind_file P((void)); int tar_close_file P((void)); long tar_file_length P((void)); int tar_read_block P((char * buffer)); int min_open_file P((char * fname)); int min_rewind_file P((void)); int min_close_file P((void)); long min_file_length P((void)); int min_read_block P((char * buffer)); int dos_open_file P((char * fname)); int dos_rewind_file P((void)); int dos_close_file P((void)); long dos_file_length P((void)); int dos_read_block P((char * buffer)); #define read_sector(__sect) read_lsector((unsigned long)(__sect)) char * read_lsector P((long sector)); void reset_disk P((void)); extern char * track_buffer; extern int disk_drive; extern int disk_cyls; extern int disk_heads; extern int disk_spt; dev86-0.16.17/bootblocks/boot_win.c0000644000000000000000000002035510043732155016712 0ustar rootroot00000000000000/* * This program is designed to be put onto an MSDOS filesystem floppy or * a floppy image on a CD-ROM. * * The hexdump at the end is from Windows 95 boot sector and can be used * to start a Windows 9X io.sys. * * This program runs first and if the hard disk appears bootable will load * and start that unless you press return. * * If you press a key you have the option of Zapping the MBR! * */ #include #define sysboot_dosfs_stat 0x000B #define sysboot_codestart 0x003E #define sysboot_bootblock_magic 0x01FE extern char win95_bb[512]; char bs_buf[512]; char buf2[512]; unsigned memseg, memlen; fatal(str) char * str; { cprintf(str); getch(); exit(0); } main() { int i, rv; int floppy_only = 0; int c,h,s,os; reset_screen(); cprintf("...\n"); relocate(); if (__get_cs() != 0x80) fatal("ERROR - program incorrectly compiled.\n"); for(i=0; i<6; i++) if (!(rv = _bios_disk_read(0x80, 0, 0, 1, 1, bs_buf))) break; if (rv != 0 || bs_buf[510] != 0x55 || bs_buf[511] != (char)0xAA) { cprintf("Hard disk not bootable.\n"); floppy_only = 1; /* Check for zapped MBR */ for(i=0; i<512; i++) { if (bs_buf[i]) break; if (i==511) boot_floppy(); } } if (!floppy_only) { for(rv=-1, i=0x1BE; i<0x1FE; i+= 16) { if (bs_buf[i] == (char)0x80) { rv = 0; s = (bs_buf[i+2] & 63) ; h = (bs_buf[i+1] & 255) ; c = (bs_buf[i+3] & 255) + ((bs_buf[i+2] & 0xC0) << 2); os = (bs_buf[i+4] & 255) ; break; } } if (rv) { cprintf("Hard disk has no active partition.\n"); floppy_only = 1; } } if (!floppy_only && (os==4 || os==6 || os==11 || os==12 || os==13)) { for(i=0; i<6; i++) if (!(rv = _bios_disk_read(0x80, c, h, s, 1, bs_buf))) break; if (rv != 0 || bs_buf[510] != 0x55 || bs_buf[511] != (char)0xAA) { cprintf("DOS Partition not bootable.\n"); floppy_only = 1; } } if (floppy_only) cprintf("Press return to wipe MBR: "); else cprintf("Press return to skip hard disk boot: "); __set_es(0x40); for(i=0; ; i++) { unsigned int tv = __deek_es(0x6c); while (tv == __deek_es(0x6c)) if (kbhit()) { getch(); cprintf("\n"); goto break_break; } if (i%10 == 0) cprintf("."); if (i>= 18*5) { cprintf(" Booting.\n"); if(floppy_only) boot_floppy(); else boot_hd(); } } break_break:; cprintf("Do you want to leave the hard disk intact?\n"); cprintf("(Y/n) "); i = (getch() & 0xFF); if (i == 'n' || i == 'N') { cprintf("No\n"); cprintf("WARNING: This WILL delete everything on the hard disk!\n"); cprintf("Do you want to clear the hard disk MBR?\n"); cprintf("(N/y) "); i = (getch() & 0xFF); if (i == 'y' || i == 'Y') { cprintf("Yes\n"); memset(bs_buf, 0, sizeof(bs_buf)); for(i=0; i<6; i++) if (!(rv = _bios_disk_write(0x80, 0, 0, 1, 1, bs_buf))) break; if (rv) { cprintf("Disk error 0x%2x on disk write:", rv); getch(); cprintf("\n"); } else { cprintf("Hard disk MBR wiped!\n"); } } else cprintf("No -- Disk is still untouched\n"); } else cprintf("Ok -- Disk is untouched\n"); boot_floppy(); } reset_screen() { #asm mov ah,#$0F int $10 cmp al,#$07 je dont_touch mov ax,#$0003 int $10 dont_touch: #endasm } boot_floppy() { _bios_disk_read(0, 0, 0, 1, 1, bs_buf); make_floppy_bb(); #asm mov ax,#$00 push ax pop ds mov bx,#$7c00 mov dx,#$0000 ! Of the floppy drive jmpi $7c00,0 #endasm } boot_hd() { int i; /* If we're booting from a CD we want to turn off the floppy emulation */ buf2[0] = 0x13; /* Sizeof a 'Specification packet' */ #asm mov ax,#$4B01 mov dl,#$7F mov si,#_buf2 int $13 ! Ignore the return value; it's meaningless if we aren't on a CD #endasm /* Now boot the hard disk */ __set_es(0x07c0); for(i=0; i<512; i++) __poke_es(i, bs_buf[i]); #asm mov ax,#$00 push ax pop ds mov bx,#$7c00 mov dx,#$0080 ! Of the hard drive jmpi $7c00,0 #endasm } make_floppy_bb() { int i; __set_es(0x07c0); for(i=0; i> 4); /* if (__deek_es(0) == 0x0301 ) memlen = (__deek_es(24) >> 4); */ if( memlen == 0 ) memlen = 0x1000; memlen += codelen; __set_es(es); } newseg = 0x80; /* If the old area overlaps the new then fail */ if( newseg >= memseg && newseg < memseg+memlen ) return; if( memseg >= newseg && memseg < newseg+memlen ) return; /* Copy segments, done in 32k chunks */ for(moved=0; moved < memlen; ) { unsigned int lump; if( memlen-moved <= 0x800 ) lump = memlen-moved; else lump = 0x800; __movedata(memseg+moved, 0, newseg+moved, 0, (lump<<4)); moved += lump; } /* re-link int 0x80, this one is only an example (used by 'standalone.c') */ /* __set_es(0); __doke_es(0x80*4+2, newseg); __set_es(es); */ /* The actual jump ... */ memseg = newseg; #asm mov ax,ds mov bx,cs sub ax,bx mov bx,[_memseg] add ax,bx push bx call L_x mov ds,ax mov ss,ax mov [_memseg],bx #endasm } #asm L_x: retf #endasm #else } #endif char win95_bb[512] = { 0xeb,0x3c,0x90,0x29,0x69,0x71,0x22,0x5a,0x49,0x48,0x43,0x00,0x02,0x01,0x01,0x00, 0x02,0xe0,0x00,0x40,0x0b,0xf0,0x09,0x00,0x12,0x00,0x02,0x00,0x00,0x00,0x00,0x00, 0x40,0x0b,0x00,0x00,0x00,0x00,0x29,0xfa,0x16,0x58,0x2c,0x4e,0x4f,0x20,0x4e,0x41, 0x4d,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x32,0x20,0x20,0x20,0xfa,0x33, 0xc9,0x8e,0xd1,0xbc,0xfc,0x7b,0x16,0x07,0xbd,0x78,0x00,0xc5,0x76,0x00,0x1e,0x56, 0x16,0x55,0xbf,0x22,0x05,0x89,0x7e,0x00,0x89,0x4e,0x02,0xb1,0x0b,0xfc,0xf3,0xa4, 0x06,0x1f,0xbd,0x00,0x7c,0xc6,0x45,0xfe,0x0f,0x8b,0x46,0x18,0x88,0x45,0xf9,0x38, 0x4e,0x24,0x7d,0x22,0x8b,0xc1,0x99,0xe8,0x77,0x01,0x72,0x1a,0x83,0xeb,0x3a,0x66, 0xa1,0x1c,0x7c,0x66,0x3b,0x07,0x8a,0x57,0xfc,0x75,0x06,0x80,0xca,0x02,0x88,0x56, 0x02,0x80,0xc3,0x10,0x73,0xed,0x33,0xc9,0x8a,0x46,0x10,0x98,0xf7,0x66,0x16,0x03, 0x46,0x1c,0x13,0x56,0x1e,0x03,0x46,0x0e,0x13,0xd1,0x8b,0x76,0x11,0x60,0x89,0x46, 0xfc,0x89,0x56,0xfe,0xb8,0x20,0x00,0xf7,0xe6,0x8b,0x5e,0x0b,0x03,0xc3,0x48,0xf7, 0xf3,0x01,0x46,0xfc,0x11,0x4e,0xfe,0x61,0xbf,0x00,0x07,0xe8,0x23,0x01,0x72,0x39, 0x38,0x2d,0x74,0x17,0x60,0xb1,0x0b,0xbe,0xd8,0x7d,0xf3,0xa6,0x61,0x74,0x39,0x4e, 0x74,0x09,0x83,0xc7,0x20,0x3b,0xfb,0x72,0xe7,0xeb,0xdd,0xbe,0x7f,0x7d,0xac,0x98, 0x03,0xf0,0xac,0x84,0xc0,0x74,0x17,0x3c,0xff,0x74,0x09,0xb4,0x0e,0xbb,0x07,0x00, 0xcd,0x10,0xeb,0xee,0xbe,0x82,0x7d,0xeb,0xe5,0xbe,0x80,0x7d,0xeb,0xe0,0x98,0xcd, 0x16,0x5e,0x1f,0x66,0x8f,0x04,0xcd,0x19,0xbe,0x81,0x7d,0x8b,0x7d,0x1a,0x8d,0x45, 0xfe,0x8a,0x4e,0x0d,0xf7,0xe1,0x03,0x46,0xfc,0x13,0x56,0xfe,0xb1,0x04,0xe8,0xc1, 0x00,0x72,0xd6,0xea,0x00,0x02,0x70,0x00,0xb4,0x42,0xeb,0x2d,0x60,0x66,0x6a,0x00, 0x52,0x50,0x06,0x53,0x6a,0x01,0x6a,0x10,0x8b,0xf4,0x74,0xec,0x91,0x92,0x33,0xd2, 0xf7,0x76,0x18,0x91,0xf7,0x76,0x18,0x42,0x87,0xca,0xf7,0x76,0x1a,0x8a,0xf2,0x8a, 0xe8,0xc0,0xcc,0x02,0x0a,0xcc,0xb8,0x01,0x02,0x8a,0x56,0x24,0xcd,0x13,0x8d,0x64, 0x10,0x61,0x72,0x0a,0x40,0x75,0x01,0x42,0x03,0x5e,0x0b,0x49,0x75,0x77,0xc3,0x03, 0x18,0x01,0x27,0x0d,0x0a,0x49,0x6e,0x76,0x61,0x6c,0x69,0x64,0x20,0x73,0x79,0x73, 0x74,0x65,0x6d,0x20,0x64,0x69,0x73,0x6b,0xff,0x0d,0x0a,0x44,0x69,0x73,0x6b,0x20, 0x49,0x2f,0x4f,0x20,0x65,0x72,0x72,0x6f,0x72,0xff,0x0d,0x0a,0x52,0x65,0x70,0x6c, 0x61,0x63,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x69,0x73,0x6b,0x2c,0x20,0x61,0x6e, 0x64,0x20,0x74,0x68,0x65,0x6e,0x20,0x70,0x72,0x65,0x73,0x73,0x20,0x61,0x6e,0x79, 0x20,0x6b,0x65,0x79,0x0d,0x0a,0x00,0x00,0x49,0x4f,0x20,0x20,0x20,0x20,0x20,0x20, 0x53,0x59,0x53,0x4d,0x53,0x44,0x4f,0x53,0x20,0x20,0x20,0x53,0x59,0x53,0x7f,0x01, 0x00,0x41,0xbb,0x00,0x07,0x80,0x7e,0x02,0x0e,0xe9,0x40,0xff,0x00,0x00,0x55,0xaa }; dev86-0.16.17/bootblocks/monitor.c0000644000000000000000000001400307724375352016570 0ustar rootroot00000000000000 #include "monitor.h" #include "version.h" char command_buf[256]; typedef int (*proc)(); int cmd_quit(), cmd_dump(), cmd_seg(), cmd_rel(), cmd_bzimage(), cmd_help(); int cmd_nop(), cmd_memdump(), cmd_set_base(), cmd_dir(), cmd_type(), cmd_more(); int cmd_regs(), cmd_monhelp(); void init_prog(); extern struct t_cmd_list { char * command; proc func; } cmd_list[]; unsigned int current_address; int number_base = 16; main() { static char minibuf[2] = " "; int ch, i; char *cmd, *args, *ptr; struct t_cmd_list * cptr; #ifdef __STANDALONE__ printf("\r\n"); #endif init_prog(); if (!x86_test) { #ifdef __STANDALONE__ #ifndef NOCOMMAND #if 0 /* First out of the way. */ relocator(3); /* Then align DS to 64k boundry -> DMA is simple. */ relocator(0x1000-__get_ds()+__get_cs()); #else relocator(-1); /* Top of available memory */ #endif printf("Relocated to CS=$%04x DS=$%04x\n", __get_cs(), __get_ds()); #endif disk_drive = __argr.h.dl; #endif #ifdef NOCOMMAND cmd_type("help.txt"); #else display_help(0); #endif cmd_bzimage((void*)0); } #ifdef NOCOMMAND printf("Unable to boot, sorry\nreboot:"); fflush(stdout); read(0, command_buf, sizeof(command_buf)-1) ; #else for (;;) { #ifdef COLOUR printf("\033S \033R+\033Sa\033Rc"); #endif printf(">"); fflush(stdout); ch = read(0, command_buf, sizeof(command_buf)-1) ; if( ch <= 0 ) break; command_buf[ch] = '\0'; if( ch == 1 && command_buf[0] != '\n' ) { putchar('\n'); help_key(command_buf[0]&0xFF); continue; } if( command_buf[ch-1] == '\n' ) command_buf[ch-1] = 0; for(ptr=command_buf; *ptr; ptr++) { if(*ptr=='"') do { ptr++; } while(*ptr && *ptr != '"'); if( isupper(*ptr) ) *ptr = tolower(*ptr); } cmd = command_buf; while(*cmd == ' ') cmd++; if( !isalpha(cmd[0]) || !isalpha(cmd[1]) ) { minibuf[0] = cmd[0]; args = cmd+1; cmd = minibuf; } else { args = strchr(cmd, ' '); if( args ) *args++ = 0; else args = cmd + strlen(cmd); } if( *cmd == 0 ) continue; for(cptr = cmd_list; cptr->command; cptr++) { if( strcmp(cptr->command, cmd) == 0 ) break; } #ifdef COLOUR printf("\033S \033Sa\033Rg"); #endif fflush(stdout); if( cptr->command ) (void) (*cptr->func)(args); else printf("Command not found.\n"); } #endif } /****************************************************************************/ void init_prog() { char offt; #ifdef COLOUR vt52_putch(0); printf("\033E\033Rg\033Sa\033J"); #endif printf("Linux x86"); #ifdef NOCOMMAND #ifdef TARFLOPPY printf(" TAR floppy booter"); #else #ifdef DOSFLOPPY printf(" DOS floppy booter"); #else printf(" floppy booter"); #endif #endif #else printf(" boot monitor"); #endif printf(", Version %s", VERSION); printf(".\n"); cpu_check(); mem_check(); #ifndef NOMONITOR printf("Processor: %s", x86_name); if(x86_fpu) printf(" with FPU"); if(x86_emu) printf(" in protected mode"); printf("\n"); #endif printf("There is %u bytes available", &offt-sbrk(0)); printf(", %dk of boot memory", boot_mem_top/64); if( main_mem_top ) { printf(", %d.%dM of main memory", (int)(main_mem_top/1024), (int)((10*main_mem_top)/1024%10)); } printf(".\n"); } /****************************************************************************/ int getnum(numptr, valptr) char ** numptr; unsigned int * valptr; { char * ptr = *numptr; unsigned int val = 0; int base = number_base; int flg = 0; while( *ptr && *ptr <= ' ' ) ptr++; switch(*ptr) { case '$': case '&': case 'X': base=16; ptr++; break; case '#': base=10; ptr++; break; case '%': base=2; ptr++; break; case '0': if( ptr[1] == 'X' ) { base=16; ptr+=2; } break; case '-': *numptr = ptr+1; return 0; } while(*ptr) { int d = -1, ch; ch = *ptr; if( ch >= '0' && ch <= '9' ) d = ch - '0'; if( ch >= 'a' && ch <= 'z' ) d = ch - 'a' + 10; if( ch >= 'A' && ch <= 'Z' ) d = ch - 'A' + 10; if( d>=0 && d Floppy ! 1 .. 4 => Hard disk partition. if useCHS cmp al,#'F jz is_floppy cmp al,#'f jz is_floppy endif cmp al,#'1 jb key_pause cmp al,#'4 ja key_pause and ax,#0x7 dec ax mov cl,#4 shl ax,cl add ax,#partition_start mov si,ax ! Set active flag for disk interrupt. or byte [si],#$80 br found_active if useCHS is_floppy: mov si,#floppy_part br found_active endif if message disp_message: mov si,#Banner endif puts: lodsb cmp al,#0 jz EOS push bx mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 pop bx jmp puts EOS: ret Prompt: .asciz "\rMBR: " Unprompt: .asciz "\r \r" Pause: if useCHS .asciz "\rMBR F1234> " else .asciz "\rMBR 1234> " endif Showkey: .ascii " " crlf: .asciz "\r\n" floppy_part: .word 0,1 endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! This is the pre-boot loader it uses CHS but that's ok for track 0 ! if preboot public preboot_code preboot_code: push bx mov si,#pre_boot_table lodsw mov di,ax ! First word is execute address more_boot: lodsw test ah,ah jz load_done mov bx,ax ! word 1 address lodsw mov cx,ax ! word 2 CX, cylinder/sector lodsw mov dx,ax ! word 3 DX, drive, head lodsw ! word 4 AX, $02, sector count int $13 jnc more_boot ! This doesn't retry, with a HD it shouldn't be bad. mov si,#disk_read_error br no_boot ! Sorry it ain't gonna work. load_done: call di exec_done: pop bx return: ret export pre_boot_table pre_boot_table: ! Example: Do nothing. .word return,0 ! Labels ! .word ! Then repeat .. ! .word , , , ! Or. ! .word ! .byte + ( & $300)>>2), & $FF, , , , 2 ! Finally ! .word 0 ! Example: Load rest of H0,C0 into mem at $7C00 (8k). ! .word $7C00 ! .word $7C00,$0002,$8000,$0210 ! .word $0000 endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! if message&~mbrkey disp_message: mov si,#Banner puts: lodsb cmp al,#0 jz .EOS push bx mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 pop bx jmp puts .EOS: ret endif if message export Banner Banner: .blkb 16 ! 16 bytes for the message at least. endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! Now make sure this isn't too big! end_of_code: if *>table_start fail! Partition table overlaps endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! The diskman magic number and empty DM partitions. if diskman org table_start public diskman_magic diskman_magic: .word 0xAA55 .blkb 12*partition_size-1 endif !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! And a copyright message if there's room. if copyright if *0; length--) { if( left==0 ) { if( read_block(buffer) < 0 ) break; left = 1024; } ch = buffer[1024-left]; left--; if( ch == '%' && lastch == '\n' ) { flg = 1; page--; } if( page < 0 ) break; if( page == 0 && flg == 0 ) putchar(ch); if( ch == '\n' ) flg = 0; lastch = ch; } return 0; } #endif dev86-0.16.17/bootblocks/minix_elks.c0000644000000000000000000000422006504761715017240 0ustar rootroot00000000000000 #define __ASSEMBLY__ #asm #include "minix.v" ! Must match minix.c ... #define LOADSEG (0x1000) ! Must match ELKS #define ELKS_INITSEG (0x0100) #define ELKS_SYSSEG (0x1000) org minix_helper push cs pop ds xor ax,ax mov es,ax mov ss,ax mov sp,ax mov cx,#$200 ! Move 512 words mov si,ax ! Current load address. mov di,#minix_helper ! To the correct address. rep movsw mov ds,ax jmpi code,0 msg_p2: .asciz "\r\nLoading ELKS kernel\r\n" msg_p3: .asciz "Starting ...\r\n" aint_elks: .asciz "Not an ELKS image!" elks_name: .asciz "linux" .byte 0,0,0,0,0,0,0,0,0 dispmsg: ! SI now has pointer to a message lodsb cmp al,#0 jz EOS mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp dispmsg EOS: ret code: mov si,#msg_p2 call dispmsg mov ax,minix_dinode ! In the same directory. mov minix_inode,ax mov cx,#14 mov si,#elks_name mov di,#minix_bootfile rep movsb call minix__loadprog ! Ok, now loaded "boot/linux" (or so) mov si,#msg_p3 call dispmsg call kill_motor ! For kernels without a floppy driver. ! mov ax,#LOADSEG mov ds,ax mov ax,$1E6 ! Check for ELKS magic number cmp ax,#$4C45 jnz not_elks mov ax,$1E8 cmp ax,#$534B jz boot_it not_elks: xor ax,ax mov ds,ax mov si,#aint_elks call dispmsg xor ax,ax int $16 jmpi $0,$FFFF boot_it: mov ax,#ELKS_INITSEG mov es,ax mov bl,497 ! Fetch number of setup sects. xor bh,bh inc bx mov ax,500 ! Fetch system size mov cl,#5 add ax,#31 shr ax,cl mov dx,ax looping: ! Put the setup where it belongs call copy_sect dec bx jnz looping mov ax,#ELKS_SYSSEG mov es,ax looping2: ! Put the body code in the right place. call copy_sect dec dx jnz looping2 ! Ok, everything should be where it belongs call it. mov ax,#ELKS_INITSEG mov ds,ax mov es,ax mov ss,ax mov sp,#0x4000-12 jmpi 0,ELKS_INITSEG+$20 copy_sect: mov cx,#256 xor si,si xor di,di rep movsw mov ax,ds add ax,#32 mov ds,ax mov ax,es add ax,#32 mov es,ax ret kill_motor: push dx mov dx,#0x3f2 xor al, al outb pop dx ret #endasm dev86-0.16.17/bootblocks/i86_funcs.h0000644000000000000000000000072707474162042016712 0ustar rootroot00000000000000/* * These are bios and hardware functions for the 8086 IBM PC */ extern int x86; /* CPU major number (0-3) */ extern char *x86_name; /* and it's name */ extern int x86_emu; /* Is this a PC emulator ? */ extern int x86_fpu; extern int x86_test; /* Running in test mode ? */ extern unsigned boot_mem_top; /* Top of RAM below 1M */ extern long main_mem_top; /* Top of RAM above 1M */ void cpu_check(); void mem_check(); int ext_put(); int ext_get(); dev86-0.16.17/bootblocks/fs.c0000644000000000000000000000305607616744134015515 0ustar rootroot00000000000000 #include "monitor.h" #ifndef SINGLEFS int fs_type = 0; open_file(fname) char * fname; { #ifdef DEBUG fprintf(stderr, "Open file %s\n", fname); #endif if( fs_type ) close_file(); /* If we can't read the boot sector there is a _real_ problem */ if (read_sector(0) == 0) return -1; if( tar_open_file(fname) >= 0 ) { fs_type = 1; return 0; } if( min_open_file(fname) >= 0 ) { fs_type = 2; return 0; } if( dos_open_file(fname) >= 0 ) { fs_type = 3; return 0; } return -1; } rewind_file() { #ifdef DEBUG fprintf(stderr, "Rewind file (%d)\n", fs_type); #endif switch(fs_type) { case 1: return tar_rewind_file(); case 2: return min_rewind_file(); case 3: return dos_rewind_file(); } return -1; } close_file() { int rv = -1; #ifdef DEBUG fprintf(stderr, "Close file (%d)\n", fs_type); #endif switch(fs_type) { case 1: rv = tar_close_file(); break; case 2: rv = min_close_file(); break; case 3: rv = dos_close_file(); break; } fs_type = 0; return rv; } long file_length() { #ifdef DEBUG fprintf(stderr, "File length (%d)\n", fs_type); #endif switch(fs_type) { case 1: return tar_file_length(); case 2: return min_file_length(); case 3: return dos_file_length(); } return -1; } read_block(buffer) char * buffer; { #ifdef DEBUG fprintf(stderr, "read block into (%d) (%d)\n", buffer, fs_type); #endif switch(fs_type) { case 1: return tar_read_block(buffer); case 2: return min_read_block(buffer); case 3: return dos_read_block(buffer); } return -1; } #endif dev86-0.16.17/bootblocks/minix.c0000644000000000000000000004451407444643434016235 0ustar rootroot00000000000000/* * This bootblock loads the linux-8086 executable in the file 'boot' * from the root directory of a minix filesystem. * * Copyright (C) 1990-1998 Robert de Bath, distributed under the GPL Version 2 * Based on minix filesystem definitions. * * TODO: * Alter nogood() to do a mov sp,... so the helper program can override * the panic message. */ #include #include "minix.h" /* #define DOTS /* define to have dots printed */ /* #define HARDDISK /* Define for hard disk version */ /* #define TRY_FLOPPY /* To do trial reads to find floppy size */ /* #define MIN_SPACE */ #define zone_shift 0 /* for any < 32M (!= 0 not supported yet, if ever) */ #define seg_at(k) ((k)*64) #define seg_of(p) ((unsigned int)p >>4) #define BOOTSEG (0x07c0) #define LOADSEG (0x1000) #define ORGADDR (0x0500) #ifdef HARDDISK #define get_now() #endif #ifdef zone_shift #if zone_shift == 0 #define load_zone load_block #endif #else static short zone_shift; #endif #asm BOOTADDR = 0x7c00 .text ! Apparently on startup the only things we can assume are that we start at ! `start` (ABS addr $07C00) and the boot sector is in the segment. ! So first set CS=DS=ES=SS=0 ! The we move this to $0500 and put the stack at the top of the first 64k. ! The directory 'file' is loaded $1500 and scanned there. ! The final executable will be loaded in the 2nd 64k chunk. ! org ORGADDR ! The lowest available address. start: #ifndef MIN_SPACE include sysboot.s org start ! The lowest available address, again. j skip_vars org dos_sysid .ascii "MINIXFS BOOT (C) 1990-1999, Robert de Bath" org codestart #endif ! A few variables we need to know the positions of for patching, so export ! them and as86_encaps will make some variables. Put them here at the start ! so they're in the same place for both Floppy and harddisk versions as they ! will be used by helper programs. export inode ! Inode to search inode: _inode: .word 1 ! ROOT_INODE #ifndef MIN_SPACE export dinode ! Inode of directory file was found in. dinode: _dinode: .word 1 ! ROOT_INODE #endif export bootfile ! File to boot, make this whatever you like, bootfile: ! 'boot' is good, 'linux' too. _bootfile: .ascii "boot" .byte 0,0,0,0,0,0,0,0,0,0 skip_vars: #ifdef HARDDISK mov bx,[si+8] ! Fetch the linear address of part from DS:SI mov dh,[si+10] ! DL is drive number #endif xor ax,ax ! All segments are zero, first 64k of mem. mov ds,ax mov es,ax mov ss,ax mov sp,ax #ifndef HARDDISK loopy: mov ax,#$0203 ! Read 3 sectors, code + superblock. mov bx,#start ! Where this _should_ be mov cx,#$0001 ! From sector 1 xor dx,dx ! Of the floppy drive head zero int $13 jc loopy #else mov cx,#$100 ! Move 256 words mov si,#BOOTADDR ! From default BB mov di,#ORGADDR ! To the correct address. rep movsw xchg dl,dh mov [bootpart],bx ! Save the partition sector offset (and drive) mov [bootpart+2],dx ! Read next 2 sectors of hd. xor dx,dx mov cx,#1 mov bx,#ORGADDR+$200 mov al,#2 call load_sect #endif jmpi code,#0 #endasm /* /* */ /****************************************************************************/ /* Section cdef */ /****************************************************************************/ /* The name of the file and inode to start */ extern char bootfile[]; extern inode_nr inode; extern inode_nr dinode; /* For multi-sector reads */ extern sect_nr lastsect; extern sect_nr firstsect; extern unsigned loadaddr; extern unsigned loadcount; /* Keep track of zones to load */ extern zone_nr * next_zone; extern zone_nr * end_zone; extern zone_nr indirect; /* Where to load zones */ extern unsigned ldaddr; /* Directory reading */ extern dir_struct * dirptr; extern unsigned flength; extern unsigned dir_32; #ifndef HARDDISK /* The 'shape' of the floppy - intuit from superblock or try to read max */ extern unsigned n_sectors; #endif extern struct super_block b_super; extern d_inode b_inode[INODES_PER_BLOCK]; extern zone_nr b_zone[NR_INDIRECTS]; extern dir_struct directory[]; /* /* */ /****************************************************************************/ /* Section adef */ /****************************************************************************/ #asm .text #ifdef HARDDISK bootpart: .long 0 #else _loadcount: .word 0 _firstsect: .word 0 _loadaddr: .word 0 _lastsect: .word 0 #endif block start+0x400 _b_super: .blkb 512 #ifndef MIN_SPACE export helper helper: .blkb 1024 export helper_end helper_end: #endif _b_inode: .blkb 1024 _b_zone: .blkb 1024 #ifdef MIN_SPACE temp_space: .blkb 512 #endif probe_buf: _directory: .blkb 32768 endb #endasm /* /* */ /****************************************************************************/ /* Section nogood */ /****************************************************************************/ /* #if defined(HARDDISK) && !defined(SKIPBOOT) */ #ifndef SKIPBOOT static nogood() { #asm mov si,#fail_fs min_nextc: lodsb cmp al,#0 jz min_eos mov bx,#7 mov ah,#$E ! Can't use $13 cause that's AT+ only! int $10 jmp min_nextc min_eos: ! Wait for a key then reboot xor ax,ax int $16 jmpi $0,$FFFF ! Reboot. fail_fs: .byte 13,10 #if defined(HARDDISK) .asciz "Initial boot failed, press return to reboot\r\n" #else .asciz "Boot failed:" #endif #endasm } #else static nogood() { /* This didn't work, chain the boot sector of the HD */ #asm push cs pop es hcode: mov ax,#$0201 ! Read 1 sector mov bx,#BOOTADDR ! In the boot area mov cx,#$0001 ! From sector 1 mov dx,#$0080 ! Of the hard drive head zero int $13 jc hcode ! Keep trying forever! jmpi BOOTADDR,0 #endasm } #endif /* /* */ /****************************************************************************/ /* Section hd_sect */ /****************************************************************************/ #ifdef HARDDISK #asm ! ! Load AL sectors from linear sector DX:CX into location ES:BX ! Linear sector zero is at [bootpart] ! This loads one sector at a time, but that's OK cause even in the _very_ ! worst case it'll take no more that 5 seconds to load a 16 bit executable. ! load_sect: add cx,[bootpart] adc dx,[bootpart+2] moresect: cmp al,#0 jnz onesect clc ret ! Load one sector... onesect: push ax ! Save lots push di push si push cx ! Drive and sector. push dx push es ! Load location push bx push cx ! Drive and sector again. push dx ! Fetch drive 'shape' mov ah,#8 mov dl,dh int $13 ! DX:CX = drive specification jc _nogood and cx,#$3F ! Get sector count => DI mov di,cx xor dl,dl ! Get head count => SI xchg dl,dh inc dx mov si,dx pop dx ! Get back drive and sector pop ax mov bl,dh ! Save drive xor dh,dh div di ! DX=sector, AX=track number mov cx,dx inc cl ! CL=sector number xor dx,dx div si ! DX=head, AX=cylinder mov dh,dl mov dl,bl ! DX for int 1302 xchg al,ah ror al,#1 ror al,#1 or cx,ax ! CX for int 1302 pop bx ! ES:BX for int 1302 pop es mov di,#5 ! Lots of retries for a hd retry: mov ax,#$0201 int $13 jnc got_hd_sect xor ax,ax ! Reset between each try. int $13 dec di jnz retry br _nogood got_hd_sect: pop dx pop cx pop si pop di pop ax dec al add cx,#1 adc dh,#0 add bh,#2 jmp moresect #endasm #endif /****************************************************************************/ /* This is the end of the parts that MUST be in the first sector */ /* From here down the functions can safely be in any order. */ /****************************************************************************/ /* /* */ /****************************************************************************/ /* Section fd_block */ /****************************************************************************/ #ifndef HARDDISK static load_block(address, blkno) unsigned address, blkno; { register sect_nr sectno; if(blkno == 0) { zero_block(address); return; } #ifdef DOTS prt_dot(); #endif sectno = (sect_nr)blkno * 2; load_sect(address, sectno); load_sect(address+32, sectno+1); } #endif /****************************************************************************/ /* Section fd_bpb */ /****************************************************************************/ #ifndef HARDDISK #asm _set_bpb: #ifdef MIN_SPACE bios_tabl=temp_space ! Temp space. bios_disk=temp_space+4 ! #else bios_tabl=dosfs_stat ! Temp space. bios_disk=dosfs_stat+4 ! #endif #ifndef __CALLER_SAVES__ push si push di #endif mov di,#bios_disk mov bx,#0x78 ! 0:bx is parameter table address push ds push di mov si,[bx] mov ax,[bx+2] mov [bios_tabl],si mov [bios_tabl+2],ax push ax pop ds ! ds:si is source ! copy 12 bytes mov cl,#6 cld rep movsw pop di pop ds mov ax,[_n_sectors] movb 4[di],al ! patch sector count mov [bx],di mov 2[bx],es #ifndef __CALLER_SAVES__ pop si pop di #endif ret _unset_bpb: ! 0:0x78 is parameter table address mov ax,[bios_tabl] mov [0x78],ax mov ax,[bios_tabl+2] mov [0x78+2],ax ret #endasm #endif /****************************************************************************/ /* Section fd_get_now */ /****************************************************************************/ #ifndef HARDDISK static get_now() { #asm mov si,#5 retry_get: xor dx,dx mov cx,[_firstsect] shr ch,#1 adc dh,#0 mov es,[_loadaddr] xor bx,bx mov ax,[_loadcount] test ax,ax jz no_load mov ah,#2 int $13 ! Try fetch jnc no_load xor ax,ax ! Bad, retry. int $13 dec si jnz retry_get br _nogood no_load: xor ax,ax mov [_loadcount],ax #endasm } #endif /****************************************************************************/ /* Section fd_probe */ /****************************************************************************/ #ifndef HARDDISK #ifdef TRY_FLOPPY #asm !-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ! ! These are the number of sectors per track that will be scanned for. ! For 3.5 inch floppies 36 is 2.88 Mb, 18 is 1.44Mb, 21 is 1.68Mb on ! a 1.44Mb floppy drive. 15 and 9 are for 5.25 inch floppies. disksizes: .byte 36,21,18,15,9 ! It seems that there is no BIOS call to get the number of sectors. Guess ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, ! 15 if sector 15 can be read. Otherwise guess 9. _probe_sectors: mov si,#disksizes ! table of sizes to try probe_loop: lodsb cbw ! extend to word mov _n_sectors, ax cmp al,#9 je got_sectors ! if all else fails, try 9 xchg ax, cx ! cx = track and sector xor dx, dx ! drive 0, head 0 mov bx,#probe_buf ! address after setup (es = cs) mov ax,#0x0201 ! service 2, 1 sector int 0x13 jc probe_loop ! try next value got_sectors: ret #endasm #else probe_sectors() { /* Guess the number of sectors based on the size of the file system */ if( (n_sectors = b_super.s_nzones / 40) > 11 ) n_sectors /= 2; } #endif #endif /****************************************************************************/ /* Section fd_sect */ /****************************************************************************/ #ifndef HARDDISK static load_sect(address, sectno) unsigned address; sect_nr sectno; { register sect_nr nsect; nsect = sectno%n_sectors +1; sectno /= n_sectors; nsect |= (sectno<<8); if( loadcount ) { lastsect++; if( ( address & 4095 ) && nsect == lastsect ) { loadcount++; return; } get_now(); } lastsect = firstsect = nsect; loadaddr = address; loadcount = 1; } #endif /****************************************************************************/ /* Section fd_zeroblk */ /****************************************************************************/ #ifndef HARDDISK static zero_block(address) { #asm #if __FIRST_ARG_IN_AX__ mov es,ax #else mov bx,sp mov es,[bx+2] #endif push di mov cx,#512 xor ax,ax mov di,ax rep stosw pop di #endasm } #endif /****************************************************************************/ /* Section hd_block */ /****************************************************************************/ #ifdef HARDDISK /*----------------------------------*/ /* Hard disk block driver */ /*----------------------------------*/ #asm _load_block: push bp mov bp,sp #if __FIRST_ARG_IN_AX__ ! Fetch load location mov es,ax ! Test for block zero mov ax,4[bp] #else ! Fetch load location mov ax,[bp+4] mov es,ax ! Test for block zero mov ax,6[bp] #endif test ax,ax jne real_block ! Iff block zero, zap memory push di mov cx,#512 xor ax,ax mov di,ax rep stosw pop di func_exit: mov sp,bp pop bp ret real_block: #ifdef DOTS push ax call _prt_dot pop ax #endif ! Load a real block. mov cx,ax xor dx,dx shl cx,#1 rcl dx,#1 xor bx,bx mov al,#2 call load_sect j func_exit #endasm #endif /****************************************************************************/ /* Section main */ /****************************************************************************/ #asm code: call _loadprog call _runprog br _nogood #endasm /****************************************************************************/ /* Section prt_dots */ /****************************************************************************/ #ifdef DOTS #asm _prt_crlf: mov al,#13 call outch mov al,#10 j outch _prt_dot: mov al,#'. outch: mov ah,#$0E mov bx,#7 int $10 ret #endasm #endif /****************************************************************************/ /* Section end_1 */ /****************************************************************************/ #if defined(HARDDISK) || !defined(MIN_SPACE) #asm end_of_part1: #ifdef HARDDISK if *>start+0x1FE ! Leave space for magic #else if *>start+0x200 #endif fail! Part 1 too large! endif .blkb 0x200+start-* #endasm #endif /****************************************************************************/ /* Section prog_load */ /****************************************************************************/ loadprog() { #ifdef DOTS prt_dot(); #endif if( b_super.s_magic == SUPER_MAGIC2 ) dir_32 = 1; else if( b_super.s_magic == SUPER_MAGIC ) dir_32 = 0; else nogood(); #ifdef zone_shift if( zone_shift != b_super.s_log_zone_size) nogood(); #else zone_shift = b_super.s_log_zone_size; #endif #ifndef HARDDISK probe_sectors(); /* if( (n_sectors = b_super.s_nzones / 40) > 11 ) n_sectors /= 2; */ set_bpb(); #endif try_again:; inode--; load_block(seg_of(b_inode), inode/INODES_PER_BLOCK + b_super.s_imap_blocks + b_super.s_zmap_blocks + 2); get_now(); ldaddr = LOADSEG; /* Load at 64k mark */ { register d_inode * i_ptr; i_ptr = b_inode + inode%INODES_PER_BLOCK; next_zone = i_ptr->i_zone; flength = i_ptr->i_size; if( (i_ptr->i_mode & I_TYPE) == I_DIRECTORY ) { ldaddr = seg_of(directory); #ifndef MIN_SPACE dinode = inode+1; /* Remember current directory */ #endif inode = 0; /* Mark - we've no _file_ inode yet */ } } end_zone = next_zone+NR_DZONE_NUM; load_zone(seg_of(b_zone), (indirect = next_zone[NR_DZONE_NUM])); get_now(); for(;;) { if( next_zone >= end_zone ) { if( indirect != 0 ) { next_zone = b_zone; end_zone = next_zone + NR_INDIRECTS; indirect = 0; continue; } break; } load_zone(ldaddr, *next_zone); next_zone++; ldaddr += (seg_at(1) << zone_shift); } get_now(); #ifdef DOTS prt_crlf(); #endif if(!inode) { dirptr = directory; while(flength > 0) { register char * s = bootfile; register char * p = dirptr->d_name; if( dirptr->d_inum ) { for(;;) { if( *s == '\0') { if(*p == '\0') { inode = dirptr->d_inum; goto try_again; } break; } if( *s++ != *p++ ) break; } } flength -= 16; dirptr++; if( dir_32 ) { flength -= 16; dirptr++; } } nogood(); } #ifndef HARDDISK unset_bpb(); #endif } /****************************************************************************/ /* Section prog_run */ /****************************************************************************/ static runprog() { /* It all worked, run the loaded executable */ #asm #ifdef HARDDISK mov dx,[bootpart+2] xchg dh,dl ! DX => hard drive push [bootpart] ! CX => partition offset xor si,si #else xor dx,dx ! DX=0 => floppy drive push dx ! CX=0 => partition offset = 0 mov si,[_n_sectors] ! Save for monitor.out #endif mov bx,#LOADSEG mov ds,bx ! DS = loadaddress xor di,di ! Zero mov ax,[di] cmp ax,#0x0301 ! Right magic ? jnz binfile ! Yuk ... assume .SYS inc bx inc bx ! bx = initial CS mov ax,[di+2] and ax,#$20 ! Is it split I/D ? jz impure ! No ... mov cl,#4 mov ax,[di+8] shr ax,cl impure: pop cx add ax,bx mov ss,ax mov sp,[di+24] ! Chmem value mov ds,ax binfile: push bx push di ! jmpi 0,#LOADSEG+2 retf #endasm } /****************************************************************************/ /* Section sys_libs */ /****************************************************************************/ #asm ! These functions are pulled from the C library. libstuff: imodu: xor dx,dx div bx mov ax,dx ! instruction queue full so xchg slower ret idiv_u: xor dx,dx div bx ret #ifndef zone_shift isl: islu: mov cl,bl shl ax,cl ret #endif libend: #endasm /****************************************************************************/ /* Section sys_vars */ /****************************************************************************/ #asm #ifdef MIN_SPACE block temp_space+64 #endif vars: #ifndef HARDDISK _n_sectors: .blkw 1 #endif _next_zone: .blkw 1 _end_zone: .blkw 1 _indirect: .blkw 1 _ldaddr: .blkw 1 _dirptr: .blkw 1 _flength: .blkw 1 _dir_32: .blkw 1 varend: #ifdef MIN_SPACE endb #endif #endasm /****************************************************************************/ /* Section end_2 */ /****************************************************************************/ #asm end_of_prog: if *>start+0x400 fail! Part 2 too large! endif if end_of_prog