+++ /dev/null
-#######################################################
-#
-# 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
TO MAKE AND USE
-Type "make".
+Type "make -C src".
The resulting program, a56, is used as follows:
+++ /dev/null
-.\"
-.\" 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).
+++ /dev/null
-/*******************************************************
- *
- * 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);
+++ /dev/null
-.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;}
+++ /dev/null
-%{
-/*******************************************************
- *
- * 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;
-}
+++ /dev/null
-#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);
- }
-}
+++ /dev/null
-/*
- 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
+++ /dev/null
-.\"
-.\" 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).
+++ /dev/null
-/*
- * 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");
-
-}
+++ /dev/null
-/*******************************************************
- *
- * 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;
-}
+++ /dev/null
-/*******************************************************
- *
- * 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;
-}
--- /dev/null
+#######################################################
+#
+# 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
--- /dev/null
+.\"
+.\" 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).
--- /dev/null
+/*******************************************************
+ *
+ * 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);
--- /dev/null
+.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;}
--- /dev/null
+%{
+/*******************************************************
+ *
+ * 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;
+}
--- /dev/null
+#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);
+ }
+}
--- /dev/null
+/*
+ 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
--- /dev/null
+.\"
+.\" 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).
--- /dev/null
+/*
+ * 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");
+
+}
--- /dev/null
+/*******************************************************
+ *
+ * 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;
+}
--- /dev/null
+/*******************************************************
+ *
+ * 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;
+}
--- /dev/null
+/*******************************************************
+ *
+ * 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.
+ *
+ */
+static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
+
+/*
+ * subs.c - Some subroutines for the assembler.
+ *
+ */
+
+#include "a56.h"
+
+#define MAX 1024
+
+FILE *open_read(file)
+char *file;
+{
+ FILE *fp;
+
+ if(strcmp(file, "-") == 0)
+ fp = stdin;
+ else if ((fp = fopen(file, "r")) == NULL) {
+ perror(file);
+ exit(1);
+ }
+ return fp;
+}
+
+FILE *open_write(file)
+char *file;
+{
+ FILE *fp;
+ if ((fp = fopen(file, "w")) == NULL) {
+ perror(file);
+ exit(1);
+ }
+ return fp;
+}
+
+FILE *open_append(file)
+char *file;
+{
+ FILE *fp;
+ if ((fp = fopen(file, "a")) == NULL) {
+ perror(file);
+ exit(1);
+ }
+ return fp;
+}
+
+fatal(c, a1, a2, a3, a4, a5, a6, a7, a8)
+char *c, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+{
+ fprintf(stderr, c, a1, a2, a3, a4, a5, a6, a7, a8);
+ exit(1);
+}
+
+#define TABS 8
+#define MAX_BUF 256
+
+char tabbuf[MAX_BUF], *untabn();
+char *untab(s) /* expand tabs in s */
+register char *s;
+{
+ return untabn(s, TABS);
+}
+
+char *untabn(s, stops) /* expand tabs in s */
+register char *s;
+register int stops;
+{
+ char *o = s;
+
+ /* copy input string into buffer to scan while input string is modified */
+
+ register char *b = tabbuf;
+
+ strncpy(b, s, MAX_BUF);
+
+ /* iterate until the copy of the input string is depleted */
+
+ while(*b) {
+ if(*b == '\t') {
+ do
+ *s = ' ';
+ while ((++s - o) % stops);
+ } else {
+ *s = *b; s++;
+ }
+ b++;
+ }
+
+ /* null terminate the resultant string */
+
+ *s = '\0';
+
+ return o;
+}
+
+char *alloc(size)
+int size;
+{
+ char *p = (char *)malloc(size);
+ if(NOT p)
+ fatal("alloc: insufficient virtual memory to allocate %d bytes\n",
+ size);
+ return p;
+}
+
+#define ascii2n(c) \
+ ((c) >= 'a' ? (c) - 'a' + 10 : ((c) >= 'A' ? (c) - 'A' + 10 : (c) - '0'))
+
+#define valid(c) ((c) >= '0' && (c) <= '9' || \
+ (c) >= 'A' && (c) <= 'Z' || \
+ (c) >= 'a' && (c) <= 'z')
+
+a56_strtol(s, p, base)
+register char *s, **p;
+register int base;
+{
+ register long result = 0;
+ register int sign = 0;
+
+ while(*s == ' ' || *s == '\t')
+ s++;
+
+ if(*s == '-') {
+ s++;
+ sign++;
+ }
+
+ while(valid(*s)) {
+ register int dig = ascii2n(*s);
+ if(dig >= base)
+ break;
+ result *= base;
+ result += dig;
+ s++;
+ }
+
+ if(p)
+ *p = s;
+
+ return sign ? -result : result;
+}
--- /dev/null
+BEGIN {printf("struct {int n; char *name;} tok_tab[] = {\n");}
+/#define/ {printf(" {%d, \"%s\"},\n", $3, $2);}
+/# define/ {printf(" {%d, \"%s\"},\n", $4, $3);}
+END {printf("};\n#define N_TOK (sizeof tok_tab / sizeof tok_tab[0])\nint n_tok = N_TOK;\n");}
--- /dev/null
+struct {int n; char *name;} tok_tab[] = {
+ {257, "CHEX"},
+ {258, "CDEC"},
+ {259, "FRAC"},
+ {260, "AREG"},
+ {261, "BREG"},
+ {262, "MREG"},
+ {263, "NREG"},
+ {264, "RREG"},
+ {265, "XREG"},
+ {266, "YREG"},
+ {267, "OP"},
+ {268, "OPA"},
+ {269, "OPP"},
+ {270, "OP_JCC"},
+ {271, "OP_JSCC"},
+ {272, "OP_TCC"},
+ {273, "SYM"},
+ {274, "STRING"},
+ {275, "CHAR"},
+ {276, "XMEM"},
+ {277, "YMEM"},
+ {278, "LMEM"},
+ {279, "PMEM"},
+ {280, "AAAA"},
+ {281, "A10"},
+ {282, "BBBB"},
+ {283, "B10"},
+ {284, "AABB"},
+ {285, "BBAA"},
+ {286, "XXXX"},
+ {287, "YYYY"},
+ {288, "SR"},
+ {289, "MR"},
+ {290, "CCR"},
+ {291, "OMR"},
+ {292, "SP"},
+ {293, "SSH"},
+ {294, "SSL"},
+ {295, "LA"},
+ {296, "LC"},
+ {297, "EOL"},
+ {298, "EOS"},
+ {299, "LEXBAD"},
+ {300, "OP_ABS"},
+ {301, "OP_ADC"},
+ {302, "OP_ADD"},
+ {303, "OP_ADDL"},
+ {304, "OP_ADDR"},
+ {305, "OP_ASL"},
+ {306, "OP_ASR"},
+ {307, "OP_CLR"},
+ {308, "OP_CMP"},
+ {309, "OP_CMPM"},
+ {310, "OP_DIV"},
+ {311, "OP_MAC"},
+ {312, "OP_MACR"},
+ {313, "OP_MPY"},
+ {314, "OP_MPYR"},
+ {315, "OP_NEG"},
+ {316, "OP_NORM"},
+ {317, "OP_RND"},
+ {318, "OP_SBC"},
+ {319, "OP_SUB"},
+ {320, "OP_SUBL"},
+ {321, "OP_SUBR"},
+ {322, "OP_TFR"},
+ {323, "OP_TST"},
+ {324, "OP_AND"},
+ {325, "OP_ANDI"},
+ {326, "OP_EOR"},
+ {327, "OP_LSL"},
+ {328, "OP_LSR"},
+ {329, "OP_NOT"},
+ {330, "OP_OR"},
+ {331, "OP_ORI"},
+ {332, "OP_ROL"},
+ {333, "OP_ROR"},
+ {334, "OP_BCLR"},
+ {335, "OP_BSET"},
+ {336, "OP_BCHG"},
+ {337, "OP_BTST"},
+ {338, "OP_DO"},
+ {339, "OP_ENDDO"},
+ {340, "OP_LUA"},
+ {341, "OP_MOVE"},
+ {342, "OP_MOVEC"},
+ {343, "OP_MOVEM"},
+ {344, "OP_MOVEP"},
+ {345, "OP_ILLEGAL"},
+ {346, "OP_INCLUDE"},
+ {347, "OP_JMP"},
+ {348, "OP_JCLR"},
+ {349, "OP_JSET"},
+ {350, "OP_JSR"},
+ {351, "OP_JSCLR"},
+ {352, "OP_JSSET"},
+ {353, "OP_NOP"},
+ {354, "OP_REP"},
+ {355, "OP_RESET"},
+ {356, "OP_RTI"},
+ {357, "OP_RTS"},
+ {358, "OP_STOP"},
+ {359, "OP_SWI"},
+ {360, "OP_WAIT"},
+ {361, "OP_EQU"},
+ {362, "OP_ORG"},
+ {363, "OP_DC"},
+ {364, "OP_DS"},
+ {365, "OP_DSM"},
+ {366, "OP_END"},
+ {367, "OP_PAGE"},
+ {368, "OP_PSECT"},
+ {369, "OP_ALIGN"},
+ {370, "OP_INT"},
+ {371, "SHL"},
+ {372, "SHR"},
+ {373, "OP_PI"},
+ {374, "OP_SIN"},
+ {375, "OP_COS"},
+ {376, "OP_TAN"},
+ {377, "OP_ATAN"},
+ {378, "OP_ASIN"},
+ {379, "OP_ACOS"},
+ {380, "OP_EXP"},
+ {381, "OP_LN"},
+ {382, "OP_LOG"},
+ {383, "OP_POW"},
+};
+#define N_TOK (sizeof tok_tab / sizeof tok_tab[0])
+int n_tok = N_TOK;
--- /dev/null
+/*******************************************************
+ *
+ * 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-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";
+
+#include <stdio.h>
+
+/*
+ * This small program converts the a56.out file from the assembler
+ * into a file suitable for loading into 56001 memory via the
+ * SLOADER.ASM serial loader program provided on the Motorola
+ * Dr. Bubb BBS.
+ *
+ */
+
+#define MAX 256
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+ char buf[MAX];
+ int curaddr = 0;
+ int line = 0;
+ int curseg = '\0';
+ int startaddr = -1;
+
+ while(gets(buf)) {
+ char seg;
+ int addr, data;
+ line++;
+ if(sscanf(buf, "%c%x%x", &seg, &addr, &data) == 3) {
+ if(seg == 'I' || seg == 'F') break;
+ if(seg != curseg || curaddr != addr) {
+ printf("\n_DATA %c %04X\n", curseg = seg, curaddr = addr);
+ }
+ if(startaddr == -1 && seg == 'P')
+ startaddr = addr;
+ printf("%06X ", data & 0xFFFFFF);
+ curaddr++;
+ }
+ }
+ printf("\n_END %04X\n", startaddr);
+}
--- /dev/null
+/*******************************************************
+ *
+ * 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.
+ *
+ */
+static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
+
+/*
+ * This program converts the a56.out assembler output file into
+ * raw binary, suitable for conversion to S-records for an EPROM burner.
+ *
+ */
+
+
+#define MAX 256
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+ char buf[MAX];
+ int curaddr = 0;
+ int line = 0;
+
+ while(gets(buf)) {
+ char seg;
+ int addr, data;
+ line++;
+ if(sscanf(buf, "%c%x%x", &seg, &addr, &data) == 3) {
+ if(seg == 'I') {
+ break;
+ } else {
+ if(addr < curaddr) {
+ fatal("%s: input line %d: can't go back\n", argv[0], line);
+ } else if(addr != curaddr) {
+ while(curaddr < addr) {
+ putword(0);
+ curaddr++;
+ }
+ }
+ putword(data);
+ curaddr++;
+ }
+ }
+ }
+}
+
+putword(data)
+int data;
+{
+ putchar(data >> 0 & 0xFF);
+ putchar(data >> 8 & 0xFF);
+ putchar(data >> 16 & 0xFF);
+}
+++ /dev/null
-/*******************************************************
- *
- * 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.
- *
- */
-static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
-
-/*
- * subs.c - Some subroutines for the assembler.
- *
- */
-
-#include "a56.h"
-
-#define MAX 1024
-
-FILE *open_read(file)
-char *file;
-{
- FILE *fp;
-
- if(strcmp(file, "-") == 0)
- fp = stdin;
- else if ((fp = fopen(file, "r")) == NULL) {
- perror(file);
- exit(1);
- }
- return fp;
-}
-
-FILE *open_write(file)
-char *file;
-{
- FILE *fp;
- if ((fp = fopen(file, "w")) == NULL) {
- perror(file);
- exit(1);
- }
- return fp;
-}
-
-FILE *open_append(file)
-char *file;
-{
- FILE *fp;
- if ((fp = fopen(file, "a")) == NULL) {
- perror(file);
- exit(1);
- }
- return fp;
-}
-
-fatal(c, a1, a2, a3, a4, a5, a6, a7, a8)
-char *c, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-{
- fprintf(stderr, c, a1, a2, a3, a4, a5, a6, a7, a8);
- exit(1);
-}
-
-#define TABS 8
-#define MAX_BUF 256
-
-char tabbuf[MAX_BUF], *untabn();
-char *untab(s) /* expand tabs in s */
-register char *s;
-{
- return untabn(s, TABS);
-}
-
-char *untabn(s, stops) /* expand tabs in s */
-register char *s;
-register int stops;
-{
- char *o = s;
-
- /* copy input string into buffer to scan while input string is modified */
-
- register char *b = tabbuf;
-
- strncpy(b, s, MAX_BUF);
-
- /* iterate until the copy of the input string is depleted */
-
- while(*b) {
- if(*b == '\t') {
- do
- *s = ' ';
- while ((++s - o) % stops);
- } else {
- *s = *b; s++;
- }
- b++;
- }
-
- /* null terminate the resultant string */
-
- *s = '\0';
-
- return o;
-}
-
-char *alloc(size)
-int size;
-{
- char *p = (char *)malloc(size);
- if(NOT p)
- fatal("alloc: insufficient virtual memory to allocate %d bytes\n",
- size);
- return p;
-}
-
-#define ascii2n(c) \
- ((c) >= 'a' ? (c) - 'a' + 10 : ((c) >= 'A' ? (c) - 'A' + 10 : (c) - '0'))
-
-#define valid(c) ((c) >= '0' && (c) <= '9' || \
- (c) >= 'A' && (c) <= 'Z' || \
- (c) >= 'a' && (c) <= 'z')
-
-a56_strtol(s, p, base)
-register char *s, **p;
-register int base;
-{
- register long result = 0;
- register int sign = 0;
-
- while(*s == ' ' || *s == '\t')
- s++;
-
- if(*s == '-') {
- s++;
- sign++;
- }
-
- while(valid(*s)) {
- register int dig = ascii2n(*s);
- if(dig >= base)
- break;
- result *= base;
- result += dig;
- s++;
- }
-
- if(p)
- *p = s;
-
- return sign ? -result : result;
-}
+++ /dev/null
-BEGIN {printf("struct {int n; char *name;} tok_tab[] = {\n");}
-/#define/ {printf(" {%d, \"%s\"},\n", $3, $2);}
-/# define/ {printf(" {%d, \"%s\"},\n", $4, $3);}
-END {printf("};\n#define N_TOK (sizeof tok_tab / sizeof tok_tab[0])\nint n_tok = N_TOK;\n");}
+++ /dev/null
-struct {int n; char *name;} tok_tab[] = {
- {257, "CHEX"},
- {258, "CDEC"},
- {259, "FRAC"},
- {260, "AREG"},
- {261, "BREG"},
- {262, "MREG"},
- {263, "NREG"},
- {264, "RREG"},
- {265, "XREG"},
- {266, "YREG"},
- {267, "OP"},
- {268, "OPA"},
- {269, "OPP"},
- {270, "OP_JCC"},
- {271, "OP_JSCC"},
- {272, "OP_TCC"},
- {273, "SYM"},
- {274, "STRING"},
- {275, "CHAR"},
- {276, "XMEM"},
- {277, "YMEM"},
- {278, "LMEM"},
- {279, "PMEM"},
- {280, "AAAA"},
- {281, "A10"},
- {282, "BBBB"},
- {283, "B10"},
- {284, "AABB"},
- {285, "BBAA"},
- {286, "XXXX"},
- {287, "YYYY"},
- {288, "SR"},
- {289, "MR"},
- {290, "CCR"},
- {291, "OMR"},
- {292, "SP"},
- {293, "SSH"},
- {294, "SSL"},
- {295, "LA"},
- {296, "LC"},
- {297, "EOL"},
- {298, "EOS"},
- {299, "LEXBAD"},
- {300, "OP_ABS"},
- {301, "OP_ADC"},
- {302, "OP_ADD"},
- {303, "OP_ADDL"},
- {304, "OP_ADDR"},
- {305, "OP_ASL"},
- {306, "OP_ASR"},
- {307, "OP_CLR"},
- {308, "OP_CMP"},
- {309, "OP_CMPM"},
- {310, "OP_DIV"},
- {311, "OP_MAC"},
- {312, "OP_MACR"},
- {313, "OP_MPY"},
- {314, "OP_MPYR"},
- {315, "OP_NEG"},
- {316, "OP_NORM"},
- {317, "OP_RND"},
- {318, "OP_SBC"},
- {319, "OP_SUB"},
- {320, "OP_SUBL"},
- {321, "OP_SUBR"},
- {322, "OP_TFR"},
- {323, "OP_TST"},
- {324, "OP_AND"},
- {325, "OP_ANDI"},
- {326, "OP_EOR"},
- {327, "OP_LSL"},
- {328, "OP_LSR"},
- {329, "OP_NOT"},
- {330, "OP_OR"},
- {331, "OP_ORI"},
- {332, "OP_ROL"},
- {333, "OP_ROR"},
- {334, "OP_BCLR"},
- {335, "OP_BSET"},
- {336, "OP_BCHG"},
- {337, "OP_BTST"},
- {338, "OP_DO"},
- {339, "OP_ENDDO"},
- {340, "OP_LUA"},
- {341, "OP_MOVE"},
- {342, "OP_MOVEC"},
- {343, "OP_MOVEM"},
- {344, "OP_MOVEP"},
- {345, "OP_ILLEGAL"},
- {346, "OP_INCLUDE"},
- {347, "OP_JMP"},
- {348, "OP_JCLR"},
- {349, "OP_JSET"},
- {350, "OP_JSR"},
- {351, "OP_JSCLR"},
- {352, "OP_JSSET"},
- {353, "OP_NOP"},
- {354, "OP_REP"},
- {355, "OP_RESET"},
- {356, "OP_RTI"},
- {357, "OP_RTS"},
- {358, "OP_STOP"},
- {359, "OP_SWI"},
- {360, "OP_WAIT"},
- {361, "OP_EQU"},
- {362, "OP_ORG"},
- {363, "OP_DC"},
- {364, "OP_DS"},
- {365, "OP_DSM"},
- {366, "OP_END"},
- {367, "OP_PAGE"},
- {368, "OP_PSECT"},
- {369, "OP_ALIGN"},
- {370, "OP_INT"},
- {371, "SHL"},
- {372, "SHR"},
- {373, "OP_PI"},
- {374, "OP_SIN"},
- {375, "OP_COS"},
- {376, "OP_TAN"},
- {377, "OP_ATAN"},
- {378, "OP_ASIN"},
- {379, "OP_ACOS"},
- {380, "OP_EXP"},
- {381, "OP_LN"},
- {382, "OP_LOG"},
- {383, "OP_POW"},
-};
-#define N_TOK (sizeof tok_tab / sizeof tok_tab[0])
-int n_tok = N_TOK;
+++ /dev/null
-/*******************************************************
- *
- * 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-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";
-
-#include <stdio.h>
-
-/*
- * This small program converts the a56.out file from the assembler
- * into a file suitable for loading into 56001 memory via the
- * SLOADER.ASM serial loader program provided on the Motorola
- * Dr. Bubb BBS.
- *
- */
-
-#define MAX 256
-
-main(argc,argv)
-int argc;
-char *argv[];
-{
- char buf[MAX];
- int curaddr = 0;
- int line = 0;
- int curseg = '\0';
- int startaddr = -1;
-
- while(gets(buf)) {
- char seg;
- int addr, data;
- line++;
- if(sscanf(buf, "%c%x%x", &seg, &addr, &data) == 3) {
- if(seg == 'I' || seg == 'F') break;
- if(seg != curseg || curaddr != addr) {
- printf("\n_DATA %c %04X\n", curseg = seg, curaddr = addr);
- }
- if(startaddr == -1 && seg == 'P')
- startaddr = addr;
- printf("%06X ", data & 0xFFFFFF);
- curaddr++;
- }
- }
- printf("\n_END %04X\n", startaddr);
-}
+++ /dev/null
-/*******************************************************
- *
- * 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.
- *
- */
-static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen";
-
-/*
- * This program converts the a56.out assembler output file into
- * raw binary, suitable for conversion to S-records for an EPROM burner.
- *
- */
-
-
-#define MAX 256
-
-main(argc,argv)
-int argc;
-char *argv[];
-{
- char buf[MAX];
- int curaddr = 0;
- int line = 0;
-
- while(gets(buf)) {
- char seg;
- int addr, data;
- line++;
- if(sscanf(buf, "%c%x%x", &seg, &addr, &data) == 3) {
- if(seg == 'I') {
- break;
- } else {
- if(addr < curaddr) {
- fatal("%s: input line %d: can't go back\n", argv[0], line);
- } else if(addr != curaddr) {
- while(curaddr < addr) {
- putword(0);
- curaddr++;
- }
- }
- putword(data);
- curaddr++;
- }
- }
- }
-}
-
-putword(data)
-int data;
-{
- putchar(data >> 0 & 0xFF);
- putchar(data >> 8 & 0xFF);
- putchar(data >> 16 & 0xFF);
-}