Move source into src directory master
authorJason Self <j@jxself.org>
Sun, 26 Nov 2017 20:58:58 +0000 (12:58 -0800)
committerJason Self <j@jxself.org>
Sun, 26 Nov 2017 20:58:58 +0000 (12:58 -0800)
33 files changed:
Makefile [deleted file]
README
a56.1 [deleted file]
a56.h [deleted file]
a56.key [deleted file]
a56.y [deleted file]
frac2int.c [deleted file]
getopt.c [deleted file]
keybld.1 [deleted file]
keybld.c [deleted file]
lex.c [deleted file]
main.c [deleted file]
src/Makefile [new file with mode: 0644]
src/a56.1 [new file with mode: 0644]
src/a56.h [new file with mode: 0644]
src/a56.key [new file with mode: 0644]
src/a56.y [new file with mode: 0644]
src/frac2int.c [new file with mode: 0644]
src/getopt.c [new file with mode: 0644]
src/keybld.1 [new file with mode: 0644]
src/keybld.c [new file with mode: 0644]
src/lex.c [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/subs.c [new file with mode: 0644]
src/tok.awk [new file with mode: 0644]
src/toktab.c [new file with mode: 0644]
src/toomf.c [new file with mode: 0644]
src/torom.c [new file with mode: 0644]
subs.c [deleted file]
tok.awk [deleted file]
toktab.c [deleted file]
toomf.c [deleted file]
torom.c [deleted file]

diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index b2294b3..0000000
--- a/Makefile
+++ /dev/null
@@ -1,146 +0,0 @@
-#######################################################
-#
-#  a56 - a DSP56001 assembler
-#
-#  Written by Quinn C. Jensen
-#  July 1990
-#
-#######################################################
-
-# Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
-#
-# This file 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 3 of the License,
-# 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, see
-# <http://www.gnu.org/licenses/>.
-#
-# This file incorporates work covered by the following copyright and
-# permission notice:
-#
-# Copyright (C) 1990-1998 Quinn C. Jensen
-#
-# Permission to use, copy, modify, distribute, and sell this
-# software and its documentation for any purpose is hereby granted
-# without fee, provided that the above copyright notice appear in all
-# copies and that both that copyright notice and this permission
-# notice appear in supporting documentation.  The author makes no
-# representations about the suitability of this software for any
-# purpose. It is provided "as is" without express or implied
-# warranty.
-
-# environment definitions
-# uncomment the ones you like
-
-# generic unix
-CC = cc
-HOSTCC = cc
-YACC = yacc
-CCDEFS = -DLDEBUG
-MV = mv
-YTABC = y.tab.c
-YTABH = y.tab.h
-POSTPROCESS = echo
-
-# gcc & bison
-#CC = gcc
-#HOSTCC = gcc
-#YACC = bison -y
-#CCDEFS =
-#MV = mv
-#YTABC = y.tab.c
-#YTABH = y.tab.h
-#POSTPROCESS = echo
-
-# Delorie's DOS gcc (from ftp://omnigate.clarkson.edu/pub/msdos/djgpp)
-#CC = gcc
-#HOSTCC = gcc
-#YACC = bison -y
-#CCDEFS =
-#MV = ren
-#YTABC = y_tab.c
-#YTABH = y_tab.h
-#POSTPROCESS = coff2exe
-
-# gcc cross-compile to go32 environment
-#CC = i386-go32-gcc
-#HOSTCC = cc
-#YACC = yacc
-#CCDEFS =
-#MV = mv
-#YTABC = y.tab.c
-#YTABH = y.tab.h
-#POSTPROCESS = echo
-
-#######################################################
-
-# -O or -g
-#DEBUG = -O -Olimit 3000
-DEBUG = -O
-
-SRCS = main.c a56.y lex.c subs.c getopt.c kparse.key
-OBJS = main.o gram.o lex.o toktab.o subs.o getopt.o kparse.o
-
-DEFINES = $(CCDEFS)
-#DEFINES = -DYYDEBUG -DLDEBUG $(CCDEFS)
-
-CFLAGS = $(DEBUG) $(DEFINES) $(CPPFLAGS) $(LDFLAGS)
-
-all:   keybld a56 toomf
-
-a56:   $(OBJS)
-       $(CC) $(CFLAGS) -o a56 $(OBJS) -lm
-       @$(POSTPROCESS) a56
-
-keybld:        keybld.o ksubs.o
-       $(HOSTCC) $(CFLAGS) -o keybld keybld.o ksubs.o
-       @$(POSTPROCESS) keybld
-
-keybld.o:      keybld.c
-       $(HOSTCC) $(CFLAGS) -c keybld.c
-
-ksubs.o:       subs.c
-       $(HOSTCC) $(CFLAGS) -c subs.c
-       $(MV) subs.o ksubs.o
-
-lex.o: lex.c gram.h
-
-kparse.c:      a56.key keybld
-       ./keybld < a56.key > kparse.c
-
-gram.c gram.h: a56.y
-       @echo "[expect 2 shift/reduce conflicts here]"
-       $(YACC) -d a56.y
-       $(MV) $(YTABC) gram.c
-       $(MV) $(YTABH) gram.h
-
-toktab.c:      gram.h
-       awk -f tok.awk < gram.h > toktab.c
-
-y.output:      a56.y
-       $(YACC) -v a56.y
-
-toomf: toomf.o
-       $(CC) -o toomf $(CFLAGS) toomf.o
-       @$(POSTPROCESS) toomf
-
-torom: torom.o subs.o
-       $(CC) -o torom $(CFLAGS) torom.o subs.o
-
-tape:  toktab.c
-       csh -c 'tar cvbf 1 - `cat files` | gzip > a56.tar.gz'
-
-main.o gram.o lex.o:   a56.h
-
-clean: ; rm -f a56 toomf y.output *.o *.out tmp *.bak a56.tar.gz keybld
-
-spotless:      clean
-       rm -f gram.c lexyy.c gram.h toktab.c kparse.c
diff --git a/README b/README
index 0a369be7c37eac4b19db887b1b6b006ef0505903..b625458fed1719cabb525afb96c0f877794538a8 100644 (file)
--- a/README
+++ b/README
@@ -69,7 +69,7 @@ enhancements.
 
 TO MAKE AND USE
 
-Type "make".
+Type "make -C src".
 
 The resulting program, a56, is used as follows:
 
diff --git a/a56.1 b/a56.1
deleted file mode 100644 (file)
index 2ad66ba..0000000
--- a/a56.1
+++ /dev/null
@@ -1,39 +0,0 @@
-.\"
-.\" Copyright (C) 1990-1998 Quinn C. Jensen
-.\"
-.\" Permission to use, copy, modify, distribute, and sell this software
-.\" and its documentation for any purpose is hereby granted without fee,
-.\" provided that the above copyright notice appear in all copies and
-.\" that both that copyright notice and this permission notice appear
-.\" in supporting documentation.  The author makes no representations
-.\" about the suitability of this software for any purpose.  It is
-.\" provided "as is" without express or implied warranty.
-.\"
-.\"
-.TH A56 1 "April 28, 2010"
-.SH NAME
-A56 \- Motorola DSP56001 assembler
-.SH SYNOPSIS
-.B a56
-[\fI\-b\fR] [\fI\-l\fR] [\fI\-o output\-file\fR] file [...]
-.SH DESCRIPTION
-This manual page documents briefly the
-.B a56
-command.
-.PP
-a56 is an assembler for the Motorola DSP56001 family of microcontrollers. 
-It is capable of compiling the firmware used in Linux dsp56k.c driver.
-.SH OPTIONS
-.TP
-\fB\-b\fR
-Adds binary to the listing.
-.TP
-\fB\-l\fR
-Causes included files to be listed.
-.TP
-\fB\-o\fR
-Directs the output to the specified file rather than the default.
-.SH AUTHORS
-Copyright (C) 1990-1998 Quinn C. Jensen.
-This manual page was written by Denis Briand <denis@narcan.fr>,
-for the Debian GNU/Linux system (but may be used by others).
diff --git a/a56.h b/a56.h
deleted file mode 100644 (file)
index 3415001..0000000
--- a/a56.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*******************************************************
- *
- *  a56 - a DSP56001 assembler
- *
- *  Written by Quinn C. Jensen
- *  July 1990
- *
- *******************************************************\
-
-/*
- * Copyright (C) 2008 Robert Millan <rmh@aybabtu.com>
- * Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
- *
- * This file 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 3 of the License,
- * 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, see
- * <http://www.gnu.org/licenses/>.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * Copyright (C) 1990-1994 Quinn C. Jensen
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.  The author makes no representations
- * about the suitability of this software for any purpose.  It is
- * provided "as is" without express or implied warranty.
- *
- */
-
-/*
- *  a56.h - general definitions
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#define NOT !
-typedef int BOOL;
-#endif
-
-struct sym {
-       char *name;
-       struct n {
-               short type;
-#define UNDEF -1
-#define INT 0
-#define FLT 1
-               short seg;
-#define NONE 0
-#define PROG 1
-#define XDATA 2
-#define YDATA 3
-#define LDATA 4
-#define ANY 5
-               union val {
-                       int i;
-                       double f;
-               } val;
-       } n;
-       struct sym *next;
-} *find_sym();
-
-extern int pass;
-
-#define NEW(object) ((object *)alloc(sizeof(object)))
-
-#define MAX_NEST 20            /* maximum include file nesting */
-
-struct inc {
-       char *file;
-       FILE *fp;
-       int line;
-};
-extern struct inc inc[];
-extern int inc_p;
-#define curfile inc[inc_p].file
-#define curline inc[inc_p].line
-
-extern int ldebug;
-
-struct psect {
-       char *name;
-       int seg;
-       unsigned int pc, bottom, top;
-       struct psect *next;
-} *find_psect(), *new_psect();
-
-FILE *open_read(), *open_write(), *open_append();
-
-       /* save string s somewhere */
-#define strsave(s) ((s) != NULL ? \
-               (char *)strcpy((char *)malloc(strlen(s)+1),(s)) : NULL)
-
-       /* after a call to fgets(), remove the newline character */
-#define rmcr(s) {if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0';};
-
-#define ASSERT(expr, str) \
-               if(expr) fprintf(stderr, "ASSERT: %s: line %d: %s\n", __FILE__, __LINE__, str);
-
-char *alloc (int size);
-char *fixstring (char *s);
diff --git a/a56.key b/a56.key
deleted file mode 100644 (file)
index ae7c52b..0000000
--- a/a56.key
+++ /dev/null
@@ -1,193 +0,0 @@
-.code  #include "a56.h"
-.code  #include "gram.h"
-X:             {return XMEM;}
-Y:             {return YMEM;}
-L:             {return LMEM;}
-P:             {return PMEM;}
-A10            {return A10;}
-A              {return AAAA;}
-B10            {return B10;}
-B              {return BBBB;}
-AB             {return AABB;}
-BA             {return BBAA;}
-X              {return XXXX;}
-Y              {return YYYY;}
-SR             {return SR;}
-MR             {return MR;}
-CCR            {return CCR;}
-OMR            {return OMR;}
-SP             {return SP;}
-SSH            {return SSH;}
-SSL            {return SSL;}
-LA             {return LA;}
-LC             {return LC;}
-A0             {yylval.ival = 0; return AREG;}
-A1             {yylval.ival = 1; return AREG;}
-A2             {yylval.ival = 2; return AREG;}
-B0             {yylval.ival = 0; return BREG;}
-B1             {yylval.ival = 1; return BREG;}
-B2             {yylval.ival = 2; return BREG;}
-M0             {yylval.ival = 0; return MREG;}
-M1             {yylval.ival = 1; return MREG;}
-M2             {yylval.ival = 2; return MREG;}
-M3             {yylval.ival = 3; return MREG;}
-M4             {yylval.ival = 4; return MREG;}
-M5             {yylval.ival = 5; return MREG;}
-M6             {yylval.ival = 6; return MREG;}
-M7             {yylval.ival = 7; return MREG;}
-N0             {yylval.ival = 0; return NREG;}
-N1             {yylval.ival = 1; return NREG;}
-N2             {yylval.ival = 2; return NREG;}
-N3             {yylval.ival = 3; return NREG;}
-N4             {yylval.ival = 4; return NREG;}
-N5             {yylval.ival = 5; return NREG;}
-N6             {yylval.ival = 6; return NREG;}
-N7             {yylval.ival = 7; return NREG;}
-R0             {yylval.ival = 0; return RREG;}
-R1             {yylval.ival = 1; return RREG;}
-R2             {yylval.ival = 2; return RREG;}
-R3             {yylval.ival = 3; return RREG;}
-R4             {yylval.ival = 4; return RREG;}
-R5             {yylval.ival = 5; return RREG;}
-R6             {yylval.ival = 6; return RREG;}
-R7             {yylval.ival = 7; return RREG;}
-X0             {yylval.ival = 0; return XREG;}
-X1             {yylval.ival = 1; return XREG;}
-Y0             {yylval.ival = 0; return YREG;}
-Y1             {yylval.ival = 1; return YREG;}
-ABS            {return OP_ABS;}
-ADC            {return OP_ADC;}
-ADD            {return OP_ADD;}
-ADDL   {return OP_ADDL;}
-ADDR   {return OP_ADDR;}
-ASL            {return OP_ASL;}
-ASR            {return OP_ASR;}
-CLR            {return OP_CLR;}
-CMP            {return OP_CMP;}
-CMPM   {return OP_CMPM;}
-DIV            {return OP_DIV;}
-MAC            {return OP_MAC;}
-MACR   {return OP_MACR;}
-MPY            {return OP_MPY;}
-MPYR   {return OP_MPYR;}
-NEG            {return OP_NEG;}
-NORM   {return OP_NORM;}
-RND            {return OP_RND;}
-SBC            {return OP_SBC;}
-SUB            {return OP_SUB;}
-SUBL   {return OP_SUBL;}
-SUBR   {return OP_SUBR;}
-TCC            {yylval.cond = 0x0; return OP_TCC;}
-THS            {yylval.cond = 0x0; return OP_TCC;}
-TGE            {yylval.cond = 0x1; return OP_TCC;}
-TNE            {yylval.cond = 0x2; return OP_TCC;}
-TPL            {yylval.cond = 0x3; return OP_TCC;}
-TNN            {yylval.cond = 0x4; return OP_TCC;}
-TEC            {yylval.cond = 0x5; return OP_TCC;}
-TLC            {yylval.cond = 0x6; return OP_TCC;}
-TGT            {yylval.cond = 0x7; return OP_TCC;}
-TCS            {yylval.cond = 0x8; return OP_TCC;}
-TLO            {yylval.cond = 0x8; return OP_TCC;}
-TLT            {yylval.cond = 0x9; return OP_TCC;}
-TEQ            {yylval.cond = 0xA; return OP_TCC;}
-TMI            {yylval.cond = 0xB; return OP_TCC;}
-TNR            {yylval.cond = 0xC; return OP_TCC;}
-TES            {yylval.cond = 0xD; return OP_TCC;}
-TLS            {yylval.cond = 0xE; return OP_TCC;}
-TLE            {yylval.cond = 0xF; return OP_TCC;}
-TFR            {return OP_TFR;}
-TST            {return OP_TST;}
-AND            {return OP_AND;}
-ANDI   {return OP_ANDI;}
-EOR            {return OP_EOR;}
-LSL            {return OP_LSL;}
-LSR            {return OP_LSR;}
-NOT            {return OP_NOT;}
-OR             {return OP_OR;}
-ORI            {return OP_ORI;}
-ROL            {return OP_ROL;}
-ROR            {return OP_ROR;}
-BCLR   {return OP_BCLR;}
-BSET   {return OP_BSET;}
-BCHG   {return OP_BCHG;}
-BTST   {return OP_BTST;}
-DO             {return OP_DO;}
-ENDDO  {return OP_ENDDO;}
-LUA            {return OP_LUA;}
-MOVE   {return OP_MOVE;}
-MOVEC  {return OP_MOVEC;}
-MOVEM  {return OP_MOVEM;}
-MOVEP  {return OP_MOVEP;}
-INCLUDE        {return OP_INCLUDE;}
-ILLEGAL        {return OP_ILLEGAL;}
-JCC            {yylval.cond = 0x0; return OP_JCC;}
-JHS            {yylval.cond = 0x0; return OP_JCC;}
-JGE            {yylval.cond = 0x1; return OP_JCC;}
-JNE            {yylval.cond = 0x2; return OP_JCC;}
-JPL            {yylval.cond = 0x3; return OP_JCC;}
-JNN            {yylval.cond = 0x4; return OP_JCC;}
-JEC            {yylval.cond = 0x5; return OP_JCC;}
-JLC            {yylval.cond = 0x6; return OP_JCC;}
-JGT            {yylval.cond = 0x7; return OP_JCC;}
-JCS            {yylval.cond = 0x8; return OP_JCC;}
-JLO            {yylval.cond = 0x8; return OP_JCC;}
-JLT            {yylval.cond = 0x9; return OP_JCC;}
-JEQ            {yylval.cond = 0xA; return OP_JCC;}
-JMI            {yylval.cond = 0xB; return OP_JCC;}
-JNR            {yylval.cond = 0xC; return OP_JCC;}
-JES            {yylval.cond = 0xD; return OP_JCC;}
-JLS            {yylval.cond = 0xE; return OP_JCC;}
-JLE            {yylval.cond = 0xF; return OP_JCC;}
-JMP            {return OP_JMP;}
-JCLR   {return OP_JCLR;}
-JSET   {return OP_JSET;}
-JSCC   {yylval.cond = 0x0; return OP_JSCC;}
-JSHS   {yylval.cond = 0x0; return OP_JSCC;}
-JSGE   {yylval.cond = 0x1; return OP_JSCC;}
-JSNE   {yylval.cond = 0x2; return OP_JSCC;}
-JSPL   {yylval.cond = 0x3; return OP_JSCC;}
-JSNN   {yylval.cond = 0x4; return OP_JSCC;}
-JSEC   {yylval.cond = 0x5; return OP_JSCC;}
-JSLC   {yylval.cond = 0x6; return OP_JSCC;}
-JSGT   {yylval.cond = 0x7; return OP_JSCC;}
-JSCS   {yylval.cond = 0x8; return OP_JSCC;}
-JSLO   {yylval.cond = 0x8; return OP_JSCC;}
-JSLT   {yylval.cond = 0x9; return OP_JSCC;}
-JSEQ   {yylval.cond = 0xA; return OP_JSCC;}
-JSMI   {yylval.cond = 0xB; return OP_JSCC;}
-JSNR   {yylval.cond = 0xC; return OP_JSCC;}
-JSES   {yylval.cond = 0xD; return OP_JSCC;}
-JSLS   {yylval.cond = 0xE; return OP_JSCC;}
-JSLE   {yylval.cond = 0xF; return OP_JSCC;}
-JSR            {return OP_JSR;}
-JSCLR  {return OP_JSCLR;}
-JSSET  {return OP_JSSET;}
-NOP            {return OP_NOP;}
-REP            {return OP_REP;}
-RESET  {return OP_RESET;}
-RTI            {return OP_RTI;}
-RTS            {return OP_RTS;}
-STOP   {return OP_STOP;}
-SWI            {return OP_SWI;}
-WAIT   {return OP_WAIT;}
-EQU            {return OP_EQU;}
-ORG            {return OP_ORG;}
-DC             {return OP_DC;}
-DS             {return OP_DS;}
-DSM            {return OP_DSM;}
-INT            {return OP_INT;}
-END            {return OP_END;}
-PAGE   {return OP_PAGE;}
-PSECT  {return OP_PSECT;}
-ALIGN  {return OP_ALIGN;}
-PI             {return OP_PI;}
-SIN            {return OP_SIN;}
-COS            {return OP_COS;}
-TAN            {return OP_TAN;}
-ATAN   {return OP_ATAN;}
-ASIN   {return OP_ASIN;}
-ACOS   {return OP_ACOS;}
-EXP            {return OP_EXP;}
-LN             {return OP_LN;}
-LOG            {return OP_LOG;}
-POW            {return OP_POW;}
diff --git a/a56.y b/a56.y
deleted file mode 100644 (file)
index 9c3399b..0000000
--- a/a56.y
+++ /dev/null
@@ -1,2114 +0,0 @@
-%{
-/*******************************************************
- *
- *  a56 - a DSP56001 assembler
- *
- *  Written by Quinn C. Jensen
- *  July 1990
- *
- *******************************************************/
-
-/*
- * Copyright (C) 1990-1994 Quinn C. Jensen
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.  The author makes no representations
- * about the suitability of this software for any purpose.  It is
- * provided "as is" without express or implied warranty.
- *
- */
-
-/*
- *  a56.y - The YACC grammar for the assembler.
- *
- *  Note:  This module requires a "BIG" version of YACC.  I had to
- *  recompile YACC in the largest mode available.
- *
- *  Other notes:
- *
- *  MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure
- *  out which form to use.
- *
- */
-
-#include "a56.h"
-#include <math.h>
-
-unsigned int w0, w1;                   /* workspace for the actual generated code */
-BOOL uses_w1;                                  /* says whether w1 is alive */
-unsigned int pc;                               /* current program counter */
-int seg;                                               /* current segment P: X: Y: or L: */
-int expr_seg;                                  /* segment of current expression */
-
-int just_rep = 0;                              /* keeps track of REP instruction */
-int hot_rreg = -1;                             /* rreg loaded by prev inst. or -1 */
-int hot_nreg = -1;                             /* nreg loaded by prev inst. or -1 */
-int hot_mreg = -1;                             /* mreg loaded by prev inst. or -1 */
-int prev_hot_rreg = -1;                        /* rreg loaded by prev inst. or -1 */
-int prev_hot_nreg = -1;                        /* nreg loaded by prev inst. or -1 */
-int prev_hot_mreg = -1;                        /* mreg loaded by prev inst. or -1 */
-
-int substatement = 0;                  /* in a substatement */
-BOOL long_symbolic_expr = FALSE; /* a parser flag */
-char *new_include = NULL;              /* file to be included */
-
-/* listing stuff */
-
-char segs[] = "uPXYL*";
-extern BOOL list_on_next;              /* listing to turn on or off */
-BOOL list_on;                                  /* listing on at the moment */
-extern char *cur_line;                 /* points to line being lex'd */
-char list_buf[1024 + 80];              /* listing buffer */
-char list_buf2[1024 + 80];             /* listing buffer for two-line code */
-BOOL uses_buf2 = FALSE;                        /* list_buf2 is alive */
-BOOL list_print_line = FALSE;  /* whether or not to print line in listing */
-char *spaces(), *luntab();
-
-struct n binary_op();
-struct n unary_op();
-struct n sym_ref();
-
-#define R_R6                           0x0001
-#define R_R5                           0x0002
-#define R_R4                           0x0004
-#define R_DATA_ALU_ACCUM       0x0008
-#define R_CTL_REG                      0x0010
-#define R_FUNKY_CTL_REG                0x0020
-#define R_SDX                          0x0040
-#define R_SDY                          0x0080
-#define R_LSD                          0x0100
-#define R_AB                           0x0200
-#define R_XREG                         0x0400
-#define R_YREG                         0x0800
-/* registers to which short immediate move is an unsigned int */
-#define R_UINT                         0x1000
-/* registers to which short immediate move is an signed frac */
-#define R_SFRAC                                0x2000
-%}
-
-%union {
-       int ival;                       /* integer value */
-       struct n n;                     /* just like in struct sym */
-       double dval;            /* floating point value */
-       char *sval;                     /* string */
-       int cval;                       /* character */
-       char cond;                      /* condition */
-       struct regs {
-               int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg;
-               int sdx, sdy, lsd, ab, xreg, yreg;
-               int flags;
-       } regs;
-       struct ea {
-               int mode;
-               int ext;
-               int pp;
-       } ea;
-}
-
-%token <n> CHEX CDEC FRAC 
-%token <ival> AREG BREG MREG NREG RREG XREG YREG
-%token <ival> OP OPA OPP
-%token <cond> OP_JCC OP_JSCC OP_TCC
-%token <sval> SYM
-%token <sval> STRING
-%token <cval> CHAR
-%token XMEM
-%token YMEM
-%token LMEM
-%token PMEM
-%token AAAA
-%token A10
-%token BBBB
-%token B10
-%token AABB
-%token BBAA
-%token XXXX
-%token YYYY
-%token SR
-%token MR
-%token CCR
-%token OMR
-%token SP
-%token SSH
-%token SSL
-%token LA
-%token LC
-%token EOL
-%token EOS
-%token LEXBAD
-
-%token OP_ABS
-%token OP_ADC
-%token OP_ADD
-%token OP_ADDL
-%token OP_ADDR
-%token OP_ASL
-%token OP_ASR
-%token OP_CLR
-%token OP_CMP
-%token OP_CMPM
-%token OP_DIV
-%token OP_MAC
-%token OP_MACR
-%token OP_MPY
-%token OP_MPYR
-%token OP_NEG
-%token OP_NORM
-%token OP_RND
-%token OP_SBC
-%token OP_SUB
-%token OP_SUBL
-%token OP_SUBR
-%token OP_TFR
-%token OP_TST
-%token OP_AND
-%token OP_ANDI
-%token OP_EOR
-%token OP_LSL
-%token OP_LSR
-%token OP_NOT
-%token OP_OR
-%token OP_ORI
-%token OP_ROL
-%token OP_ROR
-%token OP_BCLR
-%token OP_BSET
-%token OP_BCHG
-%token OP_BTST
-%token OP_DO
-%token OP_ENDDO
-%token OP_LUA
-%token OP_MOVE
-%token OP_MOVEC
-%token OP_MOVEM
-%token OP_MOVEP
-%token OP_ILLEGAL
-%token OP_INCLUDE
-%token OP_JMP
-%token OP_JCLR
-%token OP_JSET
-%token OP_JSR
-%token OP_JSCLR
-%token OP_JSSET
-%token OP_NOP
-%token OP_REP
-%token OP_RESET
-%token OP_RTI
-%token OP_RTS
-%token OP_STOP
-%token OP_SWI
-%token OP_WAIT
-%token OP_EQU
-%token OP_ORG
-%token OP_DC
-%token OP_DS
-%token OP_DSM
-%token OP_END
-%token OP_PAGE
-%token OP_PSECT
-%token OP_ALIGN
-%token OP_INT
-%token SHL
-%token SHR
-%token OP_PI
-%token OP_SIN
-%token OP_COS
-%token OP_TAN
-%token OP_ATAN
-%token OP_ASIN
-%token OP_ACOS
-%token OP_EXP
-%token OP_LN
-%token OP_LOG
-%token OP_POW
-
-%type <n> num num_or_sym 
-%type <n> num_or_sym_expr
-%type <n> expr
-%type <n> ix
-%type <n> ix_long
-
-%type <ival> abs_addr abs_short_addr io_short_addr 
-%type <ival> a_b x_or_y ea b5_10111_max
-%type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12
-%type <ival> ea_short
-%type <ival> prog_ctl_reg
-%type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8
-%type <ival> mpy_arg mpy_srcs plus_minus
-%type <ival> sd3
-%type <ival> funky_ctl_reg tcc_sd space
-%type <sval> opt_label
-
-%type <regs> regs
-%type <ea> movep_ea_pp
-
-%left '|'
-%left '^'
-%left SHL SHR
-%left '&'
-%left '+' '-'
-%left '*' '/' '%'
-%right '~'
-
-%start input
-
-%%
-
-/*%%%********************* top syntax ***********************/
-
-input  :       /* empty */
-       |       input statement
-       ;
-
-statement
-       :       good_stuff EOL
-                       {
-                       if(pass == 2 && list_on && list_print_line) {
-                               printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
-                                       list_buf, substatement == 0 ? luntab(cur_line) : "");
-                               if(uses_buf2)
-                                       printf(ldebug ? "\n(%s|)\n" : "%s\n",
-                                               list_buf2);
-                               list_buf[0] = list_buf2[0] = '\0';
-                       }
-                       curline++;
-                       uses_buf2 = FALSE;
-                       list_print_line = TRUE;
-                       list_on = list_on_next;
-                       substatement = 0;
-                       if(NOT check_psect(seg, pc) && pass == 2)
-                               yyerror("%04X: psect violation", pc);
-                       }
-       |       good_stuff EOS
-                       {
-                       if(pass == 2 && list_on && list_print_line) {
-                               printf(ldebug ? "\n(%s" : "%s", list_buf);
-                               if(substatement == 0)
-                                       printf(ldebug ? "|%s)\n" : "%s\n", luntab(cur_line));
-                               else
-                                       printf(ldebug ? ")\n" : "\n");
-                               if(uses_buf2)
-                                       printf(ldebug ? "\n(%s|)\n" : "%s\n",
-                                               list_buf2);
-                               list_buf[0] = list_buf2[0] = '\0';
-                       }
-                       substatement++;
-                       uses_buf2 = FALSE;
-                       list_print_line = TRUE;
-                       list_on = list_on_next;
-                       if(NOT check_psect(seg, pc) && pass == 2)
-                               yyerror("%04X: psect violation", pc);
-                       }
-       |       error EOL
-                       {curline++; substatement = 0;}
-       ;
-
-good_stuff
-       :       /* empty */
-                       {sprintf(list_buf, "%s", spaces(0));}
-       |       cpp_droppings
-                       {list_print_line = FALSE;}
-       |       assembler_ops
-                       {long_symbolic_expr = FALSE;}
-       |       label_field operation_field
-                       {char *printcode();
-                       if(pass == 2) {
-                               gencode(seg, pc, w0);
-                               sprintf(list_buf, "%c:%04X %s ", segs[seg], pc, printcode(w0));
-                               pc++;
-                               if(uses_w1) {
-                                       gencode(seg, pc, w1);
-                                       sprintf(list_buf2, "%c:%04X %s", segs[seg], pc,
-                                               printcode(w1 & 0xFFFFFF));
-                                       uses_buf2++;
-                                       pc++;
-                               }
-                       } else {
-                               pc++;
-                               if(uses_w1)
-                                       pc++;
-                       }
-                       w0 = w1 = 0; uses_w1 = FALSE; 
-                       long_symbolic_expr = FALSE;}
-       |       SYM 
-                       {sym_def($1, INT, seg, pc);
-                       free($1);
-                       if(pass == 2 && list_on) {
-                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, spaces(14-8));
-                       long_symbolic_expr = FALSE;
-                       }}
-       ;
-
-cpp_droppings
-       :       '#' num STRING
-                       {if(strlen($3) > 0)
-                               curfile = $3;
-                       else
-                               curfile = "<stdin>";
-                       curline = $2.val.i - 1;}
-       ;
-
-assembler_ops
-       :       SYM OP_EQU expr
-                       {sym_def($1, $3.type, ANY, $3.val.i, $3.val.f);
-                       free($1);
-                       if(pass == 2 && list_on) {
-                               if($3.type == INT)
-                                       sprintf(list_buf, "%06X%s",
-                                               $3.val.i & 0xFFFFFF,
-                                               spaces(14-8));
-                               else
-                                       sprintf(list_buf, "%10g%s", $3.val.f,
-                                               spaces(14-4));
-                       }}
-       |       OP_ALIGN expr
-                       {int ival = n2int($2);
-                       if($2.type == UNDEF) {
-                               yyerror("illegal forward reference");
-                       } else if (ival <= 1) {
-                               yyerror("%d: illegal alignment", ival);
-                       } else {
-                               if(pc % ival != 0)
-                                       pc += ival - pc % ival;
-                       }
-                       if(pass == 2 && list_on)
-                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
-                                       spaces(14-8));
-                       }
-       |       OP_PSECT SYM
-                       {struct psect *pp = find_psect($2);
-                       if(NOT pp) {
-                               if(pass == 2)
-                                       yyerror("%s: undefined psect", $2);
-                       } else {
-                               seg = pp->seg;
-                               pc = pp->pc;
-                               set_psect(pp);
-                               if(pass == 2 && list_on)
-                                       sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
-                                               spaces(14-8));
-                       }
-                       free($2);}
-       |       OP_PSECT SYM space expr ':' expr
-                       {new_psect($2, $3, n2int($4), n2int($6));
-                       if(pass == 2 && list_on)
-                               sprintf(list_buf, "%c:%04X %04X%s", 
-                                       segs[$3], n2int($4), n2int($6), spaces(14-8+4+1));
-                       }
-       |       OP_ORG space expr
-                       {pc = n2int($3);
-                       seg = $2;
-                       if(pass == 2 && list_on)
-                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
-                                       spaces(14-8));
-                       }
-       |       OP_ORG space expr ',' space expr
-                       {pc = n2int($3);
-                       seg = $2;
-                       if(pass == 2 && list_on)
-                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
-                                       spaces(14-8));
-                       }
-       |       label_field OP_DC dc_list
-       |       label_field OP_DS expr
-                       {pc += n2int($3);
-                       if(pass == 2 && list_on)
-                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
-                                       spaces(14-8));
-                       }
-       |       opt_label OP_DSM expr
-                       {int size = n2int($3);
-                       if(size)
-                       {    int align = 1;
-                            while(align < size)
-                                align <<= 1;
-                            pc += (align - (pc % align));
-                       }
-                       if($1)
-                       {   sym_def($1, INT, seg, pc);
-                           free($1);
-                       }
-                       pc += size;
-                       }
-       |       OP_PAGE num ',' num ',' num ',' num
-                       {if(pass == 2 && list_on) {
-                               sprintf(list_buf, "%s", spaces(0));
-                       }}
-       |       OP_INCLUDE STRING
-                       {if(pass == 2 && list_on) {
-                               printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
-                                       spaces(0), luntab(cur_line));
-                               list_print_line = FALSE;
-                       }
-                       include($2); /* free($2); */
-                       }
-       |       OP_END
-                       {if(pass == 2 && list_on) {
-                               sprintf(list_buf, "%s", spaces(0));
-                       }}
-       ;
-
-dc_list
-       :       dc_list ',' dc_stuff
-       |       dc_stuff
-       ;
-
-dc_stuff
-       :       STRING
-                       {int len = strlen($1), i; char *cp; w0 = 0;
-                       if(len % 3 == 2)
-                               len++;  /* force empty word */
-                       for(i = 0, cp = $1; i < len; i++, cp++) {
-                               w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8;
-                               if(i % 3 == 2 || i == len - 1) {
-                                       if(pass == 2) {
-                                               if(list_on) sprintf(list_buf, "%c:%04X %06X%s",
-                                                       segs[seg], pc, w0, 
-                                                       spaces(14-6+5));
-                                               gencode(seg, pc, w0);
-                                       }
-                                       pc++; w0 = 0;
-                               }
-                       }
-                       free($1);}
-       |       expr
-                       {int frac = n2frac($1);
-                       if(pass == 2) {
-                               if(list_on) {
-                                       sprintf(list_buf, "%c:%04X %06X%s", segs[seg], pc, 
-                                               frac & 0xFFFFFF, spaces(14-6+5));
-                               }
-                               gencode(seg, pc, frac);
-                       }
-                       pc++;}
-
-space
-       :       PMEM
-                       {$$ = PROG;}
-       |       XMEM
-                       {$$ = XDATA;}
-       |       YMEM
-                       {$$ = YDATA;}
-       |       LMEM
-                       {$$ = LDATA;}
-       ;       
-
-label_field
-       :       SYM
-                       {sym_def($1, INT, seg, pc);
-                       free($1);}
-       |       /* empty */
-       ;
-
-opt_label
-       :       SYM             {$$ = $1;}
-       |       /* empty */     {$$ = NULL;}
-       ;
-
-operation_field
-       :       operation
-                       {prev_hot_rreg = hot_rreg;
-                       prev_hot_nreg = hot_nreg;
-                       prev_hot_mreg = hot_mreg;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       if(just_rep) 
-                               just_rep--;}
-       ;
-
-operation
-       :       no_parallel
-       |       parallel_ok
-                       {w0 |= 0x200000;}
-       |       parallel_ok parallel_move
-       ;
-
-/*%%%************* instructions that allow parallel moves ****************/
-
-parallel_ok
-       :
-               OP_MPY mpy_arg
-                       {w0 |= 0x80 | $2 << 2;}
-       |       OP_MPYR mpy_arg
-                       {w0 |= 0x81 | $2 << 2;}
-       |       OP_MAC mpy_arg
-                       {w0 |= 0x82 | $2 << 2;}
-       |       OP_MACR mpy_arg
-                       {w0 |= 0x83 | $2 << 2;}
-
-       |       OP_SUB op8_1
-                       {w0 |= 0x04 | $2 << 3;}
-       |       OP_ADD op8_1
-                       {w0 |= 0x00 | $2 << 3;}
-       |       OP_MOVE
-                       {w0 |= 0x00;}
-
-       |       OP_TFR op8_2
-                       {w0 |= 0x01 | $2 << 3;}
-       |       OP_CMP op8_2
-                       {w0 |= 0x05 | $2 << 3;}
-       |       OP_CMPM op8_2
-                       {w0 |= 0x07 | $2 << 3;}
-
-       |       OP_RND op8_3
-                       {w0 |= 0x11 | $2 << 3;}
-       |       OP_ADDL op8_3
-                       {w0 |= 0x12 | $2 << 3;}
-       |       OP_CLR op8_3
-                       {w0 |= 0x13 | $2 << 3;}
-       |       OP_SUBL op8_3
-                       {w0 |= 0x16 | $2 << 3;}
-       |       OP_NOT op8_3
-                       {w0 |= 0x17 | $2 << 3;}
-
-       |       OP_ADDR op8_4
-                       {w0 |= 0x02 | $2 << 3;}
-       |       OP_TST op8_4
-                       {w0 |= 0x03 | $2 << 3;}
-       |       OP_SUBR op8_4
-                       {w0 |= 0x06 | $2 << 3;}
-
-       |       OP_AND op8_5
-                       {w0 |= 0x46 | $2 << 3;}
-       |       OP_OR op8_5
-                       {w0 |= 0x42 | $2 << 3;}
-       |       OP_EOR op8_5
-                       {w0 |= 0x43 | $2 << 3;}
-
-       |       OP_ASR op8_6
-                       {w0 |= 0x22 | $2 << 3;}
-       |       OP_LSR op8_6
-                       {w0 |= 0x23 | $2 << 3;}
-       |       OP_ABS op8_6
-                       {w0 |= 0x26 | $2 << 3;}
-       |       OP_ROR op8_6
-                       {w0 |= 0x27 | $2 << 3;}
-
-       |       OP_ASL op8_7
-                       {w0 |= 0x32 | $2 << 3;}
-       |       OP_LSL op8_7
-                       {w0 |= 0x33 | $2 << 3;}
-       |       OP_NEG op8_7
-                       {w0 |= 0x36 | $2 << 3;}
-       |       OP_ROL op8_7
-                       {w0 |= 0x37 | $2 << 3;}
-
-       |       OP_ADC op8_8
-                       {w0 |= 0x21 | $2 << 3;}
-       |       OP_SBC op8_8
-                       {w0 |= 0x25 | $2 << 3;}
-       ;
-
-mpy_arg        :       plus_minus mpy_srcs ',' a_b
-                       {$$ = $1 | $4 << 1 | $2 << 2;}
-       ;
-
-plus_minus
-       :       '+'    
-                       {$$ = 0;}
-       |       '-'    
-                       {$$ = 1;}
-       |       
-                       {$$ = 0;}
-       ;
-
-mpy_srcs
-       :       XREG ',' XREG
-                       {switch ($1 << 4 | $3) {
-                               case 0x00: $$ = 0x0; break;
-                               case 0x01: 
-                               case 0x10: $$ = 0x2; break;
-                               case 0x11: 
-                                       yyerror("illegal source operands"); 
-                                       break;
-                       }}                              
-       |       YREG ',' YREG
-                       {switch ($1 << 4 | $3) {
-                               case 0x00: $$ = 0x1; break;
-                               case 0x01: 
-                               case 0x10: $$ = 0x3; break;
-                               case 0x11: 
-                                       yyerror("illegal source operands"); 
-                                       break;
-                       }}                              
-       |       XREG ',' YREG
-                       {switch ($1 << 4 | $3) {
-                               case 0x00: $$ = 0x5; break;
-                               case 0x01: $$ = 0x4; break;
-                               case 0x10: $$ = 0x6; break;
-                               case 0x11: $$ = 0x7; break;
-                       }}                              
-       |       YREG ',' XREG
-                       {switch ($1 << 4 | $3) {
-                               case 0x00: $$ = 0x5; break;
-                               case 0x01: $$ = 0x6; break;
-                               case 0x10: $$ = 0x4; break;
-                               case 0x11: $$ = 0x7; break;
-                       }}                              
-       ;
-
-op8_1  :       BBBB ',' AAAA
-                       {$$ = 0x2;}
-       |       AAAA ',' BBBB
-                       {$$ = 0x3;}
-       |       XXXX ',' a_b
-                       {$$ = 0x4 | $3;}
-       |       YYYY ',' a_b
-                       {$$ = 0x6 | $3;}
-       |       XREG ',' a_b
-                       {$$ = 0x8 | $1 << 2 | $3;}
-       |       YREG ',' a_b
-                       {$$ = 0xA | $1 << 2 | $3;}
-       ;
-
-op8_2  :       BBBB ',' AAAA
-                       {$$ = 0x0;}
-       |       AAAA ',' BBBB
-                       {$$ = 0x1;}
-       |       XREG ',' a_b
-                       {$$ = 0x8 | $1 << 2 | $3;}
-       |       YREG ',' a_b
-                       {$$ = 0xA | $1 << 2 | $3;}
-       ;
-
-op8_3  :       AAAA
-                       {$$ = 0x0;}
-       |       BBBB
-                       {$$ = 0x1;}
-       |       BBBB ',' AAAA
-                       {$$ = 0x0;}
-       |       AAAA ',' BBBB
-                       {$$ = 0x1;}
-       ;
-
-op8_4  :       op8_3
-                       {$$ = $1;}
-       ;
-
-op8_5  :       XREG ',' a_b
-                       {$$ = 0x0 | $1 << 2 | $3;}
-       |       YREG ',' a_b
-                       {$$ = 0x2 | $1 << 2 | $3;}
-       ;
-
-op8_6  :       a_b
-                       {$$ = $1;}
-       ;
-
-op8_7  :       a_b
-                       {$$ = $1;}
-       ;
-
-op8_8  :       XXXX ',' a_b
-                       {$$ = 0x0 | $3;}
-       |       YYYY ',' a_b
-                       {$$ = 0x2 | $3;}
-       ;
-
-a_b    :       AAAA
-                       {$$ = 0;}
-       |       BBBB
-                       {$$ = 1;}
-       ;
-
-no_parallel
-       :       control_inst
-                       {if(just_rep == 1)
-                               yyerror("instruction not allowed after REP");}
-       |       bit_inst
-       |       move_inst
-       |       arith_inst
-       ;
-
-/*%%%************** non-parallel arithmetic and logical ********************/
-
-arith_inst
-       :       OP_NORM RREG ',' a_b
-                       {w0 |= 0x01D815 | $2 << 8 | $4 << 3;}
-       |       OP_DIV sd3
-                       {w0 |= 0x018040 | $2 << 3;}
-       |       or_op ix ',' funky_ctl_reg
-                       {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;}
-       |       and_op ix ',' funky_ctl_reg
-                       {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;}
-       ;
-
-or_op  :       OP_OR
-       |       OP_ORI
-       ;
-
-and_op :       OP_AND
-       |       OP_ANDI
-       ;
-
-/*%%%******************************* control instructions **********************/
-
-control_inst
-       :       OP_JSCC ea_a12
-                       {if($2) {
-                               w0 |= 0x0BC0A0 | $1 << 0;
-                       } else {
-                               w0 |= 0x0F0000 | $1 << 12;
-                       }}
-       |       OP_JCC ea_a12
-                       {if($2) {
-                               w0 |= 0x0AC0A0 | $1 << 0;
-                       } else {
-                               w0 |= 0x0E0000 | $1 << 12;
-                       }}
-       |       OP_JSR ea_a12
-                       {if($2) {
-                               w0 |= 0x0BC080;
-                       } else {
-                               w0 |= 0x0D0000;
-                       }}
-       |       OP_JMP ea_a12
-                       {if($2) {
-                               w0 |= 0x0AC080;
-                       } else {
-                               w0 |= 0x0C0000;
-                       }}
-
-       |       OP_JSSET control_args
-                       {w0 |= 0x0B0020;}
-       |       OP_JSCLR control_args
-                       {w0 |= 0x0B0000;}
-       |       OP_JSET control_args
-                       {w0 |= 0x0A0020;}
-       |       OP_JCLR control_args
-                       {w0 |= 0x0A0000;}
-
-       |       OP_REP rep_args
-                       {just_rep = 2;}
-       |       OP_DO do_args
-                       {uses_w1++;}
-       |       OP_ENDDO
-                       {w0 |= 0x00008C;}
-       |       OP_STOP
-                       {w0 |= 0x000087;}
-       |       OP_WAIT
-                       {w0 |= 0x000086;}
-       |       OP_RESET
-                       {w0 |= 0x000084;}
-       |       OP_RTS
-                       {w0 |= 0x00000C;}
-       |       OP_SWI
-                       {w0 |= 0x000006;}
-       |       OP_ILLEGAL
-                       {w0 |= 0x000005;}
-       |       OP_RTI
-                       {w0 |= 0x000004;}
-       |       OP_NOP
-                       {w0 |= 0x000000;
-                       just_rep = 0;}
-       ;
-
-do_args
-       :       ix ',' abs_addr
-                       {int ival = n2int($1);
-                       w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
-                       if(ival > 0xFFF && pass == 2) {
-                               yywarning("warning: immediate operand truncated");
-                       }
-                       w1 |= $3-1;}
-       |       regs ',' abs_addr
-                       {w0 |= 0x06C000 | $1.r6 << 8;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       w1 |= $3-1;}
-       |       x_or_y ea_no_ext ',' abs_addr
-                       {w0 |= 0x064000 | $2 << 8 | $1 << 6;
-                       w1 |= $4-1;}
-       |       x_or_y abs_short_addr ',' abs_addr      /* allow forced */
-                       {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
-                       /*
-                        * $$$ oops, can't check expr_seg because both abs_short_addr and
-                        * abs_addr touch it
-                        */
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       w1 |= $4-1;}
-       |       x_or_y abs_addr ',' abs_addr
-                       {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
-                       /*
-                        * $$$ oops, can't check expr_seg because both abs_short_addr and
-                        * abs_addr touch it
-                        */
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       w1 |= $4-1;}
-       ;                       
-
-rep_args
-       :       ix
-                       {int ival = n2int($1);
-                       w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
-                       if(ival > 0xFFF && pass == 2) {
-                               yywarning("warning: immediate operand truncated");
-                       }}
-       |       regs
-                       {w0 |= 0x06C020 | $1.r6 << 8;
-                       hot_rreg = hot_nreg = hot_mreg = -1;}
-       |       x_or_y ea_no_ext
-                       {w0 |= 0x064020 | $1 << 6 | $2 << 8;}
-       |       x_or_y abs_addr
-                       {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
-                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
-                               $1 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       }
-       |       x_or_y abs_short_addr   /* forced */
-                       {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
-                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
-                               $1 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       }
-       ;
-
-control_args
-       :       b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr
-                       {w0 |= $1 << 0 | $3 << 6;
-                       uses_w1++;
-                       w1 = $6;}
-       |       b5_10111_max ',' regs ',' abs_addr
-                       {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       uses_w1++;
-                       w1 = $5;}
-       ;
-
-p6_ean_a6
-       :       abs_addr        /* in pass 2 can always discern size. */
-                               /* Sometimes in pass one, too.  But since */
-                               /* address extension is always used for the */
-                               /* branch target, pass 1 can assume the */
-                               /* symbol value will fit; warning in pass 2 */
-                               /* if it doesn't */
-                       {if($1 != -1) { /* symbol defined */
-                               w0 |= ($1 & 0x3F) << 8;
-                               if($1 >= 0xFFC0) {
-                                       w0 |= 0x008080;
-                               } else {
-                                       w0 |= 0x000080;
-                                       if($1 > 0x003F && pass == 2)
-                                               yywarning("warning: address operand truncated");
-                               }
-                       }}
-       |       abs_short_addr
-                       {if($1 != -1) {
-                               if($1 > 0x3F && pass == 2)
-                                       yywarning("warning: address operand truncated");
-                               w0 |= 0x000080 | ($1 & 0x3F) << 8;
-                       }}
-       |       io_short_addr
-                       {if($1 != -1) {
-                               if($1 < 0xFFC0 && pass == 2)
-                                       yywarning("warning: address operand truncated");
-                               w0 |= 0x008080 | ($1 & 0x3F) << 8;
-                       }}
-       |       ea_no_ext
-                       {w0 |= 0x004080 | $1 << 8;}
-       ;
-
-/*%%%**************************** bit instructions ***************************/
-
-bit_inst
-       :       OP_BTST bit_args
-                       {w0 |= 0x0B0020;}
-       |       OP_BCHG bit_args
-                       {w0 |= 0x0B0000;}
-       |       OP_BSET bit_args
-                       {w0 |= 0x0A0020;}
-       |       OP_BCLR bit_args
-                       {w0 |= 0x0A0000;}
-       ;                       
-
-bit_args
-       :       b5_10111_max ',' x_or_y p6_ea_a6
-                       {w0 |= $1 << 0 | $3 << 6;
-                       }
-       |       b5_10111_max ',' regs
-                       {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;}
-       ;               
-
-p6_ea_a6
-       :       io_short_addr   /* must be forced to tell from abs_addr */
-                       {if($1 != -1) {
-                               w0 |= ($1 & 0x3F) << 8 | 0x008000;
-                               if($1 < 0xFFC0 && pass == 2)
-                                       yywarning("warning: address operand truncated");
-                       }}
-       |       abs_short_addr  /* must be forced to tell from abs_addr */
-                       {if($1 != -1) {
-                               w0 |= ($1 & 0x3F) << 8 | 0x000000;
-                               if($1 > 0x003F && pass == 2)
-                                       yywarning("warning: address operand truncated");
-                       }}
-       |       ea      /* can use abs_addr */
-                       {w0 |= 0x004000;}
-       ;
-
-/*%%%************************** move instructions **********************/
-
-move_inst
-       :       OP_MOVEP movep_args
-       |       OP_MOVEM movem_args
-       |       OP_MOVEC movec_args
-       |       OP_LUA ea_short ',' regs
-                       {w0 |= 0x044010 | $2 << 8 | $4.r4;}
-       |       OP_TCC tcc_args
-                       {w0 |= $1 << 12;}
-       ;               
-
-tcc_args
-       :       tcc_sd
-                       {w0 |= 0x020000 | $1 << 3;}
-       |       tcc_sd RREG ',' RREG
-                       {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;}
-       ;
-
-tcc_sd
-       :       regs /* a_b */ ',' regs /* a_b */
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($1.flags & R_AB && $3.flags & R_AB) {
-                               if($1.ab == $3.ab) 
-                                       yyerror("source and dest must be different");
-                               $$ = $3.ab;
-                       } else if($1.flags & R_XREG && $3.flags & R_AB) {
-                               $$ = 0x8 | $1.xreg << 2 | $3.ab;
-                       } else if($1.flags & R_YREG && $3.flags & R_AB) {
-                               $$ = 0xA | $1.yreg << 2 | $3.ab;
-                       } else 
-                               yyerror("illegal TCC operands");
-                       }
-       ;
-
-sd3    :       regs /* XREG */ ',' regs /* a_b */
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($1.flags & R_XREG && $3.flags & R_AB) {
-                               $$ = $1.xreg << 2 | $3.ab;
-                       } else if($1.flags & R_YREG && $3.flags & R_AB) {
-                               $$ = $1.yreg << 2 | 2 | $3.ab;
-                       }}
-       ;
-
-movec_args
-       :       x_or_y ea ',' regs /* ctl_reg */
-                       {if(NOT ($4.flags & R_CTL_REG))
-                               yyerror("bad MOVEC target register");
-                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
-                               $1 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($1 == 0) {
-                               w0 |= 0x05C020 | $4.ctl_reg;
-                       } else {
-                               w0 |= 0x05C060 | $4.ctl_reg;
-                       }}
-       |       regs /* ctl_reg */ ',' x_or_y ea
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if(NOT ($1.flags & R_CTL_REG))
-                               yyerror("bad MOVEC source register");
-                       if($3 == 0) {
-                               w0 |= 0x054020 | $1.ctl_reg;
-                       } else {
-                               w0 |= 0x054060 | $1.ctl_reg;
-                       }}
-       |       ix ',' regs /* ctl_reg */
-                       {int ival = n2int($1);
-                       if(NOT ($3.flags & R_CTL_REG))
-                               yyerror("bad MOVEC target register");
-                       if(ival < 256 && NOT long_symbolic_expr) {
-                               w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg; 
-                       } else {
-                               w0 |= 0x05C020 | 0x003400 | $3.ctl_reg;
-                               uses_w1++; w1 = ival & 0xFFFF;
-                       }}
-       |       x_or_y abs_short_addr ',' regs /* ctl_reg */
-                       {if($1 == 0) {
-                               w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg;
-                       } else {
-                               w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg;
-                       }
-                       if(NOT ($4.flags & R_CTL_REG))
-                               yyerror("bad MOVEC target register");
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       }
-       |       regs /* ctl_reg */ ',' x_or_y abs_short_addr
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($3 == 0) {
-                               w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg;
-                       } else {
-                               w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg;
-                       }
-                       if(NOT ($1.flags & R_CTL_REG))
-                               yyerror("bad MOVEC source register");
-                       if($4 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       }
-       |       regs /* ctl_reg */ ',' regs
-                       {if($1.flags & R_CTL_REG) {
-                               w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg;
-                       } else if($3.flags & R_CTL_REG) {
-                               w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg;
-                       } else if($1.flags & $3.flags & R_CTL_REG) {
-                               /* bogus? $$$ */
-                               w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | 
-                               $3.ctl_reg;
-                       } else {
-                               yyerror("MOVEC must reference a control reg");
-                       }}
-       ;
-
-movep_args
-       :       x_or_y movep_ea_pp ',' x_or_y movep_ea_pp
-                       {w0 |= 0x084080;
-                       switch($2.pp << 1 | $5.pp) {
-                               case 0: case 3:
-                                       yyerror("illegal MOVEP; can't move EA to EA or IO to IO");
-                                       break;
-                               case 1: /* ea, pp */
-                                       w0 |= $4 << 16 | 1 << 15 | $1 << 6 |
-                                               ($5.ext & 0x3F);
-                                       if($2.mode == 0x003000) {
-                                               w0 |= 0x003000;
-                                               uses_w1++;
-                                               w1 = $2.ext;
-                                       } else {
-                                               w0 |= $2.mode;
-                                       }
-                                       break;
-                               case 2: /* pp, ea */
-                                       w0 |= $1 << 16 | 0 << 15 | $4 << 6 |
-                                               ($2.ext & 0x3F);
-                                       if($5.mode == 0x003000) {
-                                               w0 |= 0x003000;
-                                               uses_w1++;
-                                               w1 = $5.ext;
-                                       } else {
-                                               w0 |= $5.mode;
-                                       }
-                                       break;
-                       }}
-       |       ix ',' x_or_y num_or_sym
-                       {w0 |= 0x084080;
-                       w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | 
-                               (n2int($4) & 0x3F);
-                       uses_w1++;
-                       w1 = n2int($1);}
-       |       PMEM ea ',' x_or_y num_or_sym
-                       {w0 |= 0x084040;
-                       w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);}
-       |       x_or_y movep_ea_pp ',' PMEM ea
-                       {w0 |= 0x084040;
-                       if($2.mode != 0x003000 && $2.mode != 0)
-                               yyerror("illegal MOVEP");
-                       w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);}
-       |       regs ',' x_or_y num_or_sym
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       w0 |= 0x084000;
-                       w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | 
-                               (n2int($4) & 0x3F);}
-       |       x_or_y movep_ea_pp ',' regs
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       w0 |= 0x084000;
-                       if(!$2.pp)
-                               yyerror("illegal MOVEP");
-                       w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);}
-       ;
-
-movep_ea_pp
-       :       abs_addr
-                       {if($1 != UNDEF && $1 >= 0xFFC0) {
-                               /* defined symbol or constant, in i/o range */
-                               $$.pp = 1;
-                               $$.mode = 0;
-                       } else {
-                               /* either out of i/o range or symbol not */
-                               /* yet defined:  assume ea extension */
-                               $$.pp = 0;
-                               $$.mode = 0x003000;
-                       }
-                       $$.ext = $1;}
-       |       io_short_addr   /* forced i/o short */
-                       {$$.pp = 1;
-                       $$.mode = 0;
-                       if($1 < 0xFFC0 && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       $$.ext = $1;}
-       |       ea_no_ext
-                       {$$.pp = 0;
-                       $$.mode = $1 << 8;
-                       $$.ext = $1;}
-       ;
-
-movem_args
-       :       regs ',' PMEM ea_a6
-                       {w0 |= 0x070000 | 0 << 15 | $1.r6;}
-       |       PMEM ea_a6 ',' regs
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       w0 |= 0x070000 | 1 << 15 | $4.r6;}
-       ;
-
-/*%%%**************** memory reference fields ************************/
-
-b5_10111_max
-       :       ix
-                       {int ival = n2int($1);
-                       $$ = ival; if(ival > 0x17) 
-                               yyerror("%d: illegal bit number", ival);}
-       ;
-
-x_or_y
-       :       XMEM
-                       {$$ = 0;}
-       |       YMEM
-                       {$$ = 1;}
-       ;
-
-/*%%%**************** effective address fields ************************/
-
-ea_a6
-       :       ea
-                       {w0 |= 0x004080;}
-       |       abs_short_addr
-                       {w0 |= ($1 & 0x3F) << 8;
-                       if($1 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       }
-       ;
-
-ea_a12
-       :       ea
-                       {$$ = 1;}
-       |       abs_short_addr
-                       {w0 |= $1 & 0xFFF; $$ = 0;
-                       if($1 > 0x0FFF && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       }
-       ;
-
-ea     :       abs_addr
-                       {w0 |= 0x003000;
-                       uses_w1++;
-                       w1 |= $1;
-                       $$ = 0x003000;}
-       |       ea_no_ext
-                       {w0 |= $1 << 8;
-                       $$ = $1 << 8;
-                       expr_seg = ANY;}
-       ;
-
-ea_no_ext
-       :       ea_short
-                       {$$ = $1;}
-       |       '(' RREG ')'
-                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
-                       $$ = 4 << 3 | $2;}
-       |       '(' RREG '+' NREG ')'
-                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
-                       if($4 == prev_hot_nreg) yywarning("warning: n%d just loaded", $4);
-                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
-                       $$ = 5 << 3 | $2;
-                       if($2 != $4) yyerror("Rn and Nn must be same number");}
-       |       '-' '(' RREG ')'
-                       {if($3 == prev_hot_rreg) yywarning("warning: r%d just loaded", $3);
-                       if($3 == prev_hot_mreg) yywarning("warning: m%d just loaded", $3);
-                       $$ = 7 << 3 | $3;}
-       ;
-
-ea_short
-       :       '(' RREG ')' '-' NREG
-                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
-                       if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5);
-                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
-                       $$ = 0 << 3 | $2;
-                       expr_seg = ANY;
-                       if($2 != $5) yyerror("Rn and Nn must be same number");}
-       |       '(' RREG ')' '+' NREG
-                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
-                       if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5);
-                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
-                       $$ = 1 << 3 | $2;
-                       expr_seg = ANY;
-                       if($2 != $5) yyerror("Rn and Nn must be same number");}
-       |       '(' RREG ')' '-'
-                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
-                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
-                       expr_seg = ANY;
-                       $$ = 2 << 3 | $2;}
-       |       '(' RREG ')' '+'
-                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
-                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
-                       expr_seg = ANY;
-                       $$ = 3 << 3 | $2;}
-       ;
-
-/*%%%******************* register fields ******************************/
-
-regs
-       :       XREG
-                       {$$.r6 = $$.r5 = 0x04 | $1;
-                       $$.sdx = $1;
-                       $$.xreg = $1;
-                       $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;}
-       |       YREG
-                       {$$.r6 = $$.r5 = 0x06 | $1;
-                       $$.sdy = $1;
-                       $$.yreg = $1;
-                       $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;}
-       |       AREG
-                       {switch($1) {
-                               case 0: 
-                                       $$.r6 = $$.r5 = 0x08 | 0; 
-                                       break;
-                               case 1: 
-                                       $$.r6 = $$.r5 = 0x08 | 4; 
-                                       break;
-                               case 2: 
-                                       $$.r6 = $$.r5 = 0x08 | 2; 
-                                       break;
-                       }
-                       $$.flags = R_R6|R_R5|R_UINT;}
-       |       BREG
-                       {switch($1) {
-                               case 0: 
-                                       $$.r6 = $$.r5 = 0x08 | 1; break;
-                               case 1: 
-                                       $$.r6 = $$.r5 = 0x08 | 5; break;
-                               case 2: 
-                                       $$.r6 = $$.r5 = 0x08 | 3; break;
-                       }
-                       $$.flags = R_R6|R_R5|R_UINT;}
-       |       AAAA
-                       {$$.r6 = $$.r5 = 0x0E;
-                       $$.sdx = $$.sdy = 0x2;
-                       $$.ab = 0;
-                       $$.lsd = 4;
-                       $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
-       |       BBBB
-                       {$$.r6 = $$.r5 = 0x0F;
-                       $$.sdx = $$.sdy = 0x3;
-                       $$.ab = 1;
-                       $$.lsd = 5;
-                       $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
-       |       RREG
-                       {$$.r6 = $$.r5 = 0x10 | $1;
-                       $$.r4 = 0x00 | $1;
-                       $$.flags = R_R6|R_R5|R_R4|R_UINT;
-                       hot_rreg = $1;}
-       |       NREG
-                       {$$.r6 = $$.r5 = 0x18 | $1;
-                       $$.r4 = 0x08 | $1;
-                       $$.flags = R_R6|R_R5|R_R4|R_UINT;
-                       hot_nreg = $1;}
-       |       MREG
-                       {$$.r6 = 0x20 | $1;
-                       $$.r5 = -1;
-                       $$.ctl_reg = $1;
-                       $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;
-                       hot_mreg = $1;}
-       |       prog_ctl_reg
-                       {$$.r6 = 0x38 | $1;
-                       $$.r5 = -1;
-                       $$.ctl_reg = 0x18 | $1;
-                       $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
-       |       A10
-                       {$$.lsd  = 0;
-                       $$.flags = R_LSD;}
-       |       B10
-                       {$$.lsd = 1;
-                       $$.flags = R_LSD;}
-       |       XXXX
-                       {$$.lsd = 2;
-                       $$.flags = R_LSD;}
-       |       YYYY
-                       {$$.lsd = 3;
-                       $$.flags = R_LSD;}
-       |       AABB
-                       {$$.lsd = 6;
-                       $$.flags = R_LSD;}
-       |       BBAA
-                       {$$.lsd = 7;
-                       $$.flags = R_LSD;}
-       ;
-
-prog_ctl_reg
-       :       SR
-                       {$$ = 1;}
-       |       OMR
-                       {$$ = 2;}
-       |       SP
-                       {$$ = 3;}
-       |       SSH
-                       {$$ = 4;}
-       |       SSL
-                       {$$ = 5;}
-       |       LA
-                       {$$ = 6;}
-       |       LC
-                       {$$ = 7;}
-       ;
-
-funky_ctl_reg
-       :       MR
-                       {$$ = 0;}
-       |       CCR
-                       {$$ = 1;}
-       |       OMR
-                       {$$ = 2;}
-       ;
-
-/*%%%************************* parallel moves *************/
-
-parallel_move
-       :       i_move
-       |       u_move
-       |       x_or_y_move
-       |       xr_move
-       |       ry_move
-       |       r_move
-       |       xy_move
-       |       l_move
-       ;
-
-i_move  :      ix ',' regs
-                       {int ival = n2int($1);
-                       int frac = n2frac($1);
-                       int value;
-                       BOOL shortform = FALSE;
-                       if($3.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       if(($3.flags & R_SFRAC) && $1.type == FLT) {
-                               if((frac & 0xFFFF) == 0 && 
-                                       NOT long_symbolic_expr) {
-                                       value = frac >> 16;
-                                       shortform++;
-                               } else {
-                                       value = frac;
-                               }
-                       } else {
-                               if(ival <= 0xFF && ival >= -0xFF && NOT long_symbolic_expr) {
-                                       value = ival;
-                                       shortform++;
-                               } else {
-                                       value = ival;
-                               }
-                       }
-
-                       if(shortform) {
-                               w0 |= 0x200000 | (value & 0xFF) << 8 |
-                                       $3.r5 << 16;
-                       } else {
-                               w0 |= 0x400000 | 0x00F400 |
-                                       ($3.r5 >> 3 & 3) << 20 | 
-                                       ($3.r5 & 7) << 16;
-                               uses_w1++; w1 = value;
-                       }}
-       ;
-
-r_move :       regs ',' regs
-                       {
-                               if($3.flags & R_CTL_REG) {
-                                       yyerror("please use MOVEC for control register moves");
-                                       break;
-                               }
-                               if($1.flags & R_R5 & $3.flags) 
-                                       w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13;
-                               else
-                                       yyerror("illegal R move");
-                       }       
-       ;
-
-u_move :       ea_short
-                       {w0 |= 0x204000 | $1 << 8;}
-       ;
-
-x_or_y_move
-       :       x_or_y ea ',' regs
-                       {w0 |= 0x40C000 | $1 << 19;
-                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
-                               $1 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($4.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
-       |       x_or_y abs_short_addr ',' regs
-                       {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8;
-                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
-                               $1 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($4.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
-       |       regs ',' x_or_y ea
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       w0 |= 0x404000 | $3 << 19;
-                       if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
-                               $3 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($1.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
-       |       regs ',' x_or_y abs_short_addr
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8;
-                       if($1.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
-                               $3 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($4 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
-       |       ix_long ',' regs
-                       {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 |
-                           ($3.r5 & 7) << 16;
-                       if($3.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       uses_w1++; w1 = n2frac($1);
-                       }
-       ;
-
-xr_move
-       :       x_or_y /* XMEM */ ea ',' regs   regs /* a_b */ ',' YREG
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
-                               $1 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($1 == 0 && $5.flags & R_AB) {
-                               w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 |
-                                       $7 << 16;
-                       } else {
-                               yyerror("illegal X:R move");
-                       }}
-       |       ix ',' regs             regs /* a_b */ ',' YREG
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($4.flags & R_AB) {
-                               w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 |
-                                       $6 << 16;
-                               uses_w1++;
-                               w1 |= n2frac($1) & 0xFFFFFF;
-                       } else {
-                               yyerror("illegal X:R move");
-                       }}
-       |       regs ',' x_or_y /* XMEM */ ea   regs /* a_b */ ',' regs/*YREG*/
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
-                               $3 == 1 && expr_seg != YDATA))
-                               yywarning("warning: space mismatch");
-                       if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB &&
-                               $7.flags & R_YREG) {
-                               w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 |
-                                       $7.yreg << 16;
-                       } else if($1.flags & R_AB && $3 == 0 && 
-                               $5.flags & R_XREG && $7.flags & R_AB) {
-                               if($5.xreg != 0) yyerror("must use X0");
-                               if($1.ab == 0 && $7.ab == 0)
-                                       w0 |= 0x080000;
-                               else if($1.ab == 1 && $7.ab == 1)
-                                       w0 |= 0x090000;
-                               else
-                                       yyerror("illegal X:R move");
-                       } else {
-                               yyerror("illegal X:R move");
-                       }}
-       ;
-
-ry_move        :       regs /* a_b */ ',' regs /* XREG */      YMEM ea ',' regs
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) {
-                               w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 |
-                                       $7.sdy << 16;
-                       } else {
-                               yyerror("illegal R:Y move");
-                       }}
-       |       regs /* a_b */ ',' regs /* XREG */      ix ',' regs
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) {
-                               w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 |
-                                       $6.sdy << 16;
-                               uses_w1++;
-                               w1 |= n2frac($4) & 0xFFFFFF;
-                       } else {
-                               yyerror("illegal R:Y move");
-                       }}
-       |       regs /* a_b */ ',' regs /* XREG */      regs ',' YMEM ea
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($1.flags & R_AB && $3.flags & R_XREG) {
-                               w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 |
-                               $4.sdy << 16;
-                       } else if ($1.flags & R_YREG && $3.flags & R_AB &&
-                               $4.flags & R_AB) {
-                               if($1.yreg != 0) yyerror("must use Y0");
-                               if($3.ab == 0 && $4.ab == 0)
-                                       w0 |= 0x088000;
-                               else if($3.ab == 1 && $4.ab == 1)
-                                       w0 |= 0x098000;
-                               else
-                                       yyerror("illegal R:Y move");
-                       } else {
-                               yyerror("illegal R:Y move");
-                       }}
-       ;
-
-l_move
-       :       LMEM ea ',' regs /* lsd */
-                       {if($4.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;}
-       |       regs /* lsd */ ',' LMEM ea
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       if($1.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;}
-       |       LMEM abs_short_addr ',' regs /* lsd */
-                       {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;
-                       if($4.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       if($2 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       w0 |= ($2 & 0x3F) << 8;}
-       |       regs /* lsd */ ',' LMEM abs_short_addr
-                       {hot_rreg = hot_nreg = hot_mreg = -1;
-                       w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;
-                       if($1.flags & R_CTL_REG) {
-                               yyerror("please use MOVEC for control register moves");
-                               break;
-                       }
-                       if($4 > 0x003F && pass == 2)
-                               yywarning("warning: address operand truncated");
-                       w0 |= ($4 & 0x3F) << 8;}
-       ;
-
-xy_move
-       :       x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs      YMEM ea /*ea_strange*/ ',' regs
-                       {int eax = $2, eay = $6,
-                            regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
-                            regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       if((eax & 0x400) == (eay & 0x400))
-                               yyerror("registers must be in opposite halves");
-                       if(!($4.flags & (R_AB | R_XREG)))
-                               yyerror("invalid X move register");
-                       if(!($8.flags & (R_AB | R_YREG)))
-                               yyerror("invalid Y move register");
-                       if($4.flags & R_AB &&
-                          $8.flags & R_AB &&
-                          $4.ab == $8.ab)
-                               yyerror("duplicate destination register");
-                       w0 = w0 & 0xFF | 0xC08000;      /* both write */
-                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
-       |       x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs      regs ',' YMEM ea /*ea_strange*/
-                       {int eax = $2, eay = $8,
-                            regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
-                            regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       if((eax & 0x400) == (eay & 0x400))
-                               yyerror("registers must be in opposite halves");
-                       if(!($4.flags & (R_AB | R_XREG)))
-                               yyerror("invalid X move register");
-                       if(!($5.flags & (R_AB | R_YREG)))
-                               yyerror("invalid Y move register");
-                       w0 = w0 & 0xFF | 0x808000;      /* X:write, Y:read */
-                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
-       |       regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/      YMEM ea /*ea_strange*/ ',' regs
-                       {int eax = $4, eay = $6,
-                            regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
-                            regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       if((eax & 0x400) == (eay & 0x400))
-                               yyerror("registers must be in opposite halves");
-                       if(!($1.flags & (R_AB | R_XREG)))
-                               yyerror("invalid X move register");
-                       if(!($8.flags & (R_AB | R_YREG)))
-                               yyerror("invalid Y move register");
-                       w0 = w0 & 0xFF | 0xC00000;      /* X:read, Y:write */
-                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
-       |       regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/      regs ',' YMEM ea /*ea_strange*/
-                       {int eax = $4, eay = $8,
-                            regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
-                            regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
-                       hot_rreg = hot_nreg = hot_mreg = -1;
-                       if((eax & 0x400) == (eay & 0x400))
-                               yyerror("registers must be in opposite halves");
-                       if(!($1.flags & (R_AB | R_XREG)))
-                               yyerror("invalid X move register");
-                       if(!($5.flags & (R_AB | R_YREG)))
-                               yyerror("invalid Y move register");
-                       w0 = w0 & 0xFF | 0x800000;      /* both read */
-                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
-       ;
-
-/*%%%******* absolute address and immediate data fields ************/
-
-num    :       CHEX
-                       {$$ = $1;}
-       |       CDEC
-                       {$$ = $1;}
-       |       FRAC
-                       {$$ = $1;}
-       ;
-
-ix     :       '#' expr
-                       {$$ = $2; expr_seg = ANY;}
-       |       '#' '<' expr
-                       {$$.val.i = n2int($3) & 0xFF;
-                       $$.type = INT;
-                       expr_seg = ANY;
-                       long_symbolic_expr = FALSE;}
-       ;
-
-ix_long        :       '#' '>' expr
-                       {$$ = $3; expr_seg = ANY;}
-       ;
-
-abs_addr
-       :       expr
-                       {$$ = n2int($1);
-                       expr_seg = $1.seg;}
-       ;
-
-abs_short_addr
-       :       '<' expr
-                       {$$ = n2int($2);
-                       expr_seg = $2.seg;}
-       ;
-
-io_short_addr
-       :       SHL expr
-                       {$$ = n2int($2);
-                       expr_seg = $2.seg;} 
-       ;
-
-num_or_sym
-       :       num
-                       {$$ = $1;}
-       |       SYM
-                       {$$ = sym_ref($1); free($1);}
-       |       io_short_addr
-                       {$$.type = INT; $$.val.i = $1; $$.seg = expr_seg;}
-       ;
-
-num_or_sym_expr
-       :       num
-                       {$$ = $1; expr_seg = $1.seg;}
-       |       SYM
-                       {$$ = sym_ref($1);
-                       free($1);
-                       long_symbolic_expr++;
-                       expr_seg = $$.seg;
-                       }
-       |       CHAR
-                       {$$.type = INT; $$.val.i = $1 & 0xFFFFFF; expr_seg = $$.seg = ANY;}
-       |       '*'
-                       {$$.type = INT; $$.val.i = pc; expr_seg = $$.seg = ANY;}
-       |       OP_PI
-                       {$$.type = FLT; $$.val.f = acos(-1.0); expr_seg = $$.seg = ANY;}
-       ;
-
-expr
-       :       OP_INT '(' expr ')'
-                       {$$.type = INT; 
-                       if($3.type == INT)
-                               $$.val.i = $3.val.i;
-                       else
-                               $$.val.i = $3.val.f;
-                       $$.seg = $3.seg;
-                       }
-       |       expr '|' expr
-                       {$$ = binary_op($1, '|', $3);}
-       |       expr '^' expr
-                       {$$ = binary_op($1, '^', $3);}
-       |       expr '&' expr
-                       {$$ = binary_op($1, '&', $3);}
-       |       expr SHR expr
-                       {$$ = binary_op($1, SHR, $3);}
-       |       expr SHL expr
-                       {$$ = binary_op($1, SHL, $3);}
-       |       expr '-' expr
-                       {$$ = binary_op($1, '-', $3);}
-       |       expr '+' expr
-                       {$$ = binary_op($1, '+', $3);}
-       |       expr '%' expr
-                       {$$ = binary_op($1, '%', $3);}
-       |       expr '/' expr
-                       {$$ = binary_op($1, '/', $3);}
-       |       expr '*' expr
-                       {$$ = binary_op($1, '*', $3);}
-       |       '-' expr %prec '~'
-                       {$$ = unary_op('-', $2);}
-       |       '~' expr
-                       {$$ = unary_op('~', $2);}
-       |       OP_SIN '(' expr ')'
-                       {$$ = unary_op('s', $3);}
-       |       OP_COS '(' expr ')'
-                       {$$ = unary_op('c', $3);}
-       |       OP_TAN '(' expr ')'
-                       {$$ = unary_op('t', $3);}
-       |       OP_ASIN '(' expr ')'
-                       {$$ = unary_op('S', $3);}
-       |       OP_ACOS '(' expr ')'
-                       {$$ = unary_op('C', $3);}
-       |       OP_ATAN '(' expr ')'
-                       {$$ = unary_op('T', $3);}
-       |       OP_EXP '(' expr ')'
-                       {$$ = unary_op('e', $3);}
-       |       OP_LN '(' expr ')'
-                       {$$ = unary_op('l', $3);}
-       |       OP_LOG '(' expr ')'
-                       {$$ = unary_op('L', $3);}
-       |       OP_ABS '(' expr ')'
-                       {$$ = unary_op('a', $3);}
-       |       OP_POW '(' expr ',' expr ')'
-                       {$$ = binary_op($3, 'p', $5);}
-       |       '(' expr ')'
-                       {$$ = $2;}
-       |       num_or_sym_expr
-                       {$$ = $1;}
-       ;
-
-/*%%%****************** end ******************************/
-
-%%
-
-#include <stdio.h>
-#include <setjmp.h>
-#include <sys/signal.h>
-
-int yydebug;
-
-struct n binary_op(a1, op, a2)
-struct n a1, a2;
-int op;
-{
-       struct n result;
-       int iarg1, iarg2;
-       double farg1, farg2;
-
-       if(a1.type == UNDEF || a2.type == UNDEF) {
-               result.type = UNDEF;
-               return result;
-       }
-
-       iarg1 = a1.type == INT ? a1.val.i : a1.val.f;
-       iarg2 = a2.type == INT ? a2.val.i : a2.val.f;
-
-       farg1 = a1.type == INT ? a1.val.i : a1.val.f;
-       farg2 = a2.type == INT ? a2.val.i : a2.val.f;
-
-       /* figure out target segment */
-
-       if(a1.seg == a2.seg)
-               result.seg = a1.seg;
-       else if(a1.seg == ANY)
-               result.seg = a2.seg;
-       else if(a2.seg == ANY)
-               result.seg = a1.seg;
-       else
-               result.seg = NONE;
-
-       /* promote to float automatically */
-
-       if(a1.type != a2.type) {
-               if(a1.type == INT) {
-                       a1.val.f = a1.val.i;            /* truncate */
-                       a1.type = FLT;
-               } else {
-                       a2.val.f = a2.val.i;            /* truncate */
-               }
-       }
-       result.type = a1.type;
-
-       /* do the op */
-
-       switch(op) {
-       case '+':
-               if(result.type == INT) result.val.i = a1.val.i + a2.val.i;
-               else result.val.f = a1.val.f + a2.val.f;
-               break;
-       case '-':
-               if(result.type == INT) result.val.i = a1.val.i - a2.val.i;
-               else result.val.f = a1.val.f - a2.val.f;
-               break;
-       case '*':
-               if(result.type == INT) result.val.i = a1.val.i * a2.val.i;
-               else result.val.f = a1.val.f * a2.val.f;
-               break;
-       case '/':
-               if(result.type == INT) result.val.i = a1.val.i / a2.val.i;
-               else result.val.f = a1.val.f / a2.val.f;
-               break;
-       case '%':
-               result.val.i = iarg1 % iarg2;
-               result.type = INT;
-               break;
-       case SHL:
-               result.val.i = iarg1 << iarg2;
-               result.type = INT;
-               break;
-       case SHR:
-               result.val.i = iarg1 >> iarg2;
-               result.type = INT;
-               break;
-       case '|':
-               result.val.i = iarg1 | iarg2;
-               result.type = INT;
-               break;
-       case '&':
-               result.val.i = iarg1 & iarg2;
-               result.type = INT;
-               break;
-       case '^':
-               result.val.i = iarg1 ^ iarg2;
-               result.type = INT;
-               break;
-       case 'p':
-               result.val.f = pow(farg1, farg2);
-               result.type = FLT;
-       }
-
-       return result;
-}
-
-jmp_buf unary_env;
-
-void
-sigfpu()
-{
-       longjmp(unary_env, 1);
-}
-
-char *unary_name(op)
-{
-       switch(op) {
-       case 's':       return "sin";
-       case 'c':       return "cos";
-       case 't':       return "tan";
-       case 'S':       return "asin";
-       case 'C':       return "acos";
-       case 'T':       return "atan";
-       case 'e':       return "exp";
-       case 'l':       return "ln";
-       case 'L':       return "log";
-       case 'a':       return "abs";
-       }
-}
-
-struct n unary_op(op, a1)
-int op;
-struct n a1;
-{
-       struct n result;
-       void (*orig)();
-       double farg;
-
-       if(a1.type == UNDEF) {
-               result.type = UNDEF;
-               return result;
-       }
-
-       result.seg = a1.seg;
-
-       /* do the op */
-
-       orig = signal(SIGFPE, sigfpu);
-       if(setjmp(unary_env)) {
-               yyerror("floating point exception in function %s", unary_name(op));
-               result.val.i = result.val.f = 0;
-       } else {
-               farg = a1.type == INT ? (double)a1.val.i : a1.val.f;
-               switch(op) {
-               case '-':
-                       result.type = a1.type;
-                       if(a1.type == INT) result.val.i = -a1.val.i;
-                       else result.val.f = -a1.val.f;
-                       break;
-               case '~':
-                       result.type = a1.type;
-                       if(a1.type == INT) result.val.i = ~a1.val.i;
-                       else result.val.f = ~(int)a1.val.f;
-                       break;
-               case 'a':
-                       result.type = a1.type;
-                       if(a1.type == INT) result.val.i = a1.val.i < 0 ? -a1.val.i : a1.val.i;
-                       else result.val.f = result.val.f = a1.val.f < 0 ? -a1.val.f : a1.val.f;
-                       break;
-               case 's':
-                       result.type = FLT;
-                       result.val.f = sin(farg);
-                       break;
-               case 'c':
-                       result.type = FLT;
-                       result.val.f = cos(farg);
-                       break;
-               case 't':
-                       result.type = FLT;
-                       result.val.f = tan(farg);
-                       break;
-               case 'S':
-                       result.type = FLT;
-                       result.val.f = asin(farg);
-                       break;
-               case 'C':
-                       result.type = FLT;
-                       result.val.f = acos(farg);
-                       break;
-               case 'T':
-                       result.type = FLT;
-                       result.val.f = atan(farg);
-                       break;
-               case 'e':
-                       result.type = FLT;
-                       result.val.f = exp(farg);
-                       break;
-               case 'l':
-                       result.type = FLT;
-                       result.val.f = log(farg);
-                       break;
-               case 'L':
-                       result.type = FLT;
-                       result.val.f = log10(farg);
-                       break;
-               }
-       }
-       signal(SIGFPE, orig);
-
-       return result;
-}
-
-n2int(n)
-struct n n;
-{
-       if(n.type == UNDEF)
-               return UNDEF;
-       else if(n.type == INT)
-               return n.val.i;
-       else
-               return n.val.f;
-}
-
-n2frac(n)
-struct n n;
-{
-       double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f;
-
-       if(n.type == UNDEF)
-               return UNDEF;
-       else if(n.type == INT)
-               return n.val.i;
-       else if(n.val.f == -1.0)
-               return 0x800000;
-
-       adval -= (double)(int)adval;
-       adval *= (double)0x800000;
-       adval += 0.5;
-
-       if(n.val.f >= 0.0)
-               return adval;
-       else
-               return -adval;
-}
-
-extern struct {int n; char *name;} tok_tab[];
-extern int n_tok;
-
-char *tok_print(tok)
-int tok;
-{
-       int i;
-       static char buf[32];
-
-       if(tok == '1') {
-               i = 1;
-       }
-
-       if(tok < 256) {
-               sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF);
-               return buf;
-       } else {
-               for(i = 0; i < n_tok; i++) {
-                       if(tok == tok_tab[i].n)
-                               return tok_tab[i].name;
-               }
-       }
-       return "*bogus*";
-}
-
-yyerror(s, a0, a1, a2, a3)
-char *s, *a0, *a1, *a2, *a3;
-{
-       extern int error;
-       char buf[1024];
-
-       error++;
-       sprintf(buf, s, a0, a1, a2, a3);
-
-       if(pass == 2) {
-               fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
-                       buf, tok_print(yychar));
-               fprintf(stderr, "%s\n", cur_line);
-               printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
-                       buf, tok_print(yychar));
-       }
-}
-
-yywarning(s, a0, a1, a2, a3)
-char *s, *a0, *a1, *a2, *a3;
-{
-       extern int warning;
-       char buf[1024];
-
-       warning++;
-       sprintf(buf, s, a0, a1, a2, a3);
-
-       if(pass == 2) {
-               fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
-                       buf, tok_print(yychar));
-               fprintf(stderr, "%s\n", cur_line);
-               printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
-                       buf, tok_print(yychar));
-       }
-}
-
-char *luntab(s)
-char *s;
-{
-       static char buf[1024];
-       int p;
-
-       strcpy(buf, s);
-
-       untab(buf);
-       p = strlen(buf);
-
-       if(buf[p - 1] == '\n')
-               buf[p - 1] = '\0';
-
-       return buf;
-}
diff --git a/frac2int.c b/frac2int.c
deleted file mode 100644 (file)
index 8f01796..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-#if 0
-+----------------------------------------------------------------------+
-|   Question: My filter design package gives me decimal fractional     |
-|             numbers  as output  for my  FIR filter coefficients.     |
-|             How  do I convert  these decimal fractions  into the     |
-|             DSP56200's format?                                       |
-+----------------------------------------------------------------------+
-
-      Answer:
-           It's fairly easy to convert decimal fractions into  the
-      data  format required by the DSP56200.  The DSP56200 coeffi-
-      cients are represented as  24-bit  signed,  fractional,  2's
-      complement numbers as shown in Table 1.
-
-         TABLE 1 - Representations for FIR Filter Coefficients
-         -----------------------------------------------------
-
-          Decimal                                  Hexadecimal
-          Fraction       24-Bit Binary Value       Coefficient
-          --------       -------------------       ----------
-
-            0.75     0.1100000 00000000 00000000    60 00 00
-            0.5      0.1000000 00000000 00000000    40 00 00
-            0.25     0.0100000 00000000 00000000    20 00 00
-            0.125    0.0010000 00000000 00000000    10 00 00
-           -0.125    1.1110000 00000000 00000000    F0 00 00
-           -0.75     1.0100000 00000000 00000000    A0 00 00
-
-      Each  24-bit  coefficient  is  separated  into  three  bytes
-      corresponding  to the high, middle, and low bytes.  The high
-      byte is written to the DSP56200 at  address  0A  (hex),  the
-      middle byte to address 0B (hex), and the low byte to address
-      0C (hex).
-
-      Conversion Procedure:
-
-         Step 1:  Multiply the decimal fraction by 8388608.0 (decimal).
-                  Note that 8388608 = 2 raised to the 23rd power.
-         Step 2:  Truncate or round the result into an integer.
-         Step 3:  Logically AND this integer with 00FFFFFF (hex).
-         Step 4:  Write the result to an output file as a hex integer.
-
-      It is easy to write a program to perform this conversion  on
-      a  set  of  coefficients.  If done by computer program, make
-      sure that all integer  variables  are  represented  with  at
-      least  24-bits.   An  example  of  a  short  "C"  program is
-      included at the end of this answer.
-
-      Things to watch for:
-
-         (1) Avoid letting a coefficient value be exactly 800000
-             (-1.0 in a fractional system).  If this coefficient
-             is multiplied by a data sample with value -1.0, the
-             result is -1.0 instead of +1.0 as expected. This is
-             because +1.0 cannot be represented in a signed, 2's
-             complement, fractional system.
-
-         (2) The filter coefficients must  be carefully selected
-             to prevent overflow.   If there is a possibility of
-             overflow with a set of filter coefficients, then all
-             coefficients must be scaled by a constant value. The
-             DSP56200's 24-bit coefficients  allow plenty of room
-             for scaling.   If 12-bit input data samples are used
-             in a system,  the potential  for overflow is greatly
-             reduced if the samples are right justified and sign-
-             extended four bits before they are sent to the 
-             DSP56200.
-
-"C" Program:
-#endif
-           /****************************************\
-           **  DECIMAL FRACTION TO HEX CONVERSION  **
-           \****************************************/
-
-/******************************************************************\
-*  This program converts one decimal, fractional number to a hex   *
-*  number which can be written to the DSP56200's Coefficient RAM   *
-*  Access registers.  It prompts the user for a decimal fraction   *
-*  and returns the corresponding hex number.                       *
-*                                                                  *
-*   Examples of Program Results (useful for checking programs)     *
-*        Inputs                    Outputs                         *
-*        ------                    -------                         *
-*         0.750                =>  600000                          *
-*         0.500                =>  400000                          *
-*         0.250                =>  200000                          *
-*         0.125                =>  100000                          *
-*        -0.125                =>  f00000                          *
-*        -0.750                =>  a00000                          *
-*         0.00784313678741455  =>  010101                          *
-*        -0.00784313678741455  =>  fefeff                          *
-*                                                                  *
-*   Note: The program assumes that the variable type "long" is an  *
-*         integer which is at least 24-bits wide.                  *
-*                                                                  *
-*   Also: The DSP56200 cannot  use any coefficient value with a    *
-*         magnitude of 1.0 or larger.  All coefficients must be    *
-*         signed, fractional quantities.                           *
-\******************************************************************/
-
-main()
-{
-           double fractnum;              /* double precision floating pt */
-           long   hexval;                /* long integer */
-
-    for(;;) {
-        /* Read 1 Decimal Floating Point Number from the Keyboard */
-           printf("Enter the decimal fraction: ");
-           scanf("%lf", &fractnum);
-
-        /* Convert to a Hex Integer which can be used by the DSP56200 */
-           hexval =  (long) (8388608.0 * fractnum);
-           hexval =  0x00ffffffL & hexval;
-
-        /* Write the Hex number out to the Terminal */
-           printf("DSP56200 Coefficient = %06lx\n", hexval);
-    }
-}
diff --git a/getopt.c b/getopt.c
deleted file mode 100644 (file)
index 6d74b39..0000000
--- a/getopt.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-       I got this off net.sources from Henry Spencer.
-       It is a public domain getopt(3) like in System V.
-       I have made the following modifications:
-
-       index(s,c) was added because too many people could
-       not compile getopt without it.
-
-       A test main program was added, ifdeffed by GETOPT.
-       This main program is a public domain implementation
-       of the getopt(1) program like in System V.  The getopt
-       program can be used to standardize shell option handling.
-               e.g.  cc -DGETOPT getopt.c -o getopt
-*/
-#include <stdio.h>
-
-#ifndef lint
-static char    sccsfid[] = "@(#) getopt.c 5.0 (UTZoo) 1985";
-#endif
-
-#define        ARGCH    (int)':'
-#define BADCH   (int)'?'
-#define EMSG    ""
-#define        ENDARGS  "--"
-
-/* this is included because index is not on some UNIX systems */
-static
-char *
-index (s, c)
-register       char    *s;
-register       int     c;
-       {
-       while (*s)
-               if (c == *s) return (s);
-               else s++;
-       return (NULL);
-       }
-
-/*
- * get option letter from argument vector
- */
-int    opterr = 1,             /* useless, never set or used */
-       optind = 1,             /* index into parent argv vector */
-       optopt;                 /* character checked for validity */
-char   *optarg;                /* argument associated with option */
-
-#define tell(s)        fputs(*nargv,stderr);fputs(s,stderr); \
-               fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
-\f
-
-getopt(nargc,nargv,ostr)
-int    nargc;
-char   **nargv,
-       *ostr;
-{
-       static char     *place = EMSG;  /* option letter processing */
-       register char   *oli;           /* option letter list index */
-       char    *index();
-
-       if(!*place) {                   /* update scanning pointer */
-               if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
-               if (*place == '-') {    /* found "--" */
-                       ++optind;
-                       return(EOF);
-               }
-       }                               /* option letter okay? */
-       if ((optopt = (int)*place++) == ARGCH || !(oli = index(ostr,optopt))) {
-               if(!*place) ++optind;
-               tell(": illegal option -- ");
-       }
-       if (*++oli != ARGCH) {          /* don't need argument */
-               optarg = NULL;
-               if (!*place) ++optind;
-       }
-       else {                          /* need an argument */
-               if (*place) optarg = place;     /* no white space */
-               else if (nargc <= ++optind) {   /* no arg */
-                       place = EMSG;
-                       tell(": option requires an argument -- ");
-               }
-               else optarg = nargv[optind];    /* white space */
-               place = EMSG;
-               ++optind;
-       }
-       return(optopt);                 /* dump back option letter */
-}
-
-\f
-#ifdef GETOPT
-
-#ifndef lint
-static char    sccspid[] = "@(#) getopt.c 5.1 (WangInst) 6/15/85";
-#endif
-
-main (argc, argv) char **argv;
-       {
-       char    *optstring = argv[1];
-       char    *argv0 = argv[0];
-       extern  int     optind;
-       extern  char    *optarg;
-       int     opterr = 0;
-       int     C;
-       char    *opi;
-       if (argc == 1)
-               {
-               fprintf (stderr, "Usage: %s optstring args\n", argv0);
-               exit (1);
-               }
-       argv++;
-       argc--;
-       argv[0] = argv0;
-       while ((C = getopt (argc, argv, optstring)) != EOF)
-               {
-               if (C == BADCH) opterr++;
-               printf ("-%c ", C);
-               opi = index (optstring, C);
-               if (opi && opi[1] == ARGCH)
-                       if (optarg)
-                               printf ("\"%s\" ", optarg);
-                       else opterr++;
-               }
-       printf ("%s", ENDARGS);
-       while (optind < argc)
-               printf (" \"%s\"", argv[optind++]);
-       putchar ('\n');
-       exit (opterr);
-       }
-
-#endif
diff --git a/keybld.1 b/keybld.1
deleted file mode 100644 (file)
index 758349c..0000000
--- a/keybld.1
+++ /dev/null
@@ -1,24 +0,0 @@
-.\"
-.\" Copyright (C) 1990-1998 Quinn C. Jensen
-.\"
-.\" Permission to use, copy, modify, distribute, and sell this software
-.\" and its documentation for any purpose is hereby granted without fee,
-.\" provided that the above copyright notice appear in all copies and
-.\" that both that copyright notice and this permission notice appear
-.\" in supporting documentation.  The author makes no representations
-.\" about the suitability of this software for any purpose.  It is
-.\" provided "as is" without express or implied warranty.
-.\"
-.\"
-.TH A56-keybld 1 "November 26, 2012"
-.SH NAME
-a56-keybld \- Motorola DSP56001 assembler \-  build finite-state parser
-.SH SYNOPSIS
-.B a56-keybld  > output < input
-.SH DESCRIPTION
-.PP
-builds a finite-state parser for the given keyword list in input file
-.SH AUTHORS
-Copyright (C) 1990-1998 Quinn C. Jensen.
-This manual page was written by Thorsten Alteholz <debian@alteholz.de>,
-for the Debian GNU/Linux system (but may be used by others).
diff --git a/keybld.c b/keybld.c
deleted file mode 100644 (file)
index f3d6ce6..0000000
--- a/keybld.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 1990-1994 Quinn C. Jensen
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.  The author makes no representations
- * about the suitability of this software for any purpose.  It is
- * provided "as is" without express or implied warranty.
- *
- */
-static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
-
-/*
- * keybld - builds a finite-state parser for the given keyword list
- *
- */
-
-#include <stdio.h>
-#include "a56.h"
-
-char buf[1024];
-
-main()
-{
-       int line = 0;
-
-       while(gets(buf)) {
-               char *bp = buf;
-               line++;
-               while(*bp != '\t' && *bp != ' ') bp++;
-               *bp++ = '\0';
-               while(*bp == '\t' || *bp == ' ') bp++;
-               if(strcmp(buf, ".code") == 0) {
-                       printf("%s\n", bp);
-               } else if(add_tok(buf, bp) == -1) {
-                       fprintf(stderr, "input line %d: ambiguous\n", line);
-               }
-       }
-
-       dump_machine();
-       return 0;
-}
-
-#define MAX_CHAR 'z'
-
-#define TRANSITIONS (MAX_CHAR + 1)
-
-struct state {
-       int number;
-       char *seen;
-       struct trans {
-               char action;
-               void *arg;
-       } trans[TRANSITIONS];
-       struct state *next;
-} empty_state, *stop = NULL, *scur = NULL, *new_state();
-int n_states = 0;
-
-/* actions */
-#define NOMATCH 0      /* argument is nothing */
-#define GOTO 1         /* argument is target state */
-#define TERMINAL 2     /* argument is which user action to perform */
-
-struct user_action {
-       char *action;
-       struct user_action *next;
-} *utop = NULL, *ucur = NULL;
-int n_user_actions = 0;
-
-add_tok(tok, actions)
-char *tok, *actions;
-{
-       struct state *scur;
-       struct user_action *unew = (struct user_action *)alloc(sizeof *unew);
-       unew->action = strsave(actions);
-       unew->next = NULL;
-       if(ucur)
-               ucur->next = unew;
-       ucur = unew;
-       if(utop == NULL)
-               utop = unew;
-
-       if(stop == NULL)
-               new_state(NULL);
-
-       if(follow(*tok, tok + 1, stop) == -1)
-               return -1;
-
-       n_user_actions++;
-       return 0;
-}
-
-follow(c, tp, sp)
-char c;
-char *tp;
-struct state *sp;
-{
-       struct trans *arcp, *arcup;
-       
-       if(c >= 'a' && c <= 'z') {
-               c -= 'a' - 'A';
-       }
-       arcp = sp->trans + c;
-
-       if(c >= 'A' && c <= 'Z') {
-               arcup = sp->trans + c + 'a' - 'A';
-       } else {
-               arcup = arcp;
-       }
-
-       if(c == '\0') {
-               if(arcp->action == TERMINAL) {
-                       return -1;
-               } else {
-                       arcp->action = arcup->action = TERMINAL;
-                       arcp->arg = arcup->arg = (void *)n_user_actions;
-                       return 0;
-               }
-       } else {
-               if(arcp->action == GOTO) {
-                       return follow(*tp, tp + 1, arcp->arg);
-               } else {
-                       struct state *new = new_state(tp);
-                       arcp->action = arcup->action = GOTO;
-                       arcp->arg = arcup->arg = (void *)new;
-                       return follow(*tp, tp + 1, new);
-               }
-       }
-}
-
-struct state *new_state(tp)
-char *tp;
-{
-       struct state *snew = (struct state *)alloc(sizeof *snew);
-       char tmp[1024];
-
-       *snew = empty_state;
-
-       snew->number = n_states++;
-
-       snew->next = NULL;
-
-       if(scur)
-               scur->next = snew;
-       scur = snew;
-
-       if(stop == NULL)
-               stop = snew;
-
-       if(tp) {
-               strncpy(tmp, buf, tp - buf);
-               tmp[tp - buf] = '\0';
-       } else
-               strcpy(tmp, "<nothing>");
-
-       snew->seen = strsave(tmp);
-
-       return snew;
-}
-
-dump_machine()
-{
-       struct state *sp;
-       struct user_action *up;
-       int n, a;
-
-       printf("/* state machine generated by keybld */\n");
-       printf("/* states=%d actions=%d */\n", n_states, n_user_actions);
-       printf("/* %d bytes required for transition table storage */\n",
-               sizeof(short) * TRANSITIONS * n_states);
-
-       printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS);
-       for(n = 0, sp = stop; sp; sp = sp->next, n++) {
-               printf("        /* state %d: \"%s\" */\n", n, sp->seen);
-               printf("        {");
-               for(a = 0; a < TRANSITIONS; a++) {
-                       struct trans *tp = sp->trans + a;
-                       switch(tp->action) {
-                       case GOTO:
-                               printf("%d", ((struct state *)tp->arg)->number);
-                               break;
-                       case TERMINAL:
-                               printf("%d", -(int)tp->arg - 1);
-                               break;
-                       case NOMATCH:
-                               printf("0");
-                               break;
-                       }
-                       printf(",%s", a % 20 == 19 ? "\n\t\t" : "");
-               };
-               printf("},\n");
-       }
-
-       printf("};\n");
-
-       printf("\
-\n\
-kparse(kp)\n\
-char *kp;\n\
-{\n\
-       int state = 0;\n\
-\n\
-       for(;;) {\n\
-               short transition = transitions[state][*kp];\n");
-
-printf("\
-               if(transition == 0) {\n\
-                       return 0;\n\
-               } else if(transition > 0) {\n\
-                       kp++;\n\
-                       state = transition;\n\
-               } else {\n\
-                       switch(-transition) {\n");
-
-       for(n = 1, up = utop; up; up = up->next, n++) {
-               printf("\
-                       case %d:\n\
-                               %s;\n\
-                               break;\n", n, up->action);
-       }
-
-       printf("\
-                       }\n\
-                       return transition;\n\
-               }\n\
-       }\n\
-}\n");
-
-}
diff --git a/lex.c b/lex.c
deleted file mode 100644 (file)
index 2f09a34..0000000
--- a/lex.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*******************************************************
- *
- *  a56 - a DSP56001 assembler
- *
- *  Written by Quinn C. Jensen
- *  July 1990
- *
- *******************************************************\
-
-/*
- * Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
- *
- * This file 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 3 of the License,
- * 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, see
- * <http://www.gnu.org/licenses/>.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * Copyright (C) 1990-1998 Quinn C. Jensen
- *
- * Permission to use, copy, modify, distribute, and sell this
- * software and its documentation for any purpose is hereby granted
- * without fee, provided that the above copyright notice appear in
- * all copies and that both that copyright notice and this permission
- * notice appear in supporting documentation.  The author makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- */
-
-/*
- *  lex.c - lexical analyzer envelope.  lexyy.c, included below,
- *  is the LEX-generated code.
- *
- */
-
-#include "a56.h"
-#include "gram.h"
-
-int ldebug = 0;
-#ifdef LDEBUG
-#define RET(val) \
-       {\
-               if(ldebug) {\
-                       printf("[%s]", tok_print(val));\
-                       fflush(stdout);\
-               }\
-               return val;\
-       }
-#else
-#define RET(val) {return val;}
-#endif
-
-extern YYSTYPE yyval;
-
-double atof();
-
-/**************** yylex - returns next token *****************************/
-
-#define MAX_TOK 1024
-char tok[MAX_TOK];
-
-yylex()
-{
-       int ltok = next_tok();
-       int itok;
-
-       switch(ltok) {
-       case EOF:
-               if(yywrap() == 1)
-                       return 0;
-               else
-                       return yylex();
-               break;
-       case SYM:
-               if(itok = is_keyword(tok)) {
-                       RET(itok);
-               } else {
-                       yylval.sval = strsave(tok);
-                       RET(SYM);
-               }
-               break;
-       case CHEX:
-               yylval.n.type = INT;
-               yylval.n.seg = ANY;
-               yylval.n.val.i = a56_strtol(tok, 0, 16);
-               RET(CHEX);
-               break;
-       case CDEC:
-               yylval.n.type= INT;
-               yylval.n.seg = ANY;
-               yylval.n.val.i = atoi(tok);
-               RET(CDEC);
-               break;
-       case FRAC:
-               yylval.n.type = FLT;
-               yylval.n.seg = ANY;
-               yylval.n.val.f = atof(tok);
-               RET(FRAC);
-       case CHAR:
-               yylval.cval = *tok;
-               RET(CHAR);
-       case STRING:
-               yylval.sval = (char *)fixstring(tok);
-               yylval.sval = strsave(yylval.sval);
-               RET(STRING);
-       default:
-               RET(ltok);
-       }
-}
-
-is_keyword(tok)
-char *tok;
-{
-       int kval = kparse(tok);
-       if(kval > 0)
-               return kval;
-
-       return 0;
-}
-
-struct ascii_tab {
-       char *str;
-       int flags;
-} ascii_tab[];
-#define IS_NONE                0x0000
-#define IS_NUM         0x0001
-#define IS_ALPHA       0x0002
-#define IS_HEX         0x0004
-#define IS_WHITE       0x0008
-
-extern FILE *yyin;
-
-int next_tok()
-{
-       char *tp = tok;
-       enum {S_TOP, S_HEXNUM, S_NUM, S_ALNUM, S_CHAR, S_ESC_CHAR, S_COMMENT,
-               S_SQ_STRING, S_DQ_STRING, S_SHL, S_SHR} state = S_TOP;
-       static int unget = 0;
-       BOOL dot_seen = FALSE;
-
-       for(;;) {
-               int c = unget ? unget : lgetc(yyin);
-               int flags;
-               unget = 0;
-               flags = ascii_tab[c & 0x7F].flags;
-               if(tp > tok + MAX_TOK - 2) return LEXBAD;
-               switch(state) {
-               case S_TOP:
-                       if(c == EOF) {
-                               return EOF;
-                       } else if(flags & IS_WHITE) {
-                               /* ignore */ ;
-                       } else if(flags & IS_ALPHA) {
-                               *tp++ = c;
-                               state = S_ALNUM;
-                       } else if((flags & IS_NUM) || c == '.') {
-                               unget = c;
-                               state = S_NUM;
-                       } else {
-                               switch(c) {
-                               case '$': state = S_HEXNUM; break;
-                               case '"': state = S_DQ_STRING; break;
-                               case '\'': state = S_CHAR; break;
-                               case '>': state = S_SHR; break;
-                               case '<': state = S_SHL; break;
-                               case ';': state = S_COMMENT; break;
-                               case '\n': return EOL;
-                               case '@': return EOS;
-                               default: return c;
-                               }
-                       }
-                       break;
-               case S_COMMENT:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return EOL;
-                       } else if(c == '\n') {
-                               return EOL;
-                       }
-                       break;
-               case S_SHR:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return '>';
-                       } else if(c == '>') {
-                               return SHR;
-                       } else {
-                               unget = c;
-                               return '>';
-                       }
-                       break;
-               case S_SHL:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return '<';
-                       } else if(c == '<') {
-                               return SHL;
-                       } else {
-                               unget = c;
-                               return '<';
-                       }
-                       break;
-               case S_HEXNUM:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return CHEX;
-                       } else if(flags & IS_HEX) {
-                               *tp++ = c;
-                               break;
-                       } else {
-                               unget = c;
-                               *tp = '\0';
-                               return CHEX;
-                       }
-                       break;
-               case S_ALNUM:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return SYM;
-                       } else if(c == ':') {
-                               *tp++ = c;
-                               *tp = '\0';
-                               return SYM;
-                               break;
-                       } else if(flags & (IS_ALPHA|IS_NUM)) {
-                               *tp++ = c;
-                               break;
-                       } else {
-                               unget = c;
-                               *tp = '\0';
-                               return SYM;
-                       }
-                       break;
-               case S_NUM:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return dot_seen ? FRAC : CDEC;
-                       } else if((flags & IS_NUM) || (c == '.' && NOT dot_seen)) {
-                               *tp++ = c;
-                               if(c == '.') dot_seen = TRUE;
-                               break;
-                       } else {
-                               unget = c;
-                               *tp = '\0';
-                               return dot_seen ? FRAC : CDEC;
-                       }
-                       break;
-               case S_CHAR:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return CHAR;
-                       } else if(c == '\\') {
-                               state = S_ESC_CHAR;
-                       } else if(c == '\'') {
-                               *tp = '\0';
-                               return CHAR;
-                       } else {
-                               *tp++ = c;
-                               if(tp > tok + 1)
-                                       state = S_SQ_STRING;
-                       }
-                       break;
-               case S_ESC_CHAR:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return CHAR;
-                       }
-                       switch(c) {
-                       case 'b': *tp = '\b'; break;
-                       case 'f': *tp = '\f'; break;
-                       case 'n': *tp = '\n'; break;
-                       case 'r': *tp = '\r'; break;
-                       case 't': *tp = '\t'; break;
-                       case '\\': *tp = '\\'; break;
-                       case '\'':
-                               *tp = '\0';
-                               return CHAR;
-                               break;
-                       default:
-                               *tp++ = c;
-                               state = S_SQ_STRING;
-                               break;
-                       }
-                       break;
-               case S_SQ_STRING:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return STRING;
-                       } else if(c == '\'') {
-                               *tp = '\0';
-                               return STRING;
-                       } else {
-                               *tp++ = c;
-                       }
-                       break;
-               case S_DQ_STRING:
-                       if(c == EOF) {
-                               unget = EOF;
-                               *tp = '\0';
-                               return STRING;
-                       } else if(c == '"') {
-                               *tp = '\0';
-                               return STRING;
-                       } else {
-                               *tp++ = c;
-                       }
-                       break;
-               } /* switch(state) */
-       } /* for(;;) */
-}
-
-struct ascii_tab ascii_tab[] = {
-       {"\\z00",       IS_NONE                                 /* 0x00 */},
-       {"\\z01",       IS_NONE                                 /* 0x01 */},
-       {"\\z02",       IS_NONE                                 /* 0x02 */},
-       {"\\z03",       IS_NONE                                 /* 0x03 */},
-       {"\\z04",       IS_NONE                                 /* 0x04 */},
-       {"\\z05",       IS_NONE                                 /* 0x05 */},
-       {"\\z06",       IS_NONE                                 /* 0x06 */},
-       {"\\z07",       IS_NONE                                 /* 0x07 */},
-       {"\\b",         IS_NONE                                 /* 0x08 */},
-       {"\\t",         IS_NONE|IS_WHITE                /* 0x09 */},
-       {"\\n",         IS_NONE                                 /* 0x0A */},
-       {"\\z0B",       IS_NONE                                 /* 0x0B */},
-       {"\\z0C",       IS_NONE                                 /* 0x0C */},
-       {"\\r",         IS_NONE                                 /* 0x0D */},
-       {"\\z0E",       IS_NONE                                 /* 0x0E */},
-       {"\\z0F",       IS_NONE                                 /* 0x0F */},
-       {"\\z10",       IS_NONE                                 /* 0x10 */},
-       {"\\z11",       IS_NONE                                 /* 0x11 */},
-       {"\\z12",       IS_NONE                                 /* 0x12 */},
-       {"\\z13",       IS_NONE                                 /* 0x13 */},
-       {"\\z14",       IS_NONE                                 /* 0x14 */},
-       {"\\z15",       IS_NONE                                 /* 0x15 */},
-       {"\\z16",       IS_NONE                                 /* 0x16 */},
-       {"\\z17",       IS_NONE                                 /* 0x17 */},
-       {"\\z18",       IS_NONE                                 /* 0x18 */},
-       {"\\z19",       IS_NONE                                 /* 0x19 */},
-       {"\\z1A",       IS_NONE                                 /* 0x1A */},
-       {"\\z1B",       IS_NONE                                 /* 0x1B */},
-       {"\\z1C",       IS_NONE                                 /* 0x1C */},
-       {"\\z1D",       IS_NONE                                 /* 0x1D */},
-       {"\\z1E",       IS_NONE                                 /* 0x1E */},
-       {"\\z1F",       IS_NONE                                 /* 0x1F */},
-       {" ",           IS_NONE|IS_WHITE                /* 0x20 */},
-       {"!",           IS_NONE                                 /* 0x21 */},
-       {"\"",          IS_NONE                                 /* 0x22 */},
-       {"#",           IS_NONE                                 /* 0x23 */},
-       {"$",           IS_NONE                                 /* 0x24 */},
-       {"%",           IS_NONE                                 /* 0x25 */},
-       {"&",           IS_NONE                                 /* 0x26 */},
-       {"'",           IS_NONE                                 /* 0x27 */},
-       {"(",           IS_NONE                                 /* 0x28 */},
-       {")",           IS_NONE                                 /* 0x29 */},
-       {"*",           IS_NONE                                 /* 0x2A */},
-       {"+",           IS_NONE                                 /* 0x2B */},
-       {",",           IS_NONE                                 /* 0x2C */},
-       {"-",           IS_NONE                                 /* 0x2D */},
-       {".",           IS_NONE                                 /* 0x2E */},
-       {"/",           IS_NONE                                 /* 0x2F */},
-       {"0",           IS_NONE|IS_NUM|IS_HEX   /* 0x30 */},
-       {"1",           IS_NONE|IS_NUM|IS_HEX   /* 0x31 */},
-       {"2",           IS_NONE|IS_NUM|IS_HEX   /* 0x32 */},
-       {"3",           IS_NONE|IS_NUM|IS_HEX   /* 0x33 */},
-       {"4",           IS_NONE|IS_NUM|IS_HEX   /* 0x34 */},
-       {"5",           IS_NONE|IS_NUM|IS_HEX   /* 0x35 */},
-       {"6",           IS_NONE|IS_NUM|IS_HEX   /* 0x36 */},
-       {"7",           IS_NONE|IS_NUM|IS_HEX   /* 0x37 */},
-       {"8",           IS_NONE|IS_NUM|IS_HEX   /* 0x38 */},
-       {"9",           IS_NONE|IS_NUM|IS_HEX   /* 0x39 */},
-       {":",           IS_NONE                                 /* 0x3A */},
-       {";",           IS_NONE                                 /* 0x3B */},
-       {"<",           IS_NONE                                 /* 0x3C */},
-       {"=",           IS_NONE                                 /* 0x3D */},
-       {">",           IS_NONE                                 /* 0x3E */},
-       {"?",           IS_NONE                                 /* 0x3F */},
-       {"@",           IS_NONE                                 /* 0x40 */},
-       {"A",           IS_NONE|IS_ALPHA|IS_HEX /* 0x41 */},
-       {"B",           IS_NONE|IS_ALPHA|IS_HEX /* 0x42 */},
-       {"C",           IS_NONE|IS_ALPHA|IS_HEX /* 0x43 */},
-       {"D",           IS_NONE|IS_ALPHA|IS_HEX /* 0x44 */},
-       {"E",           IS_NONE|IS_ALPHA|IS_HEX /* 0x45 */},
-       {"F",           IS_NONE|IS_ALPHA|IS_HEX /* 0x46 */},
-       {"G",           IS_NONE|IS_ALPHA                /* 0x47 */},
-       {"H",           IS_NONE|IS_ALPHA                /* 0x48 */},
-       {"I",           IS_NONE|IS_ALPHA                /* 0x49 */},
-       {"J",           IS_NONE|IS_ALPHA                /* 0x4A */},
-       {"K",           IS_NONE|IS_ALPHA                /* 0x4B */},
-       {"L",           IS_NONE|IS_ALPHA                /* 0x4C */},
-       {"M",           IS_NONE|IS_ALPHA                /* 0x4D */},
-       {"N",           IS_NONE|IS_ALPHA                /* 0x4E */},
-       {"O",           IS_NONE|IS_ALPHA                /* 0x4F */},
-       {"P",           IS_NONE|IS_ALPHA                /* 0x50 */},
-       {"Q",           IS_NONE|IS_ALPHA                /* 0x51 */},
-       {"R",           IS_NONE|IS_ALPHA                /* 0x52 */},
-       {"S",           IS_NONE|IS_ALPHA                /* 0x53 */},
-       {"T",           IS_NONE|IS_ALPHA                /* 0x54 */},
-       {"U",           IS_NONE|IS_ALPHA                /* 0x55 */},
-       {"V",           IS_NONE|IS_ALPHA                /* 0x56 */},
-       {"W",           IS_NONE|IS_ALPHA                /* 0x57 */},
-       {"X",           IS_NONE|IS_ALPHA                /* 0x58 */},
-       {"Y",           IS_NONE|IS_ALPHA                /* 0x59 */},
-       {"Z",           IS_NONE|IS_ALPHA                /* 0x5A */},
-       {"[",           IS_NONE                                 /* 0x5B */},
-       {"\\",          IS_NONE                                 /* 0x5C */},
-       {"]",           IS_NONE                                 /* 0x5D */},
-       {"^",           IS_NONE                                 /* 0x5E */},
-       {"_",           IS_NONE|IS_ALPHA                /* 0x5F */},
-       {"`",           IS_NONE                                 /* 0x60 */},
-       {"a",           IS_NONE|IS_ALPHA|IS_HEX /* 0x61 */},
-       {"b",           IS_NONE|IS_ALPHA|IS_HEX /* 0x62 */},
-       {"c",           IS_NONE|IS_ALPHA|IS_HEX /* 0x63 */},
-       {"d",           IS_NONE|IS_ALPHA|IS_HEX /* 0x64 */},
-       {"e",           IS_NONE|IS_ALPHA|IS_HEX /* 0x65 */},
-       {"f",           IS_NONE|IS_ALPHA|IS_HEX /* 0x66 */},
-       {"g",           IS_NONE|IS_ALPHA                /* 0x67 */},
-       {"h",           IS_NONE|IS_ALPHA                /* 0x68 */},
-       {"i",           IS_NONE|IS_ALPHA                /* 0x69 */},
-       {"j",           IS_NONE|IS_ALPHA                /* 0x6A */},
-       {"k",           IS_NONE|IS_ALPHA                /* 0x6B */},
-       {"l",           IS_NONE|IS_ALPHA                /* 0x6C */},
-       {"m",           IS_NONE|IS_ALPHA                /* 0x6D */},
-       {"n",           IS_NONE|IS_ALPHA                /* 0x6E */},
-       {"o",           IS_NONE|IS_ALPHA                /* 0x6F */},
-       {"p",           IS_NONE|IS_ALPHA                /* 0x70 */},
-       {"q",           IS_NONE|IS_ALPHA                /* 0x71 */},
-       {"r",           IS_NONE|IS_ALPHA                /* 0x72 */},
-       {"s",           IS_NONE|IS_ALPHA                /* 0x73 */},
-       {"t",           IS_NONE|IS_ALPHA                /* 0x74 */},
-       {"u",           IS_NONE|IS_ALPHA                /* 0x75 */},
-       {"v",           IS_NONE|IS_ALPHA                /* 0x76 */},
-       {"w",           IS_NONE|IS_ALPHA                /* 0x77 */},
-       {"x",           IS_NONE|IS_ALPHA                /* 0x78 */},
-       {"y",           IS_NONE|IS_ALPHA                /* 0x79 */},
-       {"z",           IS_NONE|IS_ALPHA                /* 0x7A */},
-       {"{",           IS_NONE                                 /* 0x7B */},
-       {"|",           IS_NONE                                 /* 0x7C */},
-       {"}",           IS_NONE                                 /* 0x7D */},
-       {"~",           IS_NONE                                 /* 0x7E */},
-       {"\\z7F",       IS_NONE                                 /* 0x7F */},
-};
-
-
-/**************** lgetc - returns next character *************************/
-
-#define INLINE 1024
-
-char line_buf[INLINE];
-char *cur_line = line_buf;             /* points to current line buffer */
-char *clp = NULL;                              /* where we're at in cur_line */
-
-lgetc(fp)
-FILE *fp;
-{
-       int c;
-
-       if(clp == NULL) {
-               if(fgets(cur_line, INLINE, fp) == NULL) {
-                       c = EOF;
-               } else {
-                       clp = cur_line;
-                       c = *clp++;
-               }
-       } else {
-               c = *clp++;
-       }
-
-       switch(c) {
-       case EOF:
-               /* at EOF: all done */
-               if(ldebug)
-                       printf("<eof>\n");
-               return EOF;
-               break;
-       case '\0':
-               c = '\n';
-       case '\n':
-               clp = NULL;
-               break;
-       default:
-               break;
-       }
-
-       if(ldebug)
-               printf(c < ' ' ? "<\\z%02X>%s" : "<%c>", c, c == '\n' ? "\n" : "");
-
-       return c;
-}
diff --git a/main.c b/main.c
deleted file mode 100644 (file)
index 2d6b759..0000000
--- a/main.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*******************************************************
- *
- *  a56 - a DSP56001 assembler
- *
- *  Written by Quinn C. Jensen
- *  July 1990
- *
- *******************************************************\
-
-/*
- * Copyright (C) 2008 Robert Millan <rmh@aybabtu.com>
- * Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
- * Copyright (C) 2014 Arthur Marble <arthur@info9.net>
- *
- * This file 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 3 of the License,
- * 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, see
- * <http://www.gnu.org/licenses/>.
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * Copyright (C) 1990-1994 Quinn C. Jensen
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.  The author makes no representations
- * about the suitability of this software for any purpose.  It is
- * provided "as is" without express or implied warranty.
- *
- */
-static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
-
-/*
- *  main.c - The "main" code for the assembler.
- *
- */
-
-#include "a56.h"
-
-#define MAX 1024
-
-int pass;
-int error, warning;
-extern unsigned int pc;
-extern int seg;
-BOOL binary_listing = FALSE;
-BOOL list_includes = FALSE;
-FILE *obj = NULL;
-extern BOOL list_on;
-BOOL list_on_next = TRUE;
-
-main(argc,argv)
-int argc;
-char *argv[];
-{
-       int i;
-       extern char *optarg;
-       extern int optind;
-       int c;
-       char *output_file = "a56.out";
-       char *input_file;
-       char *usage = "usage: a56  [-b]  [-l]  [-d]  [-o output-file]  input-file\n";
-
-       while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) {
-               case 'b':
-                       binary_listing++;
-                       break;
-               case 'l':
-                       list_includes++;
-                       break;
-               case 'd':
-                       ldebug++;
-                       break;
-               case 'o':
-                       output_file = optarg;
-                       break;
-               case '?':
-               default:
-                       fatal(usage);
-       }
-       input_file = argv[optind++];
-       if(input_file == NULL) fatal(usage);
-       obj = open_write(output_file);
-
-       pc = 0;
-       seg = 0;
-       pass = 1;
-       reset_psects();
-       include(input_file);
-
-       pc = 0;
-       seg = 0;
-       pass = 2;
-       reset_psects();
-       include(input_file);
-
-       psect_summary();
-       dump_symtab();
-       fclose(obj);
-       printf("errors=%d\n", error);
-       printf("warnings=%d\n", warning);
-       return error ? 1 : 0;
-}
-
-struct inc inc[MAX_NEST];
-int inc_p = 0;
-FILE *yyin;
-
-include(file)
-char *file;
-{
-       FILE *fp = open_read(file);
-
-       inc_p++;
-       if(inc_p >= MAX_NEST)
-               fatal("%s: include nesting too deep\n", file);
-
-       inc[inc_p].file = file;
-       inc[inc_p].fp = fp;
-       inc[inc_p].line = 1;
-
-       list_on_next = TRUE;
-       if(inc_p > 1 && NOT list_includes)
-               list_on_next = FALSE;
-
-       yyin = inc[inc_p].fp;
-       if(inc_p == 1)
-#ifdef FLEX
-       {
-               static int started = 0;
-               if(started)
-                       yyrestart(yyin);
-               else
-                       started = 1;
-               yyparse();
-       }
-#else
-               yyparse();
-#endif
-}
-
-yywrap()
-{
-       fclose(inc[inc_p].fp);
-       inc_p--;
-       list_on = list_on_next = TRUE;
-       if(inc_p > 1)
-               list_on = list_on_next = FALSE;
-       if(inc_p) {
-               yyin = inc[inc_p].fp;
-               return 0;
-       } else {
-               return 1;
-       }
-}
-
-struct n
-sym_ref(sym)           /* return symbol value or UNDEF if not defined yet */
-char *sym;
-{
-       struct sym *sp, *find_sym();
-       struct n result;
-
-       result.type = UNDEF;
-
-       sp = find_sym(sym);
-       if(NOT sp) {
-               if(pass == 2) {
-                       yyerror("%s: undefined symbol", sym);
-               }                  
-               return result;
-       }
-
-       return sp->n;
-}
-
-#define HASHSIZE 128
-
-#define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE)
-
-struct sym *symtab[HASHSIZE];
-
-sym_def(sym, type, seg, i, f)
-char *sym;
-int type;
-int seg;
-int i;
-double f;
-{
-       struct sym *sp, **stop, *find_sym();
-
-       if(pass == 1) {
-               if(find_sym(sym)) {
-                       pass = 2;                               /* what a kludge */
-                       yyerror("%s: multiply defined symbol", sym);
-                       pass = 1;
-                       return 1;
-               }
-               stop = &symtab[HASH(sym)];
-               sp = NEW(struct sym);
-               sp->next = *stop;
-               *stop = sp;
-               sp->name = strsave(sym);
-               sp->n.type = type;
-               sp->n.seg = seg;
-               if(type == INT)
-                       sp->n.val.i = i & 0xFFFFFF;
-               else
-                       sp->n.val.f = f;
-       } else {
-               sp = find_sym(sym);
-               if(NOT sp)
-                       fatal("internal error 304\n");
-               if(sp->n.type != type ||
-                       type == INT && sp->n.val.i != (i & 0xFFFFFF) ||
-                       type == FLT && sp->n.val.f != f)
-                       yyerror("%s: assembler phase error", sym);
-       }               
-}
-
-struct sym *find_sym(sym)
-char *sym;
-{
-       struct sym *sp, **stop;
-
-       stop = &symtab[HASH(sym)];
-       for(sp = *stop; sp; sp = sp->next)
-               if(strcmp(sp->name, sym) == 0)
-                       return sp;
-               
-       return NULL;
-}
-
-extern char segs[];
-dump_symtab()
-{
-       struct sym *sp, **stop;
-       int i;
-
-       printf("\n\
-Symbol Table\n\
--------------------------------------\n");
-/*
-SSSSSSSSSSSSSSSS S XXXXXX
-SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD
-*/
-
-       for(i = 0, stop = symtab; i < HASHSIZE; i++, stop++) {
-               for(sp = *stop; sp; sp = sp->next) {
-                       if(sp->n.type == INT) {
-                               printf("%16s %c %06X\n", sp->name, segs[sp->n.seg], sp->n.val.i);
-                               fprintf(obj, "I %06X %s\n", sp->n.val.i, sp->name);
-                       } else {
-                               printf("%16s %c %.10f\n", sp->name, segs[sp->n.seg], sp->n.val.f);
-                               fprintf(obj, "F %.10f %s\n", sp->n.val.f, sp->name);
-                       }
-               }
-       }   
-}
-
-char *printcode(word)
-int word;
-{
-       static char list[MAX], *lp;
-       int i;
-
-       word &= 0xFFFFFF;
-
-       if(binary_listing) {
-               sprintf(list, "%06X<", word);
-               for(i = 0, lp = &list[7]; i < 24; i++, lp++) {
-                       *lp = word & 1 << 23 - i ? '1' : '0';
-                       if(i && i % 4 == 3)
-                               *++lp = i % 8 == 7 ? ' ' : ',';
-               }
-               lp[-1] = '>';
-               lp[0] = '\0';
-       } else {
-               sprintf(list, "%06X", word);
-       }
-       return list;
-}
-
-char *spacespace[2] = {
-/*P:XXXX_XXXXXX_*/
- "              ",
-/*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/
- "                                             "};
-char *spaces(n)
-int n;
-{
-       return spacespace[binary_listing ? 1 : 0] + n;
-}
-
-extern char segs[];
-
-gencode(seg, pc, word)
-int seg, pc, word;
-{
-       fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF);
-}
-
-char fixbuf[1024];
-
-char *fixstring(s)
-char *s;
-{
-       char *bp = fixbuf;
-       int ival;
-
-       while(*s) {
-               switch (*s) {
-                       case '\'':
-                       case '\"':
-                               s++;
-                               break;
-                       case '\\':
-                               switch (*++s) {
-                                       case 'b': *bp++ = '\b'; break;
-                                       case 'r': *bp++ = '\r'; break;
-                                       case 'f': *bp++ = '\f'; break;
-                                       case 'n': *bp++ = '\n'; break;
-                                       case 't': *bp++ = '\t'; break;
-                                       case '\\': *bp++ = '\\'; break;
-                                       case '0':
-                                               ival = 0;
-                                               while(*s >= '0' && *s <= '9') {
-                                                       ival <<= 3;
-                                                       ival += *s++ - '0';
-                                               }
-                                               *bp++ = ival;
-                                               break;
-                               }
-                               break;
-                       default:
-                               *bp++ = *s++;
-                               break;
-               }
-       }
-       *bp = '\0';
-       return fixbuf;
-}
-
-#define ONE 0x4000000
-
-makefrac(s)
-char *s;
-{
-       int frac = 0, div = 1;
-       int scale = 1;
-
-       while(*s) {
-               switch(*s) {
-                       case '-':
-                               scale = -1;
-                               break;
-                       case '.':
-                               div = 10;
-                               break;
-                       default:
-                               frac += (*s - '0') * scale * ONE / div;
-                               div *= 10;
-                               break;
-               }
-               s++;
-       }
-
-       return frac + scale * 4 >> 3 & 0xFFFFFF;
-}
-
-/***************** psect stuff ************************/
-
-struct psect *ptop = NULL, *cur_psect = NULL;
-
-reset_psects()
-{
-       struct psect *pp;
-
-       for(pp = ptop; pp; pp = pp->next) {
-               pp->pc = pp->bottom;
-       }
-
-       set_psect(NULL);
-}
-
-psect_summary()
-{
-       printf("\nSummary of psect usage\n\n");
-
-       printf("\
-                 section seg base last top      used       avail    total\n\
--------------------------------------------------------------------------\n");
-/*
-SSSSSSSSSSSSSSSSSSSSSSSS  X  FFFF FFFF FFFF 99999 100%  99999 100%  99999
-*/
-
-       summarize(ptop);        /* do it recursively to place back in order */
-       printf("\n");
-}
-
-summarize(pp)
-struct psect *pp;
-{
-       int used, avail, of;
-
-       if(pp == NULL)
-               return 1;
-
-       used = pp->pc - pp->bottom;
-       avail = pp->top - pp->pc;
-       of = pp->top - pp->bottom;
-
-       summarize(pp->next);
-
-       printf("%24.24s  %c  %04X %04X %04X %5d %3d%%  %5d %3d%%  %5d\n",
-               pp->name, segs[pp->seg], pp->bottom, pp->pc, pp->top,
-               used, of ? used * 100 / of : 0, avail, of ? avail * 100 / of : 0,
-               of);
-}
-
-struct psect *find_psect(name)
-char *name;
-{
-       struct psect *pp;
-
-       for(pp = ptop; pp; pp = pp->next)
-               if(strcmp(pp->name, name) == 0)
-                       return pp;
-
-       return NULL;
-}
-
-set_psect(pp)
-struct psect *pp;
-{
-       cur_psect = pp;
-}
-
-check_psect(seg, pc)
-int seg;
-unsigned int pc;
-{
-       if(cur_psect) {
-               if(seg == cur_psect->seg && pc >= cur_psect->bottom && 
-                       pc <= cur_psect->top) {
-                       cur_psect->pc = pc;
-                       return TRUE;
-               } else {
-                       return FALSE;
-               }
-       } else {
-               return TRUE;
-       }
-}
-
-struct psect *new_psect(name, seg, bottom, top)
-char *name;
-int seg;
-unsigned int bottom, top;
-{
-       struct psect *pp = find_psect(name);
-
-       if(NOT pp) {
-               pp = (struct psect *)alloc(sizeof *pp);
-               pp->next = ptop;
-               ptop = pp;
-               pp->name = strsave(name);
-               pp->seg = seg;
-               pp->pc = bottom;
-       }
-       pp->bottom = bottom;
-       pp->top = top;
-
-       return pp;
-}
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..b2294b3
--- /dev/null
@@ -0,0 +1,146 @@
+#######################################################
+#
+#  a56 - a DSP56001 assembler
+#
+#  Written by Quinn C. Jensen
+#  July 1990
+#
+#######################################################
+
+# Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
+#
+# This file 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 3 of the License,
+# 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, see
+# <http://www.gnu.org/licenses/>.
+#
+# This file incorporates work covered by the following copyright and
+# permission notice:
+#
+# Copyright (C) 1990-1998 Quinn C. Jensen
+#
+# Permission to use, copy, modify, distribute, and sell this
+# software and its documentation for any purpose is hereby granted
+# without fee, provided that the above copyright notice appear in all
+# copies and that both that copyright notice and this permission
+# notice appear in supporting documentation.  The author makes no
+# representations about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied
+# warranty.
+
+# environment definitions
+# uncomment the ones you like
+
+# generic unix
+CC = cc
+HOSTCC = cc
+YACC = yacc
+CCDEFS = -DLDEBUG
+MV = mv
+YTABC = y.tab.c
+YTABH = y.tab.h
+POSTPROCESS = echo
+
+# gcc & bison
+#CC = gcc
+#HOSTCC = gcc
+#YACC = bison -y
+#CCDEFS =
+#MV = mv
+#YTABC = y.tab.c
+#YTABH = y.tab.h
+#POSTPROCESS = echo
+
+# Delorie's DOS gcc (from ftp://omnigate.clarkson.edu/pub/msdos/djgpp)
+#CC = gcc
+#HOSTCC = gcc
+#YACC = bison -y
+#CCDEFS =
+#MV = ren
+#YTABC = y_tab.c
+#YTABH = y_tab.h
+#POSTPROCESS = coff2exe
+
+# gcc cross-compile to go32 environment
+#CC = i386-go32-gcc
+#HOSTCC = cc
+#YACC = yacc
+#CCDEFS =
+#MV = mv
+#YTABC = y.tab.c
+#YTABH = y.tab.h
+#POSTPROCESS = echo
+
+#######################################################
+
+# -O or -g
+#DEBUG = -O -Olimit 3000
+DEBUG = -O
+
+SRCS = main.c a56.y lex.c subs.c getopt.c kparse.key
+OBJS = main.o gram.o lex.o toktab.o subs.o getopt.o kparse.o
+
+DEFINES = $(CCDEFS)
+#DEFINES = -DYYDEBUG -DLDEBUG $(CCDEFS)
+
+CFLAGS = $(DEBUG) $(DEFINES) $(CPPFLAGS) $(LDFLAGS)
+
+all:   keybld a56 toomf
+
+a56:   $(OBJS)
+       $(CC) $(CFLAGS) -o a56 $(OBJS) -lm
+       @$(POSTPROCESS) a56
+
+keybld:        keybld.o ksubs.o
+       $(HOSTCC) $(CFLAGS) -o keybld keybld.o ksubs.o
+       @$(POSTPROCESS) keybld
+
+keybld.o:      keybld.c
+       $(HOSTCC) $(CFLAGS) -c keybld.c
+
+ksubs.o:       subs.c
+       $(HOSTCC) $(CFLAGS) -c subs.c
+       $(MV) subs.o ksubs.o
+
+lex.o: lex.c gram.h
+
+kparse.c:      a56.key keybld
+       ./keybld < a56.key > kparse.c
+
+gram.c gram.h: a56.y
+       @echo "[expect 2 shift/reduce conflicts here]"
+       $(YACC) -d a56.y
+       $(MV) $(YTABC) gram.c
+       $(MV) $(YTABH) gram.h
+
+toktab.c:      gram.h
+       awk -f tok.awk < gram.h > toktab.c
+
+y.output:      a56.y
+       $(YACC) -v a56.y
+
+toomf: toomf.o
+       $(CC) -o toomf $(CFLAGS) toomf.o
+       @$(POSTPROCESS) toomf
+
+torom: torom.o subs.o
+       $(CC) -o torom $(CFLAGS) torom.o subs.o
+
+tape:  toktab.c
+       csh -c 'tar cvbf 1 - `cat files` | gzip > a56.tar.gz'
+
+main.o gram.o lex.o:   a56.h
+
+clean: ; rm -f a56 toomf y.output *.o *.out tmp *.bak a56.tar.gz keybld
+
+spotless:      clean
+       rm -f gram.c lexyy.c gram.h toktab.c kparse.c
diff --git a/src/a56.1 b/src/a56.1
new file mode 100644 (file)
index 0000000..2ad66ba
--- /dev/null
+++ b/src/a56.1
@@ -0,0 +1,39 @@
+.\"
+.\" Copyright (C) 1990-1998 Quinn C. Jensen
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software
+.\" and its documentation for any purpose is hereby granted without fee,
+.\" provided that the above copyright notice appear in all copies and
+.\" that both that copyright notice and this permission notice appear
+.\" in supporting documentation.  The author makes no representations
+.\" about the suitability of this software for any purpose.  It is
+.\" provided "as is" without express or implied warranty.
+.\"
+.\"
+.TH A56 1 "April 28, 2010"
+.SH NAME
+A56 \- Motorola DSP56001 assembler
+.SH SYNOPSIS
+.B a56
+[\fI\-b\fR] [\fI\-l\fR] [\fI\-o output\-file\fR] file [...]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B a56
+command.
+.PP
+a56 is an assembler for the Motorola DSP56001 family of microcontrollers. 
+It is capable of compiling the firmware used in Linux dsp56k.c driver.
+.SH OPTIONS
+.TP
+\fB\-b\fR
+Adds binary to the listing.
+.TP
+\fB\-l\fR
+Causes included files to be listed.
+.TP
+\fB\-o\fR
+Directs the output to the specified file rather than the default.
+.SH AUTHORS
+Copyright (C) 1990-1998 Quinn C. Jensen.
+This manual page was written by Denis Briand <denis@narcan.fr>,
+for the Debian GNU/Linux system (but may be used by others).
diff --git a/src/a56.h b/src/a56.h
new file mode 100644 (file)
index 0000000..3415001
--- /dev/null
+++ b/src/a56.h
@@ -0,0 +1,119 @@
+/*******************************************************
+ *
+ *  a56 - a DSP56001 assembler
+ *
+ *  Written by Quinn C. Jensen
+ *  July 1990
+ *
+ *******************************************************\
+
+/*
+ * Copyright (C) 2008 Robert Millan <rmh@aybabtu.com>
+ * Copyright (C) 2012 Thorsten Alteholz <debian@alteholz.de>
+ *
+ * This file 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 3 of the License,
+ * 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (C) 1990-1994 Quinn C. Jensen
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  The author makes no representations
+ * about the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ *
+ */
+
+/*
+ *  a56.h - general definitions
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#define NOT !
+typedef int BOOL;
+#endif
+
+struct sym {
+       char *name;
+       struct n {
+               short type;
+#define UNDEF -1
+#define INT 0
+#define FLT 1
+               short seg;
+#define NONE 0
+#define PROG 1
+#define XDATA 2
+#define YDATA 3
+#define LDATA 4
+#define ANY 5
+               union val {
+                       int i;
+                       double f;
+               } val;
+       } n;
+       struct sym *next;
+} *find_sym();
+
+extern int pass;
+
+#define NEW(object) ((object *)alloc(sizeof(object)))
+
+#define MAX_NEST 20            /* maximum include file nesting */
+
+struct inc {
+       char *file;
+       FILE *fp;
+       int line;
+};
+extern struct inc inc[];
+extern int inc_p;
+#define curfile inc[inc_p].file
+#define curline inc[inc_p].line
+
+extern int ldebug;
+
+struct psect {
+       char *name;
+       int seg;
+       unsigned int pc, bottom, top;
+       struct psect *next;
+} *find_psect(), *new_psect();
+
+FILE *open_read(), *open_write(), *open_append();
+
+       /* save string s somewhere */
+#define strsave(s) ((s) != NULL ? \
+               (char *)strcpy((char *)malloc(strlen(s)+1),(s)) : NULL)
+
+       /* after a call to fgets(), remove the newline character */
+#define rmcr(s) {if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0';};
+
+#define ASSERT(expr, str) \
+               if(expr) fprintf(stderr, "ASSERT: %s: line %d: %s\n", __FILE__, __LINE__, str);
+
+char *alloc (int size);
+char *fixstring (char *s);
diff --git a/src/a56.key b/src/a56.key
new file mode 100644 (file)
index 0000000..ae7c52b
--- /dev/null
@@ -0,0 +1,193 @@
+.code  #include "a56.h"
+.code  #include "gram.h"
+X:             {return XMEM;}
+Y:             {return YMEM;}
+L:             {return LMEM;}
+P:             {return PMEM;}
+A10            {return A10;}
+A              {return AAAA;}
+B10            {return B10;}
+B              {return BBBB;}
+AB             {return AABB;}
+BA             {return BBAA;}
+X              {return XXXX;}
+Y              {return YYYY;}
+SR             {return SR;}
+MR             {return MR;}
+CCR            {return CCR;}
+OMR            {return OMR;}
+SP             {return SP;}
+SSH            {return SSH;}
+SSL            {return SSL;}
+LA             {return LA;}
+LC             {return LC;}
+A0             {yylval.ival = 0; return AREG;}
+A1             {yylval.ival = 1; return AREG;}
+A2             {yylval.ival = 2; return AREG;}
+B0             {yylval.ival = 0; return BREG;}
+B1             {yylval.ival = 1; return BREG;}
+B2             {yylval.ival = 2; return BREG;}
+M0             {yylval.ival = 0; return MREG;}
+M1             {yylval.ival = 1; return MREG;}
+M2             {yylval.ival = 2; return MREG;}
+M3             {yylval.ival = 3; return MREG;}
+M4             {yylval.ival = 4; return MREG;}
+M5             {yylval.ival = 5; return MREG;}
+M6             {yylval.ival = 6; return MREG;}
+M7             {yylval.ival = 7; return MREG;}
+N0             {yylval.ival = 0; return NREG;}
+N1             {yylval.ival = 1; return NREG;}
+N2             {yylval.ival = 2; return NREG;}
+N3             {yylval.ival = 3; return NREG;}
+N4             {yylval.ival = 4; return NREG;}
+N5             {yylval.ival = 5; return NREG;}
+N6             {yylval.ival = 6; return NREG;}
+N7             {yylval.ival = 7; return NREG;}
+R0             {yylval.ival = 0; return RREG;}
+R1             {yylval.ival = 1; return RREG;}
+R2             {yylval.ival = 2; return RREG;}
+R3             {yylval.ival = 3; return RREG;}
+R4             {yylval.ival = 4; return RREG;}
+R5             {yylval.ival = 5; return RREG;}
+R6             {yylval.ival = 6; return RREG;}
+R7             {yylval.ival = 7; return RREG;}
+X0             {yylval.ival = 0; return XREG;}
+X1             {yylval.ival = 1; return XREG;}
+Y0             {yylval.ival = 0; return YREG;}
+Y1             {yylval.ival = 1; return YREG;}
+ABS            {return OP_ABS;}
+ADC            {return OP_ADC;}
+ADD            {return OP_ADD;}
+ADDL   {return OP_ADDL;}
+ADDR   {return OP_ADDR;}
+ASL            {return OP_ASL;}
+ASR            {return OP_ASR;}
+CLR            {return OP_CLR;}
+CMP            {return OP_CMP;}
+CMPM   {return OP_CMPM;}
+DIV            {return OP_DIV;}
+MAC            {return OP_MAC;}
+MACR   {return OP_MACR;}
+MPY            {return OP_MPY;}
+MPYR   {return OP_MPYR;}
+NEG            {return OP_NEG;}
+NORM   {return OP_NORM;}
+RND            {return OP_RND;}
+SBC            {return OP_SBC;}
+SUB            {return OP_SUB;}
+SUBL   {return OP_SUBL;}
+SUBR   {return OP_SUBR;}
+TCC            {yylval.cond = 0x0; return OP_TCC;}
+THS            {yylval.cond = 0x0; return OP_TCC;}
+TGE            {yylval.cond = 0x1; return OP_TCC;}
+TNE            {yylval.cond = 0x2; return OP_TCC;}
+TPL            {yylval.cond = 0x3; return OP_TCC;}
+TNN            {yylval.cond = 0x4; return OP_TCC;}
+TEC            {yylval.cond = 0x5; return OP_TCC;}
+TLC            {yylval.cond = 0x6; return OP_TCC;}
+TGT            {yylval.cond = 0x7; return OP_TCC;}
+TCS            {yylval.cond = 0x8; return OP_TCC;}
+TLO            {yylval.cond = 0x8; return OP_TCC;}
+TLT            {yylval.cond = 0x9; return OP_TCC;}
+TEQ            {yylval.cond = 0xA; return OP_TCC;}
+TMI            {yylval.cond = 0xB; return OP_TCC;}
+TNR            {yylval.cond = 0xC; return OP_TCC;}
+TES            {yylval.cond = 0xD; return OP_TCC;}
+TLS            {yylval.cond = 0xE; return OP_TCC;}
+TLE            {yylval.cond = 0xF; return OP_TCC;}
+TFR            {return OP_TFR;}
+TST            {return OP_TST;}
+AND            {return OP_AND;}
+ANDI   {return OP_ANDI;}
+EOR            {return OP_EOR;}
+LSL            {return OP_LSL;}
+LSR            {return OP_LSR;}
+NOT            {return OP_NOT;}
+OR             {return OP_OR;}
+ORI            {return OP_ORI;}
+ROL            {return OP_ROL;}
+ROR            {return OP_ROR;}
+BCLR   {return OP_BCLR;}
+BSET   {return OP_BSET;}
+BCHG   {return OP_BCHG;}
+BTST   {return OP_BTST;}
+DO             {return OP_DO;}
+ENDDO  {return OP_ENDDO;}
+LUA            {return OP_LUA;}
+MOVE   {return OP_MOVE;}
+MOVEC  {return OP_MOVEC;}
+MOVEM  {return OP_MOVEM;}
+MOVEP  {return OP_MOVEP;}
+INCLUDE        {return OP_INCLUDE;}
+ILLEGAL        {return OP_ILLEGAL;}
+JCC            {yylval.cond = 0x0; return OP_JCC;}
+JHS            {yylval.cond = 0x0; return OP_JCC;}
+JGE            {yylval.cond = 0x1; return OP_JCC;}
+JNE            {yylval.cond = 0x2; return OP_JCC;}
+JPL            {yylval.cond = 0x3; return OP_JCC;}
+JNN            {yylval.cond = 0x4; return OP_JCC;}
+JEC            {yylval.cond = 0x5; return OP_JCC;}
+JLC            {yylval.cond = 0x6; return OP_JCC;}
+JGT            {yylval.cond = 0x7; return OP_JCC;}
+JCS            {yylval.cond = 0x8; return OP_JCC;}
+JLO            {yylval.cond = 0x8; return OP_JCC;}
+JLT            {yylval.cond = 0x9; return OP_JCC;}
+JEQ            {yylval.cond = 0xA; return OP_JCC;}
+JMI            {yylval.cond = 0xB; return OP_JCC;}
+JNR            {yylval.cond = 0xC; return OP_JCC;}
+JES            {yylval.cond = 0xD; return OP_JCC;}
+JLS            {yylval.cond = 0xE; return OP_JCC;}
+JLE            {yylval.cond = 0xF; return OP_JCC;}
+JMP            {return OP_JMP;}
+JCLR   {return OP_JCLR;}
+JSET   {return OP_JSET;}
+JSCC   {yylval.cond = 0x0; return OP_JSCC;}
+JSHS   {yylval.cond = 0x0; return OP_JSCC;}
+JSGE   {yylval.cond = 0x1; return OP_JSCC;}
+JSNE   {yylval.cond = 0x2; return OP_JSCC;}
+JSPL   {yylval.cond = 0x3; return OP_JSCC;}
+JSNN   {yylval.cond = 0x4; return OP_JSCC;}
+JSEC   {yylval.cond = 0x5; return OP_JSCC;}
+JSLC   {yylval.cond = 0x6; return OP_JSCC;}
+JSGT   {yylval.cond = 0x7; return OP_JSCC;}
+JSCS   {yylval.cond = 0x8; return OP_JSCC;}
+JSLO   {yylval.cond = 0x8; return OP_JSCC;}
+JSLT   {yylval.cond = 0x9; return OP_JSCC;}
+JSEQ   {yylval.cond = 0xA; return OP_JSCC;}
+JSMI   {yylval.cond = 0xB; return OP_JSCC;}
+JSNR   {yylval.cond = 0xC; return OP_JSCC;}
+JSES   {yylval.cond = 0xD; return OP_JSCC;}
+JSLS   {yylval.cond = 0xE; return OP_JSCC;}
+JSLE   {yylval.cond = 0xF; return OP_JSCC;}
+JSR            {return OP_JSR;}
+JSCLR  {return OP_JSCLR;}
+JSSET  {return OP_JSSET;}
+NOP            {return OP_NOP;}
+REP            {return OP_REP;}
+RESET  {return OP_RESET;}
+RTI            {return OP_RTI;}
+RTS            {return OP_RTS;}
+STOP   {return OP_STOP;}
+SWI            {return OP_SWI;}
+WAIT   {return OP_WAIT;}
+EQU            {return OP_EQU;}
+ORG            {return OP_ORG;}
+DC             {return OP_DC;}
+DS             {return OP_DS;}
+DSM            {return OP_DSM;}
+INT            {return OP_INT;}
+END            {return OP_END;}
+PAGE   {return OP_PAGE;}
+PSECT  {return OP_PSECT;}
+ALIGN  {return OP_ALIGN;}
+PI             {return OP_PI;}
+SIN            {return OP_SIN;}
+COS            {return OP_COS;}
+TAN            {return OP_TAN;}
+ATAN   {return OP_ATAN;}
+ASIN   {return OP_ASIN;}
+ACOS   {return OP_ACOS;}
+EXP            {return OP_EXP;}
+LN             {return OP_LN;}
+LOG            {return OP_LOG;}
+POW            {return OP_POW;}
diff --git a/src/a56.y b/src/a56.y
new file mode 100644 (file)
index 0000000..9c3399b
--- /dev/null
+++ b/src/a56.y
@@ -0,0 +1,2114 @@
+%{
+/*******************************************************
+ *
+ *  a56 - a DSP56001 assembler
+ *
+ *  Written by Quinn C. Jensen
+ *  July 1990
+ *
+ *******************************************************/
+
+/*
+ * Copyright (C) 1990-1994 Quinn C. Jensen
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  The author makes no representations
+ * about the suitability of this software for any purpose.  It is
+ * provided "as is" without express or implied warranty.
+ *
+ */
+
+/*
+ *  a56.y - The YACC grammar for the assembler.
+ *
+ *  Note:  This module requires a "BIG" version of YACC.  I had to
+ *  recompile YACC in the largest mode available.
+ *
+ *  Other notes:
+ *
+ *  MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure
+ *  out which form to use.
+ *
+ */
+
+#include "a56.h"
+#include <math.h>
+
+unsigned int w0, w1;                   /* workspace for the actual generated code */
+BOOL uses_w1;                                  /* says whether w1 is alive */
+unsigned int pc;                               /* current program counter */
+int seg;                                               /* current segment P: X: Y: or L: */
+int expr_seg;                                  /* segment of current expression */
+
+int just_rep = 0;                              /* keeps track of REP instruction */
+int hot_rreg = -1;                             /* rreg loaded by prev inst. or -1 */
+int hot_nreg = -1;                             /* nreg loaded by prev inst. or -1 */
+int hot_mreg = -1;                             /* mreg loaded by prev inst. or -1 */
+int prev_hot_rreg = -1;                        /* rreg loaded by prev inst. or -1 */
+int prev_hot_nreg = -1;                        /* nreg loaded by prev inst. or -1 */
+int prev_hot_mreg = -1;                        /* mreg loaded by prev inst. or -1 */
+
+int substatement = 0;                  /* in a substatement */
+BOOL long_symbolic_expr = FALSE; /* a parser flag */
+char *new_include = NULL;              /* file to be included */
+
+/* listing stuff */
+
+char segs[] = "uPXYL*";
+extern BOOL list_on_next;              /* listing to turn on or off */
+BOOL list_on;                                  /* listing on at the moment */
+extern char *cur_line;                 /* points to line being lex'd */
+char list_buf[1024 + 80];              /* listing buffer */
+char list_buf2[1024 + 80];             /* listing buffer for two-line code */
+BOOL uses_buf2 = FALSE;                        /* list_buf2 is alive */
+BOOL list_print_line = FALSE;  /* whether or not to print line in listing */
+char *spaces(), *luntab();
+
+struct n binary_op();
+struct n unary_op();
+struct n sym_ref();
+
+#define R_R6                           0x0001
+#define R_R5                           0x0002
+#define R_R4                           0x0004
+#define R_DATA_ALU_ACCUM       0x0008
+#define R_CTL_REG                      0x0010
+#define R_FUNKY_CTL_REG                0x0020
+#define R_SDX                          0x0040
+#define R_SDY                          0x0080
+#define R_LSD                          0x0100
+#define R_AB                           0x0200
+#define R_XREG                         0x0400
+#define R_YREG                         0x0800
+/* registers to which short immediate move is an unsigned int */
+#define R_UINT                         0x1000
+/* registers to which short immediate move is an signed frac */
+#define R_SFRAC                                0x2000
+%}
+
+%union {
+       int ival;                       /* integer value */
+       struct n n;                     /* just like in struct sym */
+       double dval;            /* floating point value */
+       char *sval;                     /* string */
+       int cval;                       /* character */
+       char cond;                      /* condition */
+       struct regs {
+               int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg;
+               int sdx, sdy, lsd, ab, xreg, yreg;
+               int flags;
+       } regs;
+       struct ea {
+               int mode;
+               int ext;
+               int pp;
+       } ea;
+}
+
+%token <n> CHEX CDEC FRAC 
+%token <ival> AREG BREG MREG NREG RREG XREG YREG
+%token <ival> OP OPA OPP
+%token <cond> OP_JCC OP_JSCC OP_TCC
+%token <sval> SYM
+%token <sval> STRING
+%token <cval> CHAR
+%token XMEM
+%token YMEM
+%token LMEM
+%token PMEM
+%token AAAA
+%token A10
+%token BBBB
+%token B10
+%token AABB
+%token BBAA
+%token XXXX
+%token YYYY
+%token SR
+%token MR
+%token CCR
+%token OMR
+%token SP
+%token SSH
+%token SSL
+%token LA
+%token LC
+%token EOL
+%token EOS
+%token LEXBAD
+
+%token OP_ABS
+%token OP_ADC
+%token OP_ADD
+%token OP_ADDL
+%token OP_ADDR
+%token OP_ASL
+%token OP_ASR
+%token OP_CLR
+%token OP_CMP
+%token OP_CMPM
+%token OP_DIV
+%token OP_MAC
+%token OP_MACR
+%token OP_MPY
+%token OP_MPYR
+%token OP_NEG
+%token OP_NORM
+%token OP_RND
+%token OP_SBC
+%token OP_SUB
+%token OP_SUBL
+%token OP_SUBR
+%token OP_TFR
+%token OP_TST
+%token OP_AND
+%token OP_ANDI
+%token OP_EOR
+%token OP_LSL
+%token OP_LSR
+%token OP_NOT
+%token OP_OR
+%token OP_ORI
+%token OP_ROL
+%token OP_ROR
+%token OP_BCLR
+%token OP_BSET
+%token OP_BCHG
+%token OP_BTST
+%token OP_DO
+%token OP_ENDDO
+%token OP_LUA
+%token OP_MOVE
+%token OP_MOVEC
+%token OP_MOVEM
+%token OP_MOVEP
+%token OP_ILLEGAL
+%token OP_INCLUDE
+%token OP_JMP
+%token OP_JCLR
+%token OP_JSET
+%token OP_JSR
+%token OP_JSCLR
+%token OP_JSSET
+%token OP_NOP
+%token OP_REP
+%token OP_RESET
+%token OP_RTI
+%token OP_RTS
+%token OP_STOP
+%token OP_SWI
+%token OP_WAIT
+%token OP_EQU
+%token OP_ORG
+%token OP_DC
+%token OP_DS
+%token OP_DSM
+%token OP_END
+%token OP_PAGE
+%token OP_PSECT
+%token OP_ALIGN
+%token OP_INT
+%token SHL
+%token SHR
+%token OP_PI
+%token OP_SIN
+%token OP_COS
+%token OP_TAN
+%token OP_ATAN
+%token OP_ASIN
+%token OP_ACOS
+%token OP_EXP
+%token OP_LN
+%token OP_LOG
+%token OP_POW
+
+%type <n> num num_or_sym 
+%type <n> num_or_sym_expr
+%type <n> expr
+%type <n> ix
+%type <n> ix_long
+
+%type <ival> abs_addr abs_short_addr io_short_addr 
+%type <ival> a_b x_or_y ea b5_10111_max
+%type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12
+%type <ival> ea_short
+%type <ival> prog_ctl_reg
+%type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8
+%type <ival> mpy_arg mpy_srcs plus_minus
+%type <ival> sd3
+%type <ival> funky_ctl_reg tcc_sd space
+%type <sval> opt_label
+
+%type <regs> regs
+%type <ea> movep_ea_pp
+
+%left '|'
+%left '^'
+%left SHL SHR
+%left '&'
+%left '+' '-'
+%left '*' '/' '%'
+%right '~'
+
+%start input
+
+%%
+
+/*%%%********************* top syntax ***********************/
+
+input  :       /* empty */
+       |       input statement
+       ;
+
+statement
+       :       good_stuff EOL
+                       {
+                       if(pass == 2 && list_on && list_print_line) {
+                               printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
+                                       list_buf, substatement == 0 ? luntab(cur_line) : "");
+                               if(uses_buf2)
+                                       printf(ldebug ? "\n(%s|)\n" : "%s\n",
+                                               list_buf2);
+                               list_buf[0] = list_buf2[0] = '\0';
+                       }
+                       curline++;
+                       uses_buf2 = FALSE;
+                       list_print_line = TRUE;
+                       list_on = list_on_next;
+                       substatement = 0;
+                       if(NOT check_psect(seg, pc) && pass == 2)
+                               yyerror("%04X: psect violation", pc);
+                       }
+       |       good_stuff EOS
+                       {
+                       if(pass == 2 && list_on && list_print_line) {
+                               printf(ldebug ? "\n(%s" : "%s", list_buf);
+                               if(substatement == 0)
+                                       printf(ldebug ? "|%s)\n" : "%s\n", luntab(cur_line));
+                               else
+                                       printf(ldebug ? ")\n" : "\n");
+                               if(uses_buf2)
+                                       printf(ldebug ? "\n(%s|)\n" : "%s\n",
+                                               list_buf2);
+                               list_buf[0] = list_buf2[0] = '\0';
+                       }
+                       substatement++;
+                       uses_buf2 = FALSE;
+                       list_print_line = TRUE;
+                       list_on = list_on_next;
+                       if(NOT check_psect(seg, pc) && pass == 2)
+                               yyerror("%04X: psect violation", pc);
+                       }
+       |       error EOL
+                       {curline++; substatement = 0;}
+       ;
+
+good_stuff
+       :       /* empty */
+                       {sprintf(list_buf, "%s", spaces(0));}
+       |       cpp_droppings
+                       {list_print_line = FALSE;}
+       |       assembler_ops
+                       {long_symbolic_expr = FALSE;}
+       |       label_field operation_field
+                       {char *printcode();
+                       if(pass == 2) {
+                               gencode(seg, pc, w0);
+                               sprintf(list_buf, "%c:%04X %s ", segs[seg], pc, printcode(w0));
+                               pc++;
+                               if(uses_w1) {
+                                       gencode(seg, pc, w1);
+                                       sprintf(list_buf2, "%c:%04X %s", segs[seg], pc,
+                                               printcode(w1 & 0xFFFFFF));
+                                       uses_buf2++;
+                                       pc++;
+                               }
+                       } else {
+                               pc++;
+                               if(uses_w1)
+                                       pc++;
+                       }
+                       w0 = w1 = 0; uses_w1 = FALSE; 
+                       long_symbolic_expr = FALSE;}
+       |       SYM 
+                       {sym_def($1, INT, seg, pc);
+                       free($1);
+                       if(pass == 2 && list_on) {
+                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, spaces(14-8));
+                       long_symbolic_expr = FALSE;
+                       }}
+       ;
+
+cpp_droppings
+       :       '#' num STRING
+                       {if(strlen($3) > 0)
+                               curfile = $3;
+                       else
+                               curfile = "<stdin>";
+                       curline = $2.val.i - 1;}
+       ;
+
+assembler_ops
+       :       SYM OP_EQU expr
+                       {sym_def($1, $3.type, ANY, $3.val.i, $3.val.f);
+                       free($1);
+                       if(pass == 2 && list_on) {
+                               if($3.type == INT)
+                                       sprintf(list_buf, "%06X%s",
+                                               $3.val.i & 0xFFFFFF,
+                                               spaces(14-8));
+                               else
+                                       sprintf(list_buf, "%10g%s", $3.val.f,
+                                               spaces(14-4));
+                       }}
+       |       OP_ALIGN expr
+                       {int ival = n2int($2);
+                       if($2.type == UNDEF) {
+                               yyerror("illegal forward reference");
+                       } else if (ival <= 1) {
+                               yyerror("%d: illegal alignment", ival);
+                       } else {
+                               if(pc % ival != 0)
+                                       pc += ival - pc % ival;
+                       }
+                       if(pass == 2 && list_on)
+                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
+                                       spaces(14-8));
+                       }
+       |       OP_PSECT SYM
+                       {struct psect *pp = find_psect($2);
+                       if(NOT pp) {
+                               if(pass == 2)
+                                       yyerror("%s: undefined psect", $2);
+                       } else {
+                               seg = pp->seg;
+                               pc = pp->pc;
+                               set_psect(pp);
+                               if(pass == 2 && list_on)
+                                       sprintf(list_buf, "%c:%04X%s", segs[seg], pc,
+                                               spaces(14-8));
+                       }
+                       free($2);}
+       |       OP_PSECT SYM space expr ':' expr
+                       {new_psect($2, $3, n2int($4), n2int($6));
+                       if(pass == 2 && list_on)
+                               sprintf(list_buf, "%c:%04X %04X%s", 
+                                       segs[$3], n2int($4), n2int($6), spaces(14-8+4+1));
+                       }
+       |       OP_ORG space expr
+                       {pc = n2int($3);
+                       seg = $2;
+                       if(pass == 2 && list_on)
+                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
+                                       spaces(14-8));
+                       }
+       |       OP_ORG space expr ',' space expr
+                       {pc = n2int($3);
+                       seg = $2;
+                       if(pass == 2 && list_on)
+                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
+                                       spaces(14-8));
+                       }
+       |       label_field OP_DC dc_list
+       |       label_field OP_DS expr
+                       {pc += n2int($3);
+                       if(pass == 2 && list_on)
+                               sprintf(list_buf, "%c:%04X%s", segs[seg], pc, 
+                                       spaces(14-8));
+                       }
+       |       opt_label OP_DSM expr
+                       {int size = n2int($3);
+                       if(size)
+                       {    int align = 1;
+                            while(align < size)
+                                align <<= 1;
+                            pc += (align - (pc % align));
+                       }
+                       if($1)
+                       {   sym_def($1, INT, seg, pc);
+                           free($1);
+                       }
+                       pc += size;
+                       }
+       |       OP_PAGE num ',' num ',' num ',' num
+                       {if(pass == 2 && list_on) {
+                               sprintf(list_buf, "%s", spaces(0));
+                       }}
+       |       OP_INCLUDE STRING
+                       {if(pass == 2 && list_on) {
+                               printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n",
+                                       spaces(0), luntab(cur_line));
+                               list_print_line = FALSE;
+                       }
+                       include($2); /* free($2); */
+                       }
+       |       OP_END
+                       {if(pass == 2 && list_on) {
+                               sprintf(list_buf, "%s", spaces(0));
+                       }}
+       ;
+
+dc_list
+       :       dc_list ',' dc_stuff
+       |       dc_stuff
+       ;
+
+dc_stuff
+       :       STRING
+                       {int len = strlen($1), i; char *cp; w0 = 0;
+                       if(len % 3 == 2)
+                               len++;  /* force empty word */
+                       for(i = 0, cp = $1; i < len; i++, cp++) {
+                               w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8;
+                               if(i % 3 == 2 || i == len - 1) {
+                                       if(pass == 2) {
+                                               if(list_on) sprintf(list_buf, "%c:%04X %06X%s",
+                                                       segs[seg], pc, w0, 
+                                                       spaces(14-6+5));
+                                               gencode(seg, pc, w0);
+                                       }
+                                       pc++; w0 = 0;
+                               }
+                       }
+                       free($1);}
+       |       expr
+                       {int frac = n2frac($1);
+                       if(pass == 2) {
+                               if(list_on) {
+                                       sprintf(list_buf, "%c:%04X %06X%s", segs[seg], pc, 
+                                               frac & 0xFFFFFF, spaces(14-6+5));
+                               }
+                               gencode(seg, pc, frac);
+                       }
+                       pc++;}
+
+space
+       :       PMEM
+                       {$$ = PROG;}
+       |       XMEM
+                       {$$ = XDATA;}
+       |       YMEM
+                       {$$ = YDATA;}
+       |       LMEM
+                       {$$ = LDATA;}
+       ;       
+
+label_field
+       :       SYM
+                       {sym_def($1, INT, seg, pc);
+                       free($1);}
+       |       /* empty */
+       ;
+
+opt_label
+       :       SYM             {$$ = $1;}
+       |       /* empty */     {$$ = NULL;}
+       ;
+
+operation_field
+       :       operation
+                       {prev_hot_rreg = hot_rreg;
+                       prev_hot_nreg = hot_nreg;
+                       prev_hot_mreg = hot_mreg;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       if(just_rep) 
+                               just_rep--;}
+       ;
+
+operation
+       :       no_parallel
+       |       parallel_ok
+                       {w0 |= 0x200000;}
+       |       parallel_ok parallel_move
+       ;
+
+/*%%%************* instructions that allow parallel moves ****************/
+
+parallel_ok
+       :
+               OP_MPY mpy_arg
+                       {w0 |= 0x80 | $2 << 2;}
+       |       OP_MPYR mpy_arg
+                       {w0 |= 0x81 | $2 << 2;}
+       |       OP_MAC mpy_arg
+                       {w0 |= 0x82 | $2 << 2;}
+       |       OP_MACR mpy_arg
+                       {w0 |= 0x83 | $2 << 2;}
+
+       |       OP_SUB op8_1
+                       {w0 |= 0x04 | $2 << 3;}
+       |       OP_ADD op8_1
+                       {w0 |= 0x00 | $2 << 3;}
+       |       OP_MOVE
+                       {w0 |= 0x00;}
+
+       |       OP_TFR op8_2
+                       {w0 |= 0x01 | $2 << 3;}
+       |       OP_CMP op8_2
+                       {w0 |= 0x05 | $2 << 3;}
+       |       OP_CMPM op8_2
+                       {w0 |= 0x07 | $2 << 3;}
+
+       |       OP_RND op8_3
+                       {w0 |= 0x11 | $2 << 3;}
+       |       OP_ADDL op8_3
+                       {w0 |= 0x12 | $2 << 3;}
+       |       OP_CLR op8_3
+                       {w0 |= 0x13 | $2 << 3;}
+       |       OP_SUBL op8_3
+                       {w0 |= 0x16 | $2 << 3;}
+       |       OP_NOT op8_3
+                       {w0 |= 0x17 | $2 << 3;}
+
+       |       OP_ADDR op8_4
+                       {w0 |= 0x02 | $2 << 3;}
+       |       OP_TST op8_4
+                       {w0 |= 0x03 | $2 << 3;}
+       |       OP_SUBR op8_4
+                       {w0 |= 0x06 | $2 << 3;}
+
+       |       OP_AND op8_5
+                       {w0 |= 0x46 | $2 << 3;}
+       |       OP_OR op8_5
+                       {w0 |= 0x42 | $2 << 3;}
+       |       OP_EOR op8_5
+                       {w0 |= 0x43 | $2 << 3;}
+
+       |       OP_ASR op8_6
+                       {w0 |= 0x22 | $2 << 3;}
+       |       OP_LSR op8_6
+                       {w0 |= 0x23 | $2 << 3;}
+       |       OP_ABS op8_6
+                       {w0 |= 0x26 | $2 << 3;}
+       |       OP_ROR op8_6
+                       {w0 |= 0x27 | $2 << 3;}
+
+       |       OP_ASL op8_7
+                       {w0 |= 0x32 | $2 << 3;}
+       |       OP_LSL op8_7
+                       {w0 |= 0x33 | $2 << 3;}
+       |       OP_NEG op8_7
+                       {w0 |= 0x36 | $2 << 3;}
+       |       OP_ROL op8_7
+                       {w0 |= 0x37 | $2 << 3;}
+
+       |       OP_ADC op8_8
+                       {w0 |= 0x21 | $2 << 3;}
+       |       OP_SBC op8_8
+                       {w0 |= 0x25 | $2 << 3;}
+       ;
+
+mpy_arg        :       plus_minus mpy_srcs ',' a_b
+                       {$$ = $1 | $4 << 1 | $2 << 2;}
+       ;
+
+plus_minus
+       :       '+'    
+                       {$$ = 0;}
+       |       '-'    
+                       {$$ = 1;}
+       |       
+                       {$$ = 0;}
+       ;
+
+mpy_srcs
+       :       XREG ',' XREG
+                       {switch ($1 << 4 | $3) {
+                               case 0x00: $$ = 0x0; break;
+                               case 0x01: 
+                               case 0x10: $$ = 0x2; break;
+                               case 0x11: 
+                                       yyerror("illegal source operands"); 
+                                       break;
+                       }}                              
+       |       YREG ',' YREG
+                       {switch ($1 << 4 | $3) {
+                               case 0x00: $$ = 0x1; break;
+                               case 0x01: 
+                               case 0x10: $$ = 0x3; break;
+                               case 0x11: 
+                                       yyerror("illegal source operands"); 
+                                       break;
+                       }}                              
+       |       XREG ',' YREG
+                       {switch ($1 << 4 | $3) {
+                               case 0x00: $$ = 0x5; break;
+                               case 0x01: $$ = 0x4; break;
+                               case 0x10: $$ = 0x6; break;
+                               case 0x11: $$ = 0x7; break;
+                       }}                              
+       |       YREG ',' XREG
+                       {switch ($1 << 4 | $3) {
+                               case 0x00: $$ = 0x5; break;
+                               case 0x01: $$ = 0x6; break;
+                               case 0x10: $$ = 0x4; break;
+                               case 0x11: $$ = 0x7; break;
+                       }}                              
+       ;
+
+op8_1  :       BBBB ',' AAAA
+                       {$$ = 0x2;}
+       |       AAAA ',' BBBB
+                       {$$ = 0x3;}
+       |       XXXX ',' a_b
+                       {$$ = 0x4 | $3;}
+       |       YYYY ',' a_b
+                       {$$ = 0x6 | $3;}
+       |       XREG ',' a_b
+                       {$$ = 0x8 | $1 << 2 | $3;}
+       |       YREG ',' a_b
+                       {$$ = 0xA | $1 << 2 | $3;}
+       ;
+
+op8_2  :       BBBB ',' AAAA
+                       {$$ = 0x0;}
+       |       AAAA ',' BBBB
+                       {$$ = 0x1;}
+       |       XREG ',' a_b
+                       {$$ = 0x8 | $1 << 2 | $3;}
+       |       YREG ',' a_b
+                       {$$ = 0xA | $1 << 2 | $3;}
+       ;
+
+op8_3  :       AAAA
+                       {$$ = 0x0;}
+       |       BBBB
+                       {$$ = 0x1;}
+       |       BBBB ',' AAAA
+                       {$$ = 0x0;}
+       |       AAAA ',' BBBB
+                       {$$ = 0x1;}
+       ;
+
+op8_4  :       op8_3
+                       {$$ = $1;}
+       ;
+
+op8_5  :       XREG ',' a_b
+                       {$$ = 0x0 | $1 << 2 | $3;}
+       |       YREG ',' a_b
+                       {$$ = 0x2 | $1 << 2 | $3;}
+       ;
+
+op8_6  :       a_b
+                       {$$ = $1;}
+       ;
+
+op8_7  :       a_b
+                       {$$ = $1;}
+       ;
+
+op8_8  :       XXXX ',' a_b
+                       {$$ = 0x0 | $3;}
+       |       YYYY ',' a_b
+                       {$$ = 0x2 | $3;}
+       ;
+
+a_b    :       AAAA
+                       {$$ = 0;}
+       |       BBBB
+                       {$$ = 1;}
+       ;
+
+no_parallel
+       :       control_inst
+                       {if(just_rep == 1)
+                               yyerror("instruction not allowed after REP");}
+       |       bit_inst
+       |       move_inst
+       |       arith_inst
+       ;
+
+/*%%%************** non-parallel arithmetic and logical ********************/
+
+arith_inst
+       :       OP_NORM RREG ',' a_b
+                       {w0 |= 0x01D815 | $2 << 8 | $4 << 3;}
+       |       OP_DIV sd3
+                       {w0 |= 0x018040 | $2 << 3;}
+       |       or_op ix ',' funky_ctl_reg
+                       {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;}
+       |       and_op ix ',' funky_ctl_reg
+                       {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;}
+       ;
+
+or_op  :       OP_OR
+       |       OP_ORI
+       ;
+
+and_op :       OP_AND
+       |       OP_ANDI
+       ;
+
+/*%%%******************************* control instructions **********************/
+
+control_inst
+       :       OP_JSCC ea_a12
+                       {if($2) {
+                               w0 |= 0x0BC0A0 | $1 << 0;
+                       } else {
+                               w0 |= 0x0F0000 | $1 << 12;
+                       }}
+       |       OP_JCC ea_a12
+                       {if($2) {
+                               w0 |= 0x0AC0A0 | $1 << 0;
+                       } else {
+                               w0 |= 0x0E0000 | $1 << 12;
+                       }}
+       |       OP_JSR ea_a12
+                       {if($2) {
+                               w0 |= 0x0BC080;
+                       } else {
+                               w0 |= 0x0D0000;
+                       }}
+       |       OP_JMP ea_a12
+                       {if($2) {
+                               w0 |= 0x0AC080;
+                       } else {
+                               w0 |= 0x0C0000;
+                       }}
+
+       |       OP_JSSET control_args
+                       {w0 |= 0x0B0020;}
+       |       OP_JSCLR control_args
+                       {w0 |= 0x0B0000;}
+       |       OP_JSET control_args
+                       {w0 |= 0x0A0020;}
+       |       OP_JCLR control_args
+                       {w0 |= 0x0A0000;}
+
+       |       OP_REP rep_args
+                       {just_rep = 2;}
+       |       OP_DO do_args
+                       {uses_w1++;}
+       |       OP_ENDDO
+                       {w0 |= 0x00008C;}
+       |       OP_STOP
+                       {w0 |= 0x000087;}
+       |       OP_WAIT
+                       {w0 |= 0x000086;}
+       |       OP_RESET
+                       {w0 |= 0x000084;}
+       |       OP_RTS
+                       {w0 |= 0x00000C;}
+       |       OP_SWI
+                       {w0 |= 0x000006;}
+       |       OP_ILLEGAL
+                       {w0 |= 0x000005;}
+       |       OP_RTI
+                       {w0 |= 0x000004;}
+       |       OP_NOP
+                       {w0 |= 0x000000;
+                       just_rep = 0;}
+       ;
+
+do_args
+       :       ix ',' abs_addr
+                       {int ival = n2int($1);
+                       w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
+                       if(ival > 0xFFF && pass == 2) {
+                               yywarning("warning: immediate operand truncated");
+                       }
+                       w1 |= $3-1;}
+       |       regs ',' abs_addr
+                       {w0 |= 0x06C000 | $1.r6 << 8;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       w1 |= $3-1;}
+       |       x_or_y ea_no_ext ',' abs_addr
+                       {w0 |= 0x064000 | $2 << 8 | $1 << 6;
+                       w1 |= $4-1;}
+       |       x_or_y abs_short_addr ',' abs_addr      /* allow forced */
+                       {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
+                       /*
+                        * $$$ oops, can't check expr_seg because both abs_short_addr and
+                        * abs_addr touch it
+                        */
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       w1 |= $4-1;}
+       |       x_or_y abs_addr ',' abs_addr
+                       {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
+                       /*
+                        * $$$ oops, can't check expr_seg because both abs_short_addr and
+                        * abs_addr touch it
+                        */
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       w1 |= $4-1;}
+       ;                       
+
+rep_args
+       :       ix
+                       {int ival = n2int($1);
+                       w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8;
+                       if(ival > 0xFFF && pass == 2) {
+                               yywarning("warning: immediate operand truncated");
+                       }}
+       |       regs
+                       {w0 |= 0x06C020 | $1.r6 << 8;
+                       hot_rreg = hot_nreg = hot_mreg = -1;}
+       |       x_or_y ea_no_ext
+                       {w0 |= 0x064020 | $1 << 6 | $2 << 8;}
+       |       x_or_y abs_addr
+                       {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
+                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
+                               $1 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       }
+       |       x_or_y abs_short_addr   /* forced */
+                       {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
+                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
+                               $1 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       }
+       ;
+
+control_args
+       :       b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr
+                       {w0 |= $1 << 0 | $3 << 6;
+                       uses_w1++;
+                       w1 = $6;}
+       |       b5_10111_max ',' regs ',' abs_addr
+                       {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       uses_w1++;
+                       w1 = $5;}
+       ;
+
+p6_ean_a6
+       :       abs_addr        /* in pass 2 can always discern size. */
+                               /* Sometimes in pass one, too.  But since */
+                               /* address extension is always used for the */
+                               /* branch target, pass 1 can assume the */
+                               /* symbol value will fit; warning in pass 2 */
+                               /* if it doesn't */
+                       {if($1 != -1) { /* symbol defined */
+                               w0 |= ($1 & 0x3F) << 8;
+                               if($1 >= 0xFFC0) {
+                                       w0 |= 0x008080;
+                               } else {
+                                       w0 |= 0x000080;
+                                       if($1 > 0x003F && pass == 2)
+                                               yywarning("warning: address operand truncated");
+                               }
+                       }}
+       |       abs_short_addr
+                       {if($1 != -1) {
+                               if($1 > 0x3F && pass == 2)
+                                       yywarning("warning: address operand truncated");
+                               w0 |= 0x000080 | ($1 & 0x3F) << 8;
+                       }}
+       |       io_short_addr
+                       {if($1 != -1) {
+                               if($1 < 0xFFC0 && pass == 2)
+                                       yywarning("warning: address operand truncated");
+                               w0 |= 0x008080 | ($1 & 0x3F) << 8;
+                       }}
+       |       ea_no_ext
+                       {w0 |= 0x004080 | $1 << 8;}
+       ;
+
+/*%%%**************************** bit instructions ***************************/
+
+bit_inst
+       :       OP_BTST bit_args
+                       {w0 |= 0x0B0020;}
+       |       OP_BCHG bit_args
+                       {w0 |= 0x0B0000;}
+       |       OP_BSET bit_args
+                       {w0 |= 0x0A0020;}
+       |       OP_BCLR bit_args
+                       {w0 |= 0x0A0000;}
+       ;                       
+
+bit_args
+       :       b5_10111_max ',' x_or_y p6_ea_a6
+                       {w0 |= $1 << 0 | $3 << 6;
+                       }
+       |       b5_10111_max ',' regs
+                       {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;}
+       ;               
+
+p6_ea_a6
+       :       io_short_addr   /* must be forced to tell from abs_addr */
+                       {if($1 != -1) {
+                               w0 |= ($1 & 0x3F) << 8 | 0x008000;
+                               if($1 < 0xFFC0 && pass == 2)
+                                       yywarning("warning: address operand truncated");
+                       }}
+       |       abs_short_addr  /* must be forced to tell from abs_addr */
+                       {if($1 != -1) {
+                               w0 |= ($1 & 0x3F) << 8 | 0x000000;
+                               if($1 > 0x003F && pass == 2)
+                                       yywarning("warning: address operand truncated");
+                       }}
+       |       ea      /* can use abs_addr */
+                       {w0 |= 0x004000;}
+       ;
+
+/*%%%************************** move instructions **********************/
+
+move_inst
+       :       OP_MOVEP movep_args
+       |       OP_MOVEM movem_args
+       |       OP_MOVEC movec_args
+       |       OP_LUA ea_short ',' regs
+                       {w0 |= 0x044010 | $2 << 8 | $4.r4;}
+       |       OP_TCC tcc_args
+                       {w0 |= $1 << 12;}
+       ;               
+
+tcc_args
+       :       tcc_sd
+                       {w0 |= 0x020000 | $1 << 3;}
+       |       tcc_sd RREG ',' RREG
+                       {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;}
+       ;
+
+tcc_sd
+       :       regs /* a_b */ ',' regs /* a_b */
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($1.flags & R_AB && $3.flags & R_AB) {
+                               if($1.ab == $3.ab) 
+                                       yyerror("source and dest must be different");
+                               $$ = $3.ab;
+                       } else if($1.flags & R_XREG && $3.flags & R_AB) {
+                               $$ = 0x8 | $1.xreg << 2 | $3.ab;
+                       } else if($1.flags & R_YREG && $3.flags & R_AB) {
+                               $$ = 0xA | $1.yreg << 2 | $3.ab;
+                       } else 
+                               yyerror("illegal TCC operands");
+                       }
+       ;
+
+sd3    :       regs /* XREG */ ',' regs /* a_b */
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($1.flags & R_XREG && $3.flags & R_AB) {
+                               $$ = $1.xreg << 2 | $3.ab;
+                       } else if($1.flags & R_YREG && $3.flags & R_AB) {
+                               $$ = $1.yreg << 2 | 2 | $3.ab;
+                       }}
+       ;
+
+movec_args
+       :       x_or_y ea ',' regs /* ctl_reg */
+                       {if(NOT ($4.flags & R_CTL_REG))
+                               yyerror("bad MOVEC target register");
+                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
+                               $1 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($1 == 0) {
+                               w0 |= 0x05C020 | $4.ctl_reg;
+                       } else {
+                               w0 |= 0x05C060 | $4.ctl_reg;
+                       }}
+       |       regs /* ctl_reg */ ',' x_or_y ea
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if(NOT ($1.flags & R_CTL_REG))
+                               yyerror("bad MOVEC source register");
+                       if($3 == 0) {
+                               w0 |= 0x054020 | $1.ctl_reg;
+                       } else {
+                               w0 |= 0x054060 | $1.ctl_reg;
+                       }}
+       |       ix ',' regs /* ctl_reg */
+                       {int ival = n2int($1);
+                       if(NOT ($3.flags & R_CTL_REG))
+                               yyerror("bad MOVEC target register");
+                       if(ival < 256 && NOT long_symbolic_expr) {
+                               w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg; 
+                       } else {
+                               w0 |= 0x05C020 | 0x003400 | $3.ctl_reg;
+                               uses_w1++; w1 = ival & 0xFFFF;
+                       }}
+       |       x_or_y abs_short_addr ',' regs /* ctl_reg */
+                       {if($1 == 0) {
+                               w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg;
+                       } else {
+                               w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg;
+                       }
+                       if(NOT ($4.flags & R_CTL_REG))
+                               yyerror("bad MOVEC target register");
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       }
+       |       regs /* ctl_reg */ ',' x_or_y abs_short_addr
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($3 == 0) {
+                               w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg;
+                       } else {
+                               w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg;
+                       }
+                       if(NOT ($1.flags & R_CTL_REG))
+                               yyerror("bad MOVEC source register");
+                       if($4 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       }
+       |       regs /* ctl_reg */ ',' regs
+                       {if($1.flags & R_CTL_REG) {
+                               w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg;
+                       } else if($3.flags & R_CTL_REG) {
+                               w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg;
+                       } else if($1.flags & $3.flags & R_CTL_REG) {
+                               /* bogus? $$$ */
+                               w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | 
+                               $3.ctl_reg;
+                       } else {
+                               yyerror("MOVEC must reference a control reg");
+                       }}
+       ;
+
+movep_args
+       :       x_or_y movep_ea_pp ',' x_or_y movep_ea_pp
+                       {w0 |= 0x084080;
+                       switch($2.pp << 1 | $5.pp) {
+                               case 0: case 3:
+                                       yyerror("illegal MOVEP; can't move EA to EA or IO to IO");
+                                       break;
+                               case 1: /* ea, pp */
+                                       w0 |= $4 << 16 | 1 << 15 | $1 << 6 |
+                                               ($5.ext & 0x3F);
+                                       if($2.mode == 0x003000) {
+                                               w0 |= 0x003000;
+                                               uses_w1++;
+                                               w1 = $2.ext;
+                                       } else {
+                                               w0 |= $2.mode;
+                                       }
+                                       break;
+                               case 2: /* pp, ea */
+                                       w0 |= $1 << 16 | 0 << 15 | $4 << 6 |
+                                               ($2.ext & 0x3F);
+                                       if($5.mode == 0x003000) {
+                                               w0 |= 0x003000;
+                                               uses_w1++;
+                                               w1 = $5.ext;
+                                       } else {
+                                               w0 |= $5.mode;
+                                       }
+                                       break;
+                       }}
+       |       ix ',' x_or_y num_or_sym
+                       {w0 |= 0x084080;
+                       w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | 
+                               (n2int($4) & 0x3F);
+                       uses_w1++;
+                       w1 = n2int($1);}
+       |       PMEM ea ',' x_or_y num_or_sym
+                       {w0 |= 0x084040;
+                       w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);}
+       |       x_or_y movep_ea_pp ',' PMEM ea
+                       {w0 |= 0x084040;
+                       if($2.mode != 0x003000 && $2.mode != 0)
+                               yyerror("illegal MOVEP");
+                       w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);}
+       |       regs ',' x_or_y num_or_sym
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       w0 |= 0x084000;
+                       w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | 
+                               (n2int($4) & 0x3F);}
+       |       x_or_y movep_ea_pp ',' regs
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       w0 |= 0x084000;
+                       if(!$2.pp)
+                               yyerror("illegal MOVEP");
+                       w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);}
+       ;
+
+movep_ea_pp
+       :       abs_addr
+                       {if($1 != UNDEF && $1 >= 0xFFC0) {
+                               /* defined symbol or constant, in i/o range */
+                               $$.pp = 1;
+                               $$.mode = 0;
+                       } else {
+                               /* either out of i/o range or symbol not */
+                               /* yet defined:  assume ea extension */
+                               $$.pp = 0;
+                               $$.mode = 0x003000;
+                       }
+                       $$.ext = $1;}
+       |       io_short_addr   /* forced i/o short */
+                       {$$.pp = 1;
+                       $$.mode = 0;
+                       if($1 < 0xFFC0 && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       $$.ext = $1;}
+       |       ea_no_ext
+                       {$$.pp = 0;
+                       $$.mode = $1 << 8;
+                       $$.ext = $1;}
+       ;
+
+movem_args
+       :       regs ',' PMEM ea_a6
+                       {w0 |= 0x070000 | 0 << 15 | $1.r6;}
+       |       PMEM ea_a6 ',' regs
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       w0 |= 0x070000 | 1 << 15 | $4.r6;}
+       ;
+
+/*%%%**************** memory reference fields ************************/
+
+b5_10111_max
+       :       ix
+                       {int ival = n2int($1);
+                       $$ = ival; if(ival > 0x17) 
+                               yyerror("%d: illegal bit number", ival);}
+       ;
+
+x_or_y
+       :       XMEM
+                       {$$ = 0;}
+       |       YMEM
+                       {$$ = 1;}
+       ;
+
+/*%%%**************** effective address fields ************************/
+
+ea_a6
+       :       ea
+                       {w0 |= 0x004080;}
+       |       abs_short_addr
+                       {w0 |= ($1 & 0x3F) << 8;
+                       if($1 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       }
+       ;
+
+ea_a12
+       :       ea
+                       {$$ = 1;}
+       |       abs_short_addr
+                       {w0 |= $1 & 0xFFF; $$ = 0;
+                       if($1 > 0x0FFF && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       }
+       ;
+
+ea     :       abs_addr
+                       {w0 |= 0x003000;
+                       uses_w1++;
+                       w1 |= $1;
+                       $$ = 0x003000;}
+       |       ea_no_ext
+                       {w0 |= $1 << 8;
+                       $$ = $1 << 8;
+                       expr_seg = ANY;}
+       ;
+
+ea_no_ext
+       :       ea_short
+                       {$$ = $1;}
+       |       '(' RREG ')'
+                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
+                       $$ = 4 << 3 | $2;}
+       |       '(' RREG '+' NREG ')'
+                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
+                       if($4 == prev_hot_nreg) yywarning("warning: n%d just loaded", $4);
+                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
+                       $$ = 5 << 3 | $2;
+                       if($2 != $4) yyerror("Rn and Nn must be same number");}
+       |       '-' '(' RREG ')'
+                       {if($3 == prev_hot_rreg) yywarning("warning: r%d just loaded", $3);
+                       if($3 == prev_hot_mreg) yywarning("warning: m%d just loaded", $3);
+                       $$ = 7 << 3 | $3;}
+       ;
+
+ea_short
+       :       '(' RREG ')' '-' NREG
+                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
+                       if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5);
+                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
+                       $$ = 0 << 3 | $2;
+                       expr_seg = ANY;
+                       if($2 != $5) yyerror("Rn and Nn must be same number");}
+       |       '(' RREG ')' '+' NREG
+                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
+                       if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5);
+                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
+                       $$ = 1 << 3 | $2;
+                       expr_seg = ANY;
+                       if($2 != $5) yyerror("Rn and Nn must be same number");}
+       |       '(' RREG ')' '-'
+                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
+                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
+                       expr_seg = ANY;
+                       $$ = 2 << 3 | $2;}
+       |       '(' RREG ')' '+'
+                       {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2);
+                       if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2);
+                       expr_seg = ANY;
+                       $$ = 3 << 3 | $2;}
+       ;
+
+/*%%%******************* register fields ******************************/
+
+regs
+       :       XREG
+                       {$$.r6 = $$.r5 = 0x04 | $1;
+                       $$.sdx = $1;
+                       $$.xreg = $1;
+                       $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;}
+       |       YREG
+                       {$$.r6 = $$.r5 = 0x06 | $1;
+                       $$.sdy = $1;
+                       $$.yreg = $1;
+                       $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;}
+       |       AREG
+                       {switch($1) {
+                               case 0: 
+                                       $$.r6 = $$.r5 = 0x08 | 0; 
+                                       break;
+                               case 1: 
+                                       $$.r6 = $$.r5 = 0x08 | 4; 
+                                       break;
+                               case 2: 
+                                       $$.r6 = $$.r5 = 0x08 | 2; 
+                                       break;
+                       }
+                       $$.flags = R_R6|R_R5|R_UINT;}
+       |       BREG
+                       {switch($1) {
+                               case 0: 
+                                       $$.r6 = $$.r5 = 0x08 | 1; break;
+                               case 1: 
+                                       $$.r6 = $$.r5 = 0x08 | 5; break;
+                               case 2: 
+                                       $$.r6 = $$.r5 = 0x08 | 3; break;
+                       }
+                       $$.flags = R_R6|R_R5|R_UINT;}
+       |       AAAA
+                       {$$.r6 = $$.r5 = 0x0E;
+                       $$.sdx = $$.sdy = 0x2;
+                       $$.ab = 0;
+                       $$.lsd = 4;
+                       $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
+       |       BBBB
+                       {$$.r6 = $$.r5 = 0x0F;
+                       $$.sdx = $$.sdy = 0x3;
+                       $$.ab = 1;
+                       $$.lsd = 5;
+                       $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;}
+       |       RREG
+                       {$$.r6 = $$.r5 = 0x10 | $1;
+                       $$.r4 = 0x00 | $1;
+                       $$.flags = R_R6|R_R5|R_R4|R_UINT;
+                       hot_rreg = $1;}
+       |       NREG
+                       {$$.r6 = $$.r5 = 0x18 | $1;
+                       $$.r4 = 0x08 | $1;
+                       $$.flags = R_R6|R_R5|R_R4|R_UINT;
+                       hot_nreg = $1;}
+       |       MREG
+                       {$$.r6 = 0x20 | $1;
+                       $$.r5 = -1;
+                       $$.ctl_reg = $1;
+                       $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;
+                       hot_mreg = $1;}
+       |       prog_ctl_reg
+                       {$$.r6 = 0x38 | $1;
+                       $$.r5 = -1;
+                       $$.ctl_reg = 0x18 | $1;
+                       $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;}
+       |       A10
+                       {$$.lsd  = 0;
+                       $$.flags = R_LSD;}
+       |       B10
+                       {$$.lsd = 1;
+                       $$.flags = R_LSD;}
+       |       XXXX
+                       {$$.lsd = 2;
+                       $$.flags = R_LSD;}
+       |       YYYY
+                       {$$.lsd = 3;
+                       $$.flags = R_LSD;}
+       |       AABB
+                       {$$.lsd = 6;
+                       $$.flags = R_LSD;}
+       |       BBAA
+                       {$$.lsd = 7;
+                       $$.flags = R_LSD;}
+       ;
+
+prog_ctl_reg
+       :       SR
+                       {$$ = 1;}
+       |       OMR
+                       {$$ = 2;}
+       |       SP
+                       {$$ = 3;}
+       |       SSH
+                       {$$ = 4;}
+       |       SSL
+                       {$$ = 5;}
+       |       LA
+                       {$$ = 6;}
+       |       LC
+                       {$$ = 7;}
+       ;
+
+funky_ctl_reg
+       :       MR
+                       {$$ = 0;}
+       |       CCR
+                       {$$ = 1;}
+       |       OMR
+                       {$$ = 2;}
+       ;
+
+/*%%%************************* parallel moves *************/
+
+parallel_move
+       :       i_move
+       |       u_move
+       |       x_or_y_move
+       |       xr_move
+       |       ry_move
+       |       r_move
+       |       xy_move
+       |       l_move
+       ;
+
+i_move  :      ix ',' regs
+                       {int ival = n2int($1);
+                       int frac = n2frac($1);
+                       int value;
+                       BOOL shortform = FALSE;
+                       if($3.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       if(($3.flags & R_SFRAC) && $1.type == FLT) {
+                               if((frac & 0xFFFF) == 0 && 
+                                       NOT long_symbolic_expr) {
+                                       value = frac >> 16;
+                                       shortform++;
+                               } else {
+                                       value = frac;
+                               }
+                       } else {
+                               if(ival <= 0xFF && ival >= -0xFF && NOT long_symbolic_expr) {
+                                       value = ival;
+                                       shortform++;
+                               } else {
+                                       value = ival;
+                               }
+                       }
+
+                       if(shortform) {
+                               w0 |= 0x200000 | (value & 0xFF) << 8 |
+                                       $3.r5 << 16;
+                       } else {
+                               w0 |= 0x400000 | 0x00F400 |
+                                       ($3.r5 >> 3 & 3) << 20 | 
+                                       ($3.r5 & 7) << 16;
+                               uses_w1++; w1 = value;
+                       }}
+       ;
+
+r_move :       regs ',' regs
+                       {
+                               if($3.flags & R_CTL_REG) {
+                                       yyerror("please use MOVEC for control register moves");
+                                       break;
+                               }
+                               if($1.flags & R_R5 & $3.flags) 
+                                       w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13;
+                               else
+                                       yyerror("illegal R move");
+                       }       
+       ;
+
+u_move :       ea_short
+                       {w0 |= 0x204000 | $1 << 8;}
+       ;
+
+x_or_y_move
+       :       x_or_y ea ',' regs
+                       {w0 |= 0x40C000 | $1 << 19;
+                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
+                               $1 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($4.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
+       |       x_or_y abs_short_addr ',' regs
+                       {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8;
+                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
+                               $1 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($4.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
+       |       regs ',' x_or_y ea
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       w0 |= 0x404000 | $3 << 19;
+                       if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
+                               $3 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($1.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
+       |       regs ',' x_or_y abs_short_addr
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8;
+                       if($1.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
+                               $3 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($4 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
+       |       ix_long ',' regs
+                       {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 |
+                           ($3.r5 & 7) << 16;
+                       if($3.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       uses_w1++; w1 = n2frac($1);
+                       }
+       ;
+
+xr_move
+       :       x_or_y /* XMEM */ ea ',' regs   regs /* a_b */ ',' YREG
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA ||
+                               $1 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($1 == 0 && $5.flags & R_AB) {
+                               w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 |
+                                       $7 << 16;
+                       } else {
+                               yyerror("illegal X:R move");
+                       }}
+       |       ix ',' regs             regs /* a_b */ ',' YREG
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($4.flags & R_AB) {
+                               w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 |
+                                       $6 << 16;
+                               uses_w1++;
+                               w1 |= n2frac($1) & 0xFFFFFF;
+                       } else {
+                               yyerror("illegal X:R move");
+                       }}
+       |       regs ',' x_or_y /* XMEM */ ea   regs /* a_b */ ',' regs/*YREG*/
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA ||
+                               $3 == 1 && expr_seg != YDATA))
+                               yywarning("warning: space mismatch");
+                       if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB &&
+                               $7.flags & R_YREG) {
+                               w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 |
+                                       $7.yreg << 16;
+                       } else if($1.flags & R_AB && $3 == 0 && 
+                               $5.flags & R_XREG && $7.flags & R_AB) {
+                               if($5.xreg != 0) yyerror("must use X0");
+                               if($1.ab == 0 && $7.ab == 0)
+                                       w0 |= 0x080000;
+                               else if($1.ab == 1 && $7.ab == 1)
+                                       w0 |= 0x090000;
+                               else
+                                       yyerror("illegal X:R move");
+                       } else {
+                               yyerror("illegal X:R move");
+                       }}
+       ;
+
+ry_move        :       regs /* a_b */ ',' regs /* XREG */      YMEM ea ',' regs
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) {
+                               w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 |
+                                       $7.sdy << 16;
+                       } else {
+                               yyerror("illegal R:Y move");
+                       }}
+       |       regs /* a_b */ ',' regs /* XREG */      ix ',' regs
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) {
+                               w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 |
+                                       $6.sdy << 16;
+                               uses_w1++;
+                               w1 |= n2frac($4) & 0xFFFFFF;
+                       } else {
+                               yyerror("illegal R:Y move");
+                       }}
+       |       regs /* a_b */ ',' regs /* XREG */      regs ',' YMEM ea
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($1.flags & R_AB && $3.flags & R_XREG) {
+                               w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 |
+                               $4.sdy << 16;
+                       } else if ($1.flags & R_YREG && $3.flags & R_AB &&
+                               $4.flags & R_AB) {
+                               if($1.yreg != 0) yyerror("must use Y0");
+                               if($3.ab == 0 && $4.ab == 0)
+                                       w0 |= 0x088000;
+                               else if($3.ab == 1 && $4.ab == 1)
+                                       w0 |= 0x098000;
+                               else
+                                       yyerror("illegal R:Y move");
+                       } else {
+                               yyerror("illegal R:Y move");
+                       }}
+       ;
+
+l_move
+       :       LMEM ea ',' regs /* lsd */
+                       {if($4.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;}
+       |       regs /* lsd */ ',' LMEM ea
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       if($1.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;}
+       |       LMEM abs_short_addr ',' regs /* lsd */
+                       {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;
+                       if($4.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       if($2 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       w0 |= ($2 & 0x3F) << 8;}
+       |       regs /* lsd */ ',' LMEM abs_short_addr
+                       {hot_rreg = hot_nreg = hot_mreg = -1;
+                       w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;
+                       if($1.flags & R_CTL_REG) {
+                               yyerror("please use MOVEC for control register moves");
+                               break;
+                       }
+                       if($4 > 0x003F && pass == 2)
+                               yywarning("warning: address operand truncated");
+                       w0 |= ($4 & 0x3F) << 8;}
+       ;
+
+xy_move
+       :       x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs      YMEM ea /*ea_strange*/ ',' regs
+                       {int eax = $2, eay = $6,
+                            regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
+                            regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       if((eax & 0x400) == (eay & 0x400))
+                               yyerror("registers must be in opposite halves");
+                       if(!($4.flags & (R_AB | R_XREG)))
+                               yyerror("invalid X move register");
+                       if(!($8.flags & (R_AB | R_YREG)))
+                               yyerror("invalid Y move register");
+                       if($4.flags & R_AB &&
+                          $8.flags & R_AB &&
+                          $4.ab == $8.ab)
+                               yyerror("duplicate destination register");
+                       w0 = w0 & 0xFF | 0xC08000;      /* both write */
+                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
+       |       x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs      regs ',' YMEM ea /*ea_strange*/
+                       {int eax = $2, eay = $8,
+                            regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg,
+                            regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       if((eax & 0x400) == (eay & 0x400))
+                               yyerror("registers must be in opposite halves");
+                       if(!($4.flags & (R_AB | R_XREG)))
+                               yyerror("invalid X move register");
+                       if(!($5.flags & (R_AB | R_YREG)))
+                               yyerror("invalid Y move register");
+                       w0 = w0 & 0xFF | 0x808000;      /* X:write, Y:read */
+                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
+       |       regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/      YMEM ea /*ea_strange*/ ',' regs
+                       {int eax = $4, eay = $6,
+                            regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
+                            regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       if((eax & 0x400) == (eay & 0x400))
+                               yyerror("registers must be in opposite halves");
+                       if(!($1.flags & (R_AB | R_XREG)))
+                               yyerror("invalid X move register");
+                       if(!($8.flags & (R_AB | R_YREG)))
+                               yyerror("invalid Y move register");
+                       w0 = w0 & 0xFF | 0xC00000;      /* X:read, Y:write */
+                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
+       |       regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/      regs ',' YMEM ea /*ea_strange*/
+                       {int eax = $4, eay = $8,
+                            regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg,
+                            regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg;
+                       hot_rreg = hot_nreg = hot_mreg = -1;
+                       if((eax & 0x400) == (eay & 0x400))
+                               yyerror("registers must be in opposite halves");
+                       if(!($1.flags & (R_AB | R_XREG)))
+                               yyerror("invalid X move register");
+                       if(!($5.flags & (R_AB | R_YREG)))
+                               yyerror("invalid Y move register");
+                       w0 = w0 & 0xFF | 0x800000;      /* both read */
+                       w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;}
+       ;
+
+/*%%%******* absolute address and immediate data fields ************/
+
+num    :       CHEX
+                       {$$ = $1;}
+       |       CDEC
+                       {$$ = $1;}
+       |       FRAC
+                       {$$ = $1;}
+       ;
+
+ix     :       '#' expr
+                       {$$ = $2; expr_seg = ANY;}
+       |       '#' '<' expr
+                       {$$.val.i = n2int($3) & 0xFF;
+                       $$.type = INT;
+                       expr_seg = ANY;
+                       long_symbolic_expr = FALSE;}
+       ;
+
+ix_long        :       '#' '>' expr
+                       {$$ = $3; expr_seg = ANY;}
+       ;
+
+abs_addr
+       :       expr
+                       {$$ = n2int($1);
+                       expr_seg = $1.seg;}
+       ;
+
+abs_short_addr
+       :       '<' expr
+                       {$$ = n2int($2);
+                       expr_seg = $2.seg;}
+       ;
+
+io_short_addr
+       :       SHL expr
+                       {$$ = n2int($2);
+                       expr_seg = $2.seg;} 
+       ;
+
+num_or_sym
+       :       num
+                       {$$ = $1;}
+       |       SYM
+                       {$$ = sym_ref($1); free($1);}
+       |       io_short_addr
+                       {$$.type = INT; $$.val.i = $1; $$.seg = expr_seg;}
+       ;
+
+num_or_sym_expr
+       :       num
+                       {$$ = $1; expr_seg = $1.seg;}
+       |       SYM
+                       {$$ = sym_ref($1);
+                       free($1);
+                       long_symbolic_expr++;
+                       expr_seg = $$.seg;
+                       }
+       |       CHAR
+                       {$$.type = INT; $$.val.i = $1 & 0xFFFFFF; expr_seg = $$.seg = ANY;}
+       |       '*'
+                       {$$.type = INT; $$.val.i = pc; expr_seg = $$.seg = ANY;}
+       |       OP_PI
+                       {$$.type = FLT; $$.val.f = acos(-1.0); expr_seg = $$.seg = ANY;}
+       ;
+
+expr
+       :       OP_INT '(' expr ')'
+                       {$$.type = INT; 
+                       if($3.type == INT)
+                               $$.val.i = $3.val.i;
+                       else
+                               $$.val.i = $3.val.f;
+                       $$.seg = $3.seg;
+                       }
+       |       expr '|' expr
+                       {$$ = binary_op($1, '|', $3);}
+       |       expr '^' expr
+                       {$$ = binary_op($1, '^', $3);}
+       |       expr '&' expr
+                       {$$ = binary_op($1, '&', $3);}
+       |       expr SHR expr
+                       {$$ = binary_op($1, SHR, $3);}
+       |       expr SHL expr
+                       {$$ = binary_op($1, SHL, $3);}
+       |       expr '-' expr
+                       {$$ = binary_op($1, '-', $3);}
+       |       expr '+' expr
+                       {$$ = binary_op($1, '+', $3);}
+       |       expr '%' expr
+                       {$$ = binary_op($1, '%', $3);}
+       |       expr '/' expr
+                       {$$ = binary_op($1, '/', $3);}
+       |       expr '*' expr
+                       {$$ = binary_op($1, '*', $3);}
+       |       '-' expr %prec '~'
+                       {$$ = unary_op('-', $2);}
+       |       '~' expr
+                       {$$ = unary_op('~', $2);}
+       |       OP_SIN '(' expr ')'
+                       {$$ = unary_op('s', $3);}
+       |       OP_COS '(' expr ')'
+                       {$$ = unary_op('c', $3);}
+       |       OP_TAN '(' expr ')'
+                       {$$ = unary_op('t', $3);}
+       |       OP_ASIN '(' expr ')'
+                       {$$ = unary_op('S', $3);}
+       |       OP_ACOS '(' expr ')'
+                       {$$ = unary_op('C', $3);}
+       |       OP_ATAN '(' expr ')'
+                       {$$ = unary_op('T', $3);}
+       |       OP_EXP '(' expr ')'
+                       {$$ = unary_op('e', $3);}
+       |       OP_LN '(' expr ')'
+                       {$$ = unary_op('l', $3);}
+       |       OP_LOG '(' expr ')'
+                       {$$ = unary_op('L', $3);}
+       |       OP_ABS '(' expr ')'
+                       {$$ = unary_op('a', $3);}
+       |       OP_POW '(' expr ',' expr ')'
+                       {$$ = binary_op($3, 'p', $5);}
+       |       '(' expr ')'
+                       {$$ = $2;}
+       |       num_or_sym_expr
+                       {$$ = $1;}
+       ;
+
+/*%%%****************** end ******************************/
+
+%%
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <sys/signal.h>
+
+int yydebug;
+
+struct n binary_op(a1, op, a2)
+struct n a1, a2;
+int op;
+{
+       struct n result;
+       int iarg1, iarg2;
+       double farg1, farg2;
+
+       if(a1.type == UNDEF || a2.type == UNDEF) {
+               result.type = UNDEF;
+               return result;
+       }
+
+       iarg1 = a1.type == INT ? a1.val.i : a1.val.f;
+       iarg2 = a2.type == INT ? a2.val.i : a2.val.f;
+
+       farg1 = a1.type == INT ? a1.val.i : a1.val.f;
+       farg2 = a2.type == INT ? a2.val.i : a2.val.f;
+
+       /* figure out target segment */
+
+       if(a1.seg == a2.seg)
+               result.seg = a1.seg;
+       else if(a1.seg == ANY)
+               result.seg = a2.seg;
+       else if(a2.seg == ANY)
+               result.seg = a1.seg;
+       else
+               result.seg = NONE;
+
+       /* promote to float automatically */
+
+       if(a1.type != a2.type) {
+               if(a1.type == INT) {
+                       a1.val.f = a1.val.i;            /* truncate */
+                       a1.type = FLT;
+               } else {
+                       a2.val.f = a2.val.i;            /* truncate */
+               }
+       }
+       result.type = a1.type;
+
+       /* do the op */
+
+       switch(op) {
+       case '+':
+               if(result.type == INT) result.val.i = a1.val.i + a2.val.i;
+               else result.val.f = a1.val.f + a2.val.f;
+               break;
+       case '-':
+               if(result.type == INT) result.val.i = a1.val.i - a2.val.i;
+               else result.val.f = a1.val.f - a2.val.f;
+               break;
+       case '*':
+               if(result.type == INT) result.val.i = a1.val.i * a2.val.i;
+               else result.val.f = a1.val.f * a2.val.f;
+               break;
+       case '/':
+               if(result.type == INT) result.val.i = a1.val.i / a2.val.i;
+               else result.val.f = a1.val.f / a2.val.f;
+               break;
+       case '%':
+               result.val.i = iarg1 % iarg2;
+               result.type = INT;
+               break;
+       case SHL:
+               result.val.i = iarg1 << iarg2;
+               result.type = INT;
+               break;
+       case SHR:
+               result.val.i = iarg1 >> iarg2;
+               result.type = INT;
+               break;
+       case '|':
+               result.val.i = iarg1 | iarg2;
+               result.type = INT;
+               break;
+       case '&':
+               result.val.i = iarg1 & iarg2;
+               result.type = INT;
+               break;
+       case '^':
+               result.val.i = iarg1 ^ iarg2;
+               result.type = INT;
+               break;
+       case 'p':
+               result.val.f = pow(farg1, farg2);
+               result.type = FLT;
+       }
+
+       return result;
+}
+
+jmp_buf unary_env;
+
+void
+sigfpu()
+{
+       longjmp(unary_env, 1);
+}
+
+char *unary_name(op)
+{
+       switch(op) {
+       case 's':       return "sin";
+       case 'c':       return "cos";
+       case 't':       return "tan";
+       case 'S':       return "asin";
+       case 'C':       return "acos";
+       case 'T':       return "atan";
+       case 'e':       return "exp";
+       case 'l':       return "ln";
+       case 'L':       return "log";
+       case 'a':       return "abs";
+       }
+}
+
+struct n unary_op(op, a1)
+int op;
+struct n a1;
+{
+       struct n result;
+       void (*orig)();
+       double farg;
+
+       if(a1.type == UNDEF) {
+               result.type = UNDEF;
+               return result;
+       }
+
+       result.seg = a1.seg;
+
+       /* do the op */
+
+       orig = signal(SIGFPE, sigfpu);
+       if(setjmp(unary_env)) {
+               yyerror("floating point exception in function %s", unary_name(op));
+               result.val.i = result.val.f = 0;
+       } else {
+               farg = a1.t