From: Jason Self Date: Sun, 26 Nov 2017 20:58:58 +0000 (-0800) Subject: Move source into src directory X-Git-Url: https://jxself.org/git/?p=a56.git;a=commitdiff_plain;h=HEAD;hp=c6db6f4c5cb82f5e09472163bf11be0c165965ee Move source into src directory --- diff --git a/Makefile b/Makefile deleted file mode 100644 index b2294b3..0000000 --- a/Makefile +++ /dev/null @@ -1,146 +0,0 @@ -####################################################### -# -# a56 - a DSP56001 assembler -# -# Written by Quinn C. Jensen -# July 1990 -# -####################################################### - -# Copyright (C) 2012 Thorsten Alteholz -# -# 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 -# . -# -# This file incorporates work covered by the following copyright and -# permission notice: -# -# Copyright (C) 1990-1998 Quinn C. Jensen -# -# Permission to use, copy, modify, distribute, and sell this -# software and its documentation for any purpose is hereby granted -# without fee, provided that the above copyright notice appear in all -# copies and that both that copyright notice and this permission -# notice appear in supporting documentation. The author makes no -# representations about the suitability of this software for any -# purpose. It is provided "as is" without express or implied -# warranty. - -# environment definitions -# uncomment the ones you like - -# generic unix -CC = cc -HOSTCC = cc -YACC = yacc -CCDEFS = -DLDEBUG -MV = mv -YTABC = y.tab.c -YTABH = y.tab.h -POSTPROCESS = echo - -# gcc & bison -#CC = gcc -#HOSTCC = gcc -#YACC = bison -y -#CCDEFS = -#MV = mv -#YTABC = y.tab.c -#YTABH = y.tab.h -#POSTPROCESS = echo - -# Delorie's DOS gcc (from ftp://omnigate.clarkson.edu/pub/msdos/djgpp) -#CC = gcc -#HOSTCC = gcc -#YACC = bison -y -#CCDEFS = -#MV = ren -#YTABC = y_tab.c -#YTABH = y_tab.h -#POSTPROCESS = coff2exe - -# gcc cross-compile to go32 environment -#CC = i386-go32-gcc -#HOSTCC = cc -#YACC = yacc -#CCDEFS = -#MV = mv -#YTABC = y.tab.c -#YTABH = y.tab.h -#POSTPROCESS = echo - -####################################################### - -# -O or -g -#DEBUG = -O -Olimit 3000 -DEBUG = -O - -SRCS = main.c a56.y lex.c subs.c getopt.c kparse.key -OBJS = main.o gram.o lex.o toktab.o subs.o getopt.o kparse.o - -DEFINES = $(CCDEFS) -#DEFINES = -DYYDEBUG -DLDEBUG $(CCDEFS) - -CFLAGS = $(DEBUG) $(DEFINES) $(CPPFLAGS) $(LDFLAGS) - -all: keybld a56 toomf - -a56: $(OBJS) - $(CC) $(CFLAGS) -o a56 $(OBJS) -lm - @$(POSTPROCESS) a56 - -keybld: keybld.o ksubs.o - $(HOSTCC) $(CFLAGS) -o keybld keybld.o ksubs.o - @$(POSTPROCESS) keybld - -keybld.o: keybld.c - $(HOSTCC) $(CFLAGS) -c keybld.c - -ksubs.o: subs.c - $(HOSTCC) $(CFLAGS) -c subs.c - $(MV) subs.o ksubs.o - -lex.o: lex.c gram.h - -kparse.c: a56.key keybld - ./keybld < a56.key > kparse.c - -gram.c gram.h: a56.y - @echo "[expect 2 shift/reduce conflicts here]" - $(YACC) -d a56.y - $(MV) $(YTABC) gram.c - $(MV) $(YTABH) gram.h - -toktab.c: gram.h - awk -f tok.awk < gram.h > toktab.c - -y.output: a56.y - $(YACC) -v a56.y - -toomf: toomf.o - $(CC) -o toomf $(CFLAGS) toomf.o - @$(POSTPROCESS) toomf - -torom: torom.o subs.o - $(CC) -o torom $(CFLAGS) torom.o subs.o - -tape: toktab.c - csh -c 'tar cvbf 1 - `cat files` | gzip > a56.tar.gz' - -main.o gram.o lex.o: a56.h - -clean: ; rm -f a56 toomf y.output *.o *.out tmp *.bak a56.tar.gz keybld - -spotless: clean - rm -f gram.c lexyy.c gram.h toktab.c kparse.c diff --git a/README b/README index 0a369be..b625458 100644 --- a/README +++ b/README @@ -69,7 +69,7 @@ enhancements. TO MAKE AND USE -Type "make". +Type "make -C src". The resulting program, a56, is used as follows: diff --git a/a56.1 b/a56.1 deleted file mode 100644 index 2ad66ba..0000000 --- a/a56.1 +++ /dev/null @@ -1,39 +0,0 @@ -.\" -.\" Copyright (C) 1990-1998 Quinn C. Jensen -.\" -.\" Permission to use, copy, modify, distribute, and sell this software -.\" and its documentation for any purpose is hereby granted without fee, -.\" provided that the above copyright notice appear in all copies and -.\" that both that copyright notice and this permission notice appear -.\" in supporting documentation. The author makes no representations -.\" about the suitability of this software for any purpose. It is -.\" provided "as is" without express or implied warranty. -.\" -.\" -.TH A56 1 "April 28, 2010" -.SH NAME -A56 \- Motorola DSP56001 assembler -.SH SYNOPSIS -.B a56 -[\fI\-b\fR] [\fI\-l\fR] [\fI\-o output\-file\fR] file [...] -.SH DESCRIPTION -This manual page documents briefly the -.B a56 -command. -.PP -a56 is an assembler for the Motorola DSP56001 family of microcontrollers. -It is capable of compiling the firmware used in Linux dsp56k.c driver. -.SH OPTIONS -.TP -\fB\-b\fR -Adds binary to the listing. -.TP -\fB\-l\fR -Causes included files to be listed. -.TP -\fB\-o\fR -Directs the output to the specified file rather than the default. -.SH AUTHORS -Copyright (C) 1990-1998 Quinn C. Jensen. -This manual page was written by Denis Briand , -for the Debian GNU/Linux system (but may be used by others). diff --git a/a56.h b/a56.h deleted file mode 100644 index 3415001..0000000 --- a/a56.h +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************\ - -/* - * Copyright (C) 2008 Robert Millan - * Copyright (C) 2012 Thorsten Alteholz - * - * 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 - * . - * - * 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 -#include -#include - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#define NOT ! -typedef int BOOL; -#endif - -struct sym { - char *name; - struct n { - short type; -#define UNDEF -1 -#define INT 0 -#define FLT 1 - short seg; -#define NONE 0 -#define PROG 1 -#define XDATA 2 -#define YDATA 3 -#define LDATA 4 -#define ANY 5 - union val { - int i; - double f; - } val; - } n; - struct sym *next; -} *find_sym(); - -extern int pass; - -#define NEW(object) ((object *)alloc(sizeof(object))) - -#define MAX_NEST 20 /* maximum include file nesting */ - -struct inc { - char *file; - FILE *fp; - int line; -}; -extern struct inc inc[]; -extern int inc_p; -#define curfile inc[inc_p].file -#define curline inc[inc_p].line - -extern int ldebug; - -struct psect { - char *name; - int seg; - unsigned int pc, bottom, top; - struct psect *next; -} *find_psect(), *new_psect(); - -FILE *open_read(), *open_write(), *open_append(); - - /* save string s somewhere */ -#define strsave(s) ((s) != NULL ? \ - (char *)strcpy((char *)malloc(strlen(s)+1),(s)) : NULL) - - /* after a call to fgets(), remove the newline character */ -#define rmcr(s) {if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0';}; - -#define ASSERT(expr, str) \ - if(expr) fprintf(stderr, "ASSERT: %s: line %d: %s\n", __FILE__, __LINE__, str); - -char *alloc (int size); -char *fixstring (char *s); diff --git a/a56.key b/a56.key deleted file mode 100644 index ae7c52b..0000000 --- a/a56.key +++ /dev/null @@ -1,193 +0,0 @@ -.code #include "a56.h" -.code #include "gram.h" -X: {return XMEM;} -Y: {return YMEM;} -L: {return LMEM;} -P: {return PMEM;} -A10 {return A10;} -A {return AAAA;} -B10 {return B10;} -B {return BBBB;} -AB {return AABB;} -BA {return BBAA;} -X {return XXXX;} -Y {return YYYY;} -SR {return SR;} -MR {return MR;} -CCR {return CCR;} -OMR {return OMR;} -SP {return SP;} -SSH {return SSH;} -SSL {return SSL;} -LA {return LA;} -LC {return LC;} -A0 {yylval.ival = 0; return AREG;} -A1 {yylval.ival = 1; return AREG;} -A2 {yylval.ival = 2; return AREG;} -B0 {yylval.ival = 0; return BREG;} -B1 {yylval.ival = 1; return BREG;} -B2 {yylval.ival = 2; return BREG;} -M0 {yylval.ival = 0; return MREG;} -M1 {yylval.ival = 1; return MREG;} -M2 {yylval.ival = 2; return MREG;} -M3 {yylval.ival = 3; return MREG;} -M4 {yylval.ival = 4; return MREG;} -M5 {yylval.ival = 5; return MREG;} -M6 {yylval.ival = 6; return MREG;} -M7 {yylval.ival = 7; return MREG;} -N0 {yylval.ival = 0; return NREG;} -N1 {yylval.ival = 1; return NREG;} -N2 {yylval.ival = 2; return NREG;} -N3 {yylval.ival = 3; return NREG;} -N4 {yylval.ival = 4; return NREG;} -N5 {yylval.ival = 5; return NREG;} -N6 {yylval.ival = 6; return NREG;} -N7 {yylval.ival = 7; return NREG;} -R0 {yylval.ival = 0; return RREG;} -R1 {yylval.ival = 1; return RREG;} -R2 {yylval.ival = 2; return RREG;} -R3 {yylval.ival = 3; return RREG;} -R4 {yylval.ival = 4; return RREG;} -R5 {yylval.ival = 5; return RREG;} -R6 {yylval.ival = 6; return RREG;} -R7 {yylval.ival = 7; return RREG;} -X0 {yylval.ival = 0; return XREG;} -X1 {yylval.ival = 1; return XREG;} -Y0 {yylval.ival = 0; return YREG;} -Y1 {yylval.ival = 1; return YREG;} -ABS {return OP_ABS;} -ADC {return OP_ADC;} -ADD {return OP_ADD;} -ADDL {return OP_ADDL;} -ADDR {return OP_ADDR;} -ASL {return OP_ASL;} -ASR {return OP_ASR;} -CLR {return OP_CLR;} -CMP {return OP_CMP;} -CMPM {return OP_CMPM;} -DIV {return OP_DIV;} -MAC {return OP_MAC;} -MACR {return OP_MACR;} -MPY {return OP_MPY;} -MPYR {return OP_MPYR;} -NEG {return OP_NEG;} -NORM {return OP_NORM;} -RND {return OP_RND;} -SBC {return OP_SBC;} -SUB {return OP_SUB;} -SUBL {return OP_SUBL;} -SUBR {return OP_SUBR;} -TCC {yylval.cond = 0x0; return OP_TCC;} -THS {yylval.cond = 0x0; return OP_TCC;} -TGE {yylval.cond = 0x1; return OP_TCC;} -TNE {yylval.cond = 0x2; return OP_TCC;} -TPL {yylval.cond = 0x3; return OP_TCC;} -TNN {yylval.cond = 0x4; return OP_TCC;} -TEC {yylval.cond = 0x5; return OP_TCC;} -TLC {yylval.cond = 0x6; return OP_TCC;} -TGT {yylval.cond = 0x7; return OP_TCC;} -TCS {yylval.cond = 0x8; return OP_TCC;} -TLO {yylval.cond = 0x8; return OP_TCC;} -TLT {yylval.cond = 0x9; return OP_TCC;} -TEQ {yylval.cond = 0xA; return OP_TCC;} -TMI {yylval.cond = 0xB; return OP_TCC;} -TNR {yylval.cond = 0xC; return OP_TCC;} -TES {yylval.cond = 0xD; return OP_TCC;} -TLS {yylval.cond = 0xE; return OP_TCC;} -TLE {yylval.cond = 0xF; return OP_TCC;} -TFR {return OP_TFR;} -TST {return OP_TST;} -AND {return OP_AND;} -ANDI {return OP_ANDI;} -EOR {return OP_EOR;} -LSL {return OP_LSL;} -LSR {return OP_LSR;} -NOT {return OP_NOT;} -OR {return OP_OR;} -ORI {return OP_ORI;} -ROL {return OP_ROL;} -ROR {return OP_ROR;} -BCLR {return OP_BCLR;} -BSET {return OP_BSET;} -BCHG {return OP_BCHG;} -BTST {return OP_BTST;} -DO {return OP_DO;} -ENDDO {return OP_ENDDO;} -LUA {return OP_LUA;} -MOVE {return OP_MOVE;} -MOVEC {return OP_MOVEC;} -MOVEM {return OP_MOVEM;} -MOVEP {return OP_MOVEP;} -INCLUDE {return OP_INCLUDE;} -ILLEGAL {return OP_ILLEGAL;} -JCC {yylval.cond = 0x0; return OP_JCC;} -JHS {yylval.cond = 0x0; return OP_JCC;} -JGE {yylval.cond = 0x1; return OP_JCC;} -JNE {yylval.cond = 0x2; return OP_JCC;} -JPL {yylval.cond = 0x3; return OP_JCC;} -JNN {yylval.cond = 0x4; return OP_JCC;} -JEC {yylval.cond = 0x5; return OP_JCC;} -JLC {yylval.cond = 0x6; return OP_JCC;} -JGT {yylval.cond = 0x7; return OP_JCC;} -JCS {yylval.cond = 0x8; return OP_JCC;} -JLO {yylval.cond = 0x8; return OP_JCC;} -JLT {yylval.cond = 0x9; return OP_JCC;} -JEQ {yylval.cond = 0xA; return OP_JCC;} -JMI {yylval.cond = 0xB; return OP_JCC;} -JNR {yylval.cond = 0xC; return OP_JCC;} -JES {yylval.cond = 0xD; return OP_JCC;} -JLS {yylval.cond = 0xE; return OP_JCC;} -JLE {yylval.cond = 0xF; return OP_JCC;} -JMP {return OP_JMP;} -JCLR {return OP_JCLR;} -JSET {return OP_JSET;} -JSCC {yylval.cond = 0x0; return OP_JSCC;} -JSHS {yylval.cond = 0x0; return OP_JSCC;} -JSGE {yylval.cond = 0x1; return OP_JSCC;} -JSNE {yylval.cond = 0x2; return OP_JSCC;} -JSPL {yylval.cond = 0x3; return OP_JSCC;} -JSNN {yylval.cond = 0x4; return OP_JSCC;} -JSEC {yylval.cond = 0x5; return OP_JSCC;} -JSLC {yylval.cond = 0x6; return OP_JSCC;} -JSGT {yylval.cond = 0x7; return OP_JSCC;} -JSCS {yylval.cond = 0x8; return OP_JSCC;} -JSLO {yylval.cond = 0x8; return OP_JSCC;} -JSLT {yylval.cond = 0x9; return OP_JSCC;} -JSEQ {yylval.cond = 0xA; return OP_JSCC;} -JSMI {yylval.cond = 0xB; return OP_JSCC;} -JSNR {yylval.cond = 0xC; return OP_JSCC;} -JSES {yylval.cond = 0xD; return OP_JSCC;} -JSLS {yylval.cond = 0xE; return OP_JSCC;} -JSLE {yylval.cond = 0xF; return OP_JSCC;} -JSR {return OP_JSR;} -JSCLR {return OP_JSCLR;} -JSSET {return OP_JSSET;} -NOP {return OP_NOP;} -REP {return OP_REP;} -RESET {return OP_RESET;} -RTI {return OP_RTI;} -RTS {return OP_RTS;} -STOP {return OP_STOP;} -SWI {return OP_SWI;} -WAIT {return OP_WAIT;} -EQU {return OP_EQU;} -ORG {return OP_ORG;} -DC {return OP_DC;} -DS {return OP_DS;} -DSM {return OP_DSM;} -INT {return OP_INT;} -END {return OP_END;} -PAGE {return OP_PAGE;} -PSECT {return OP_PSECT;} -ALIGN {return OP_ALIGN;} -PI {return OP_PI;} -SIN {return OP_SIN;} -COS {return OP_COS;} -TAN {return OP_TAN;} -ATAN {return OP_ATAN;} -ASIN {return OP_ASIN;} -ACOS {return OP_ACOS;} -EXP {return OP_EXP;} -LN {return OP_LN;} -LOG {return OP_LOG;} -POW {return OP_POW;} diff --git a/a56.y b/a56.y deleted file mode 100644 index 9c3399b..0000000 --- a/a56.y +++ /dev/null @@ -1,2114 +0,0 @@ -%{ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************/ - -/* - * Copyright (C) 1990-1994 Quinn C. Jensen - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. The author makes no representations - * about the suitability of this software for any purpose. It is - * provided "as is" without express or implied warranty. - * - */ - -/* - * a56.y - The YACC grammar for the assembler. - * - * Note: This module requires a "BIG" version of YACC. I had to - * recompile YACC in the largest mode available. - * - * Other notes: - * - * MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure - * out which form to use. - * - */ - -#include "a56.h" -#include - -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 CHEX CDEC FRAC -%token AREG BREG MREG NREG RREG XREG YREG -%token OP OPA OPP -%token OP_JCC OP_JSCC OP_TCC -%token SYM -%token STRING -%token 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 num num_or_sym -%type num_or_sym_expr -%type expr -%type ix -%type ix_long - -%type abs_addr abs_short_addr io_short_addr -%type a_b x_or_y ea b5_10111_max -%type p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12 -%type ea_short -%type prog_ctl_reg -%type op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8 -%type mpy_arg mpy_srcs plus_minus -%type sd3 -%type funky_ctl_reg tcc_sd space -%type opt_label - -%type regs -%type 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 = ""; - 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 -#include -#include - -int yydebug; - -struct n binary_op(a1, op, a2) -struct n a1, a2; -int op; -{ - struct n result; - int iarg1, iarg2; - double farg1, farg2; - - if(a1.type == UNDEF || a2.type == UNDEF) { - result.type = UNDEF; - return result; - } - - iarg1 = a1.type == INT ? a1.val.i : a1.val.f; - iarg2 = a2.type == INT ? a2.val.i : a2.val.f; - - farg1 = a1.type == INT ? a1.val.i : a1.val.f; - farg2 = a2.type == INT ? a2.val.i : a2.val.f; - - /* figure out target segment */ - - if(a1.seg == a2.seg) - result.seg = a1.seg; - else if(a1.seg == ANY) - result.seg = a2.seg; - else if(a2.seg == ANY) - result.seg = a1.seg; - else - result.seg = NONE; - - /* promote to float automatically */ - - if(a1.type != a2.type) { - if(a1.type == INT) { - a1.val.f = a1.val.i; /* truncate */ - a1.type = FLT; - } else { - a2.val.f = a2.val.i; /* truncate */ - } - } - result.type = a1.type; - - /* do the op */ - - switch(op) { - case '+': - if(result.type == INT) result.val.i = a1.val.i + a2.val.i; - else result.val.f = a1.val.f + a2.val.f; - break; - case '-': - if(result.type == INT) result.val.i = a1.val.i - a2.val.i; - else result.val.f = a1.val.f - a2.val.f; - break; - case '*': - if(result.type == INT) result.val.i = a1.val.i * a2.val.i; - else result.val.f = a1.val.f * a2.val.f; - break; - case '/': - if(result.type == INT) result.val.i = a1.val.i / a2.val.i; - else result.val.f = a1.val.f / a2.val.f; - break; - case '%': - result.val.i = iarg1 % iarg2; - result.type = INT; - break; - case SHL: - result.val.i = iarg1 << iarg2; - result.type = INT; - break; - case SHR: - result.val.i = iarg1 >> iarg2; - result.type = INT; - break; - case '|': - result.val.i = iarg1 | iarg2; - result.type = INT; - break; - case '&': - result.val.i = iarg1 & iarg2; - result.type = INT; - break; - case '^': - result.val.i = iarg1 ^ iarg2; - result.type = INT; - break; - case 'p': - result.val.f = pow(farg1, farg2); - result.type = FLT; - } - - return result; -} - -jmp_buf unary_env; - -void -sigfpu() -{ - longjmp(unary_env, 1); -} - -char *unary_name(op) -{ - switch(op) { - case 's': return "sin"; - case 'c': return "cos"; - case 't': return "tan"; - case 'S': return "asin"; - case 'C': return "acos"; - case 'T': return "atan"; - case 'e': return "exp"; - case 'l': return "ln"; - case 'L': return "log"; - case 'a': return "abs"; - } -} - -struct n unary_op(op, a1) -int op; -struct n a1; -{ - struct n result; - void (*orig)(); - double farg; - - if(a1.type == UNDEF) { - result.type = UNDEF; - return result; - } - - result.seg = a1.seg; - - /* do the op */ - - orig = signal(SIGFPE, sigfpu); - if(setjmp(unary_env)) { - yyerror("floating point exception in function %s", unary_name(op)); - result.val.i = result.val.f = 0; - } else { - farg = a1.type == INT ? (double)a1.val.i : a1.val.f; - switch(op) { - case '-': - result.type = a1.type; - if(a1.type == INT) result.val.i = -a1.val.i; - else result.val.f = -a1.val.f; - break; - case '~': - result.type = a1.type; - if(a1.type == INT) result.val.i = ~a1.val.i; - else result.val.f = ~(int)a1.val.f; - break; - case 'a': - result.type = a1.type; - if(a1.type == INT) result.val.i = a1.val.i < 0 ? -a1.val.i : a1.val.i; - else result.val.f = result.val.f = a1.val.f < 0 ? -a1.val.f : a1.val.f; - break; - case 's': - result.type = FLT; - result.val.f = sin(farg); - break; - case 'c': - result.type = FLT; - result.val.f = cos(farg); - break; - case 't': - result.type = FLT; - result.val.f = tan(farg); - break; - case 'S': - result.type = FLT; - result.val.f = asin(farg); - break; - case 'C': - result.type = FLT; - result.val.f = acos(farg); - break; - case 'T': - result.type = FLT; - result.val.f = atan(farg); - break; - case 'e': - result.type = FLT; - result.val.f = exp(farg); - break; - case 'l': - result.type = FLT; - result.val.f = log(farg); - break; - case 'L': - result.type = FLT; - result.val.f = log10(farg); - break; - } - } - signal(SIGFPE, orig); - - return result; -} - -n2int(n) -struct n n; -{ - if(n.type == UNDEF) - return UNDEF; - else if(n.type == INT) - return n.val.i; - else - return n.val.f; -} - -n2frac(n) -struct n n; -{ - double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f; - - if(n.type == UNDEF) - return UNDEF; - else if(n.type == INT) - return n.val.i; - else if(n.val.f == -1.0) - return 0x800000; - - adval -= (double)(int)adval; - adval *= (double)0x800000; - adval += 0.5; - - if(n.val.f >= 0.0) - return adval; - else - return -adval; -} - -extern struct {int n; char *name;} tok_tab[]; -extern int n_tok; - -char *tok_print(tok) -int tok; -{ - int i; - static char buf[32]; - - if(tok == '1') { - i = 1; - } - - if(tok < 256) { - sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF); - return buf; - } else { - for(i = 0; i < n_tok; i++) { - if(tok == tok_tab[i].n) - return tok_tab[i].name; - } - } - return "*bogus*"; -} - -yyerror(s, a0, a1, a2, a3) -char *s, *a0, *a1, *a2, *a3; -{ - extern int error; - char buf[1024]; - - error++; - sprintf(buf, s, a0, a1, a2, a3); - - if(pass == 2) { - fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - fprintf(stderr, "%s\n", cur_line); - printf("%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - } -} - -yywarning(s, a0, a1, a2, a3) -char *s, *a0, *a1, *a2, *a3; -{ - extern int warning; - char buf[1024]; - - warning++; - sprintf(buf, s, a0, a1, a2, a3); - - if(pass == 2) { - fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - fprintf(stderr, "%s\n", cur_line); - printf("%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - } -} - -char *luntab(s) -char *s; -{ - static char buf[1024]; - int p; - - strcpy(buf, s); - - untab(buf); - p = strlen(buf); - - if(buf[p - 1] == '\n') - buf[p - 1] = '\0'; - - return buf; -} diff --git a/frac2int.c b/frac2int.c deleted file mode 100644 index 8f01796..0000000 --- a/frac2int.c +++ /dev/null @@ -1,118 +0,0 @@ -#if 0 -+----------------------------------------------------------------------+ -| Question: My filter design package gives me decimal fractional | -| numbers as output for my FIR filter coefficients. | -| How do I convert these decimal fractions into the | -| DSP56200's format? | -+----------------------------------------------------------------------+ - - Answer: - It's fairly easy to convert decimal fractions into the - data format required by the DSP56200. The DSP56200 coeffi- - cients are represented as 24-bit signed, fractional, 2's - complement numbers as shown in Table 1. - - TABLE 1 - Representations for FIR Filter Coefficients - ----------------------------------------------------- - - Decimal Hexadecimal - Fraction 24-Bit Binary Value Coefficient - -------- ------------------- ---------- - - 0.75 0.1100000 00000000 00000000 60 00 00 - 0.5 0.1000000 00000000 00000000 40 00 00 - 0.25 0.0100000 00000000 00000000 20 00 00 - 0.125 0.0010000 00000000 00000000 10 00 00 - -0.125 1.1110000 00000000 00000000 F0 00 00 - -0.75 1.0100000 00000000 00000000 A0 00 00 - - Each 24-bit coefficient is separated into three bytes - corresponding to the high, middle, and low bytes. The high - byte is written to the DSP56200 at address 0A (hex), the - middle byte to address 0B (hex), and the low byte to address - 0C (hex). - - Conversion Procedure: - - Step 1: Multiply the decimal fraction by 8388608.0 (decimal). - Note that 8388608 = 2 raised to the 23rd power. - Step 2: Truncate or round the result into an integer. - Step 3: Logically AND this integer with 00FFFFFF (hex). - Step 4: Write the result to an output file as a hex integer. - - It is easy to write a program to perform this conversion on - a set of coefficients. If done by computer program, make - sure that all integer variables are represented with at - least 24-bits. An example of a short "C" program is - included at the end of this answer. - - Things to watch for: - - (1) Avoid letting a coefficient value be exactly 800000 - (-1.0 in a fractional system). If this coefficient - is multiplied by a data sample with value -1.0, the - result is -1.0 instead of +1.0 as expected. This is - because +1.0 cannot be represented in a signed, 2's - complement, fractional system. - - (2) The filter coefficients must be carefully selected - to prevent overflow. If there is a possibility of - overflow with a set of filter coefficients, then all - coefficients must be scaled by a constant value. The - DSP56200's 24-bit coefficients allow plenty of room - for scaling. If 12-bit input data samples are used - in a system, the potential for overflow is greatly - reduced if the samples are right justified and sign- - extended four bits before they are sent to the - DSP56200. - -"C" Program: -#endif - /****************************************\ - ** DECIMAL FRACTION TO HEX CONVERSION ** - \****************************************/ - -/******************************************************************\ -* This program converts one decimal, fractional number to a hex * -* number which can be written to the DSP56200's Coefficient RAM * -* Access registers. It prompts the user for a decimal fraction * -* and returns the corresponding hex number. * -* * -* Examples of Program Results (useful for checking programs) * -* Inputs Outputs * -* ------ ------- * -* 0.750 => 600000 * -* 0.500 => 400000 * -* 0.250 => 200000 * -* 0.125 => 100000 * -* -0.125 => f00000 * -* -0.750 => a00000 * -* 0.00784313678741455 => 010101 * -* -0.00784313678741455 => fefeff * -* * -* Note: The program assumes that the variable type "long" is an * -* integer which is at least 24-bits wide. * -* * -* Also: The DSP56200 cannot use any coefficient value with a * -* magnitude of 1.0 or larger. All coefficients must be * -* signed, fractional quantities. * -\******************************************************************/ - -main() -{ - double fractnum; /* double precision floating pt */ - long hexval; /* long integer */ - - for(;;) { - /* Read 1 Decimal Floating Point Number from the Keyboard */ - printf("Enter the decimal fraction: "); - scanf("%lf", &fractnum); - - /* Convert to a Hex Integer which can be used by the DSP56200 */ - hexval = (long) (8388608.0 * fractnum); - hexval = 0x00ffffffL & hexval; - - /* Write the Hex number out to the Terminal */ - printf("DSP56200 Coefficient = %06lx\n", hexval); - } -} diff --git a/getopt.c b/getopt.c deleted file mode 100644 index 6d74b39..0000000 --- a/getopt.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - I got this off net.sources from Henry Spencer. - It is a public domain getopt(3) like in System V. - I have made the following modifications: - - index(s,c) was added because too many people could - not compile getopt without it. - - A test main program was added, ifdeffed by GETOPT. - This main program is a public domain implementation - of the getopt(1) program like in System V. The getopt - program can be used to standardize shell option handling. - e.g. cc -DGETOPT getopt.c -o getopt -*/ -#include - -#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); - - -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 */ -} - - -#ifdef GETOPT - -#ifndef lint -static char sccspid[] = "@(#) getopt.c 5.1 (WangInst) 6/15/85"; -#endif - -main (argc, argv) char **argv; - { - char *optstring = argv[1]; - char *argv0 = argv[0]; - extern int optind; - extern char *optarg; - int opterr = 0; - int C; - char *opi; - if (argc == 1) - { - fprintf (stderr, "Usage: %s optstring args\n", argv0); - exit (1); - } - argv++; - argc--; - argv[0] = argv0; - while ((C = getopt (argc, argv, optstring)) != EOF) - { - if (C == BADCH) opterr++; - printf ("-%c ", C); - opi = index (optstring, C); - if (opi && opi[1] == ARGCH) - if (optarg) - printf ("\"%s\" ", optarg); - else opterr++; - } - printf ("%s", ENDARGS); - while (optind < argc) - printf (" \"%s\"", argv[optind++]); - putchar ('\n'); - exit (opterr); - } - -#endif diff --git a/keybld.1 b/keybld.1 deleted file mode 100644 index 758349c..0000000 --- a/keybld.1 +++ /dev/null @@ -1,24 +0,0 @@ -.\" -.\" Copyright (C) 1990-1998 Quinn C. Jensen -.\" -.\" Permission to use, copy, modify, distribute, and sell this software -.\" and its documentation for any purpose is hereby granted without fee, -.\" provided that the above copyright notice appear in all copies and -.\" that both that copyright notice and this permission notice appear -.\" in supporting documentation. The author makes no representations -.\" about the suitability of this software for any purpose. It is -.\" provided "as is" without express or implied warranty. -.\" -.\" -.TH A56-keybld 1 "November 26, 2012" -.SH NAME -a56-keybld \- Motorola DSP56001 assembler \- build finite-state parser -.SH SYNOPSIS -.B a56-keybld > output < input -.SH DESCRIPTION -.PP -builds a finite-state parser for the given keyword list in input file -.SH AUTHORS -Copyright (C) 1990-1998 Quinn C. Jensen. -This manual page was written by Thorsten Alteholz , -for the Debian GNU/Linux system (but may be used by others). diff --git a/keybld.c b/keybld.c deleted file mode 100644 index f3d6ce6..0000000 --- a/keybld.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 1990-1994 Quinn C. Jensen - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. The author makes no representations - * about the suitability of this software for any purpose. It is - * provided "as is" without express or implied warranty. - * - */ -static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; - -/* - * keybld - builds a finite-state parser for the given keyword list - * - */ - -#include -#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, ""); - - snew->seen = strsave(tmp); - - return snew; -} - -dump_machine() -{ - struct state *sp; - struct user_action *up; - int n, a; - - printf("/* state machine generated by keybld */\n"); - printf("/* states=%d actions=%d */\n", n_states, n_user_actions); - printf("/* %d bytes required for transition table storage */\n", - sizeof(short) * TRANSITIONS * n_states); - - printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS); - for(n = 0, sp = stop; sp; sp = sp->next, n++) { - printf(" /* state %d: \"%s\" */\n", n, sp->seen); - printf(" {"); - for(a = 0; a < TRANSITIONS; a++) { - struct trans *tp = sp->trans + a; - switch(tp->action) { - case GOTO: - printf("%d", ((struct state *)tp->arg)->number); - break; - case TERMINAL: - printf("%d", -(int)tp->arg - 1); - break; - case NOMATCH: - printf("0"); - break; - } - printf(",%s", a % 20 == 19 ? "\n\t\t" : ""); - }; - printf("},\n"); - } - - printf("};\n"); - - printf("\ -\n\ -kparse(kp)\n\ -char *kp;\n\ -{\n\ - int state = 0;\n\ -\n\ - for(;;) {\n\ - short transition = transitions[state][*kp];\n"); - -printf("\ - if(transition == 0) {\n\ - return 0;\n\ - } else if(transition > 0) {\n\ - kp++;\n\ - state = transition;\n\ - } else {\n\ - switch(-transition) {\n"); - - for(n = 1, up = utop; up; up = up->next, n++) { - printf("\ - case %d:\n\ - %s;\n\ - break;\n", n, up->action); - } - - printf("\ - }\n\ - return transition;\n\ - }\n\ - }\n\ -}\n"); - -} diff --git a/lex.c b/lex.c deleted file mode 100644 index 2f09a34..0000000 --- a/lex.c +++ /dev/null @@ -1,509 +0,0 @@ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************\ - -/* - * Copyright (C) 2012 Thorsten Alteholz - * - * 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 - * . - * - * 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("\n"); - return EOF; - break; - case '\0': - c = '\n'; - case '\n': - clp = NULL; - break; - default: - break; - } - - if(ldebug) - printf(c < ' ' ? "<\\z%02X>%s" : "<%c>", c, c == '\n' ? "\n" : ""); - - return c; -} diff --git a/main.c b/main.c deleted file mode 100644 index 2d6b759..0000000 --- a/main.c +++ /dev/null @@ -1,487 +0,0 @@ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************\ - -/* - * Copyright (C) 2008 Robert Millan - * Copyright (C) 2012 Thorsten Alteholz - * Copyright (C) 2014 Arthur Marble - * - * 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 - * . - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (C) 1990-1994 Quinn C. Jensen - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. The author makes no representations - * about the suitability of this software for any purpose. It is - * provided "as is" without express or implied warranty. - * - */ -static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; - -/* - * main.c - The "main" code for the assembler. - * - */ - -#include "a56.h" - -#define MAX 1024 - -int pass; -int error, warning; -extern unsigned int pc; -extern int seg; -BOOL binary_listing = FALSE; -BOOL list_includes = FALSE; -FILE *obj = NULL; -extern BOOL list_on; -BOOL list_on_next = TRUE; - -main(argc,argv) -int argc; -char *argv[]; -{ - int i; - extern char *optarg; - extern int optind; - int c; - char *output_file = "a56.out"; - char *input_file; - char *usage = "usage: a56 [-b] [-l] [-d] [-o output-file] input-file\n"; - - while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) { - case 'b': - binary_listing++; - break; - case 'l': - list_includes++; - break; - case 'd': - ldebug++; - break; - case 'o': - output_file = optarg; - break; - case '?': - default: - fatal(usage); - } - input_file = argv[optind++]; - if(input_file == NULL) fatal(usage); - obj = open_write(output_file); - - pc = 0; - seg = 0; - pass = 1; - reset_psects(); - include(input_file); - - pc = 0; - seg = 0; - pass = 2; - reset_psects(); - include(input_file); - - psect_summary(); - dump_symtab(); - fclose(obj); - printf("errors=%d\n", error); - printf("warnings=%d\n", warning); - return error ? 1 : 0; -} - -struct inc inc[MAX_NEST]; -int inc_p = 0; -FILE *yyin; - -include(file) -char *file; -{ - FILE *fp = open_read(file); - - inc_p++; - if(inc_p >= MAX_NEST) - fatal("%s: include nesting too deep\n", file); - - inc[inc_p].file = file; - inc[inc_p].fp = fp; - inc[inc_p].line = 1; - - list_on_next = TRUE; - if(inc_p > 1 && NOT list_includes) - list_on_next = FALSE; - - yyin = inc[inc_p].fp; - if(inc_p == 1) -#ifdef FLEX - { - static int started = 0; - if(started) - yyrestart(yyin); - else - started = 1; - yyparse(); - } -#else - yyparse(); -#endif -} - -yywrap() -{ - fclose(inc[inc_p].fp); - inc_p--; - list_on = list_on_next = TRUE; - if(inc_p > 1) - list_on = list_on_next = FALSE; - if(inc_p) { - yyin = inc[inc_p].fp; - return 0; - } else { - return 1; - } -} - -struct n -sym_ref(sym) /* return symbol value or UNDEF if not defined yet */ -char *sym; -{ - struct sym *sp, *find_sym(); - struct n result; - - result.type = UNDEF; - - sp = find_sym(sym); - if(NOT sp) { - if(pass == 2) { - yyerror("%s: undefined symbol", sym); - } - return result; - } - - return sp->n; -} - -#define HASHSIZE 128 - -#define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE) - -struct sym *symtab[HASHSIZE]; - -sym_def(sym, type, seg, i, f) -char *sym; -int type; -int seg; -int i; -double f; -{ - struct sym *sp, **stop, *find_sym(); - - if(pass == 1) { - if(find_sym(sym)) { - pass = 2; /* what a kludge */ - yyerror("%s: multiply defined symbol", sym); - pass = 1; - return 1; - } - stop = &symtab[HASH(sym)]; - sp = NEW(struct sym); - sp->next = *stop; - *stop = sp; - sp->name = strsave(sym); - sp->n.type = type; - sp->n.seg = seg; - if(type == INT) - sp->n.val.i = i & 0xFFFFFF; - else - sp->n.val.f = f; - } else { - sp = find_sym(sym); - if(NOT sp) - fatal("internal error 304\n"); - if(sp->n.type != type || - type == INT && sp->n.val.i != (i & 0xFFFFFF) || - type == FLT && sp->n.val.f != f) - yyerror("%s: assembler phase error", sym); - } -} - -struct sym *find_sym(sym) -char *sym; -{ - struct sym *sp, **stop; - - stop = &symtab[HASH(sym)]; - for(sp = *stop; sp; sp = sp->next) - if(strcmp(sp->name, sym) == 0) - return sp; - - return NULL; -} - -extern char segs[]; -dump_symtab() -{ - struct sym *sp, **stop; - int i; - - printf("\n\ -Symbol Table\n\ --------------------------------------\n"); -/* -SSSSSSSSSSSSSSSS S XXXXXX -SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD -*/ - - for(i = 0, stop = symtab; i < HASHSIZE; i++, stop++) { - for(sp = *stop; sp; sp = sp->next) { - if(sp->n.type == INT) { - printf("%16s %c %06X\n", sp->name, segs[sp->n.seg], sp->n.val.i); - fprintf(obj, "I %06X %s\n", sp->n.val.i, sp->name); - } else { - printf("%16s %c %.10f\n", sp->name, segs[sp->n.seg], sp->n.val.f); - fprintf(obj, "F %.10f %s\n", sp->n.val.f, sp->name); - } - } - } -} - -char *printcode(word) -int word; -{ - static char list[MAX], *lp; - int i; - - word &= 0xFFFFFF; - - if(binary_listing) { - sprintf(list, "%06X<", word); - for(i = 0, lp = &list[7]; i < 24; i++, lp++) { - *lp = word & 1 << 23 - i ? '1' : '0'; - if(i && i % 4 == 3) - *++lp = i % 8 == 7 ? ' ' : ','; - } - lp[-1] = '>'; - lp[0] = '\0'; - } else { - sprintf(list, "%06X", word); - } - return list; -} - -char *spacespace[2] = { -/*P:XXXX_XXXXXX_*/ - " ", -/*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/ - " "}; -char *spaces(n) -int n; -{ - return spacespace[binary_listing ? 1 : 0] + n; -} - -extern char segs[]; - -gencode(seg, pc, word) -int seg, pc, word; -{ - fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF); -} - -char fixbuf[1024]; - -char *fixstring(s) -char *s; -{ - char *bp = fixbuf; - int ival; - - while(*s) { - switch (*s) { - case '\'': - case '\"': - s++; - break; - case '\\': - switch (*++s) { - case 'b': *bp++ = '\b'; break; - case 'r': *bp++ = '\r'; break; - case 'f': *bp++ = '\f'; break; - case 'n': *bp++ = '\n'; break; - case 't': *bp++ = '\t'; break; - case '\\': *bp++ = '\\'; break; - case '0': - ival = 0; - while(*s >= '0' && *s <= '9') { - ival <<= 3; - ival += *s++ - '0'; - } - *bp++ = ival; - break; - } - break; - default: - *bp++ = *s++; - break; - } - } - *bp = '\0'; - return fixbuf; -} - -#define ONE 0x4000000 - -makefrac(s) -char *s; -{ - int frac = 0, div = 1; - int scale = 1; - - while(*s) { - switch(*s) { - case '-': - scale = -1; - break; - case '.': - div = 10; - break; - default: - frac += (*s - '0') * scale * ONE / div; - div *= 10; - break; - } - s++; - } - - return frac + scale * 4 >> 3 & 0xFFFFFF; -} - -/***************** psect stuff ************************/ - -struct psect *ptop = NULL, *cur_psect = NULL; - -reset_psects() -{ - struct psect *pp; - - for(pp = ptop; pp; pp = pp->next) { - pp->pc = pp->bottom; - } - - set_psect(NULL); -} - -psect_summary() -{ - printf("\nSummary of psect usage\n\n"); - - printf("\ - section seg base last top used avail total\n\ --------------------------------------------------------------------------\n"); -/* -SSSSSSSSSSSSSSSSSSSSSSSS X FFFF FFFF FFFF 99999 100% 99999 100% 99999 -*/ - - summarize(ptop); /* do it recursively to place back in order */ - printf("\n"); -} - -summarize(pp) -struct psect *pp; -{ - int used, avail, of; - - if(pp == NULL) - return 1; - - used = pp->pc - pp->bottom; - avail = pp->top - pp->pc; - of = pp->top - pp->bottom; - - summarize(pp->next); - - printf("%24.24s %c %04X %04X %04X %5d %3d%% %5d %3d%% %5d\n", - pp->name, segs[pp->seg], pp->bottom, pp->pc, pp->top, - used, of ? used * 100 / of : 0, avail, of ? avail * 100 / of : 0, - of); -} - -struct psect *find_psect(name) -char *name; -{ - struct psect *pp; - - for(pp = ptop; pp; pp = pp->next) - if(strcmp(pp->name, name) == 0) - return pp; - - return NULL; -} - -set_psect(pp) -struct psect *pp; -{ - cur_psect = pp; -} - -check_psect(seg, pc) -int seg; -unsigned int pc; -{ - if(cur_psect) { - if(seg == cur_psect->seg && pc >= cur_psect->bottom && - pc <= cur_psect->top) { - cur_psect->pc = pc; - return TRUE; - } else { - return FALSE; - } - } else { - return TRUE; - } -} - -struct psect *new_psect(name, seg, bottom, top) -char *name; -int seg; -unsigned int bottom, top; -{ - struct psect *pp = find_psect(name); - - if(NOT pp) { - pp = (struct psect *)alloc(sizeof *pp); - pp->next = ptop; - ptop = pp; - pp->name = strsave(name); - pp->seg = seg; - pp->pc = bottom; - } - pp->bottom = bottom; - pp->top = top; - - return pp; -} diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..b2294b3 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,146 @@ +####################################################### +# +# a56 - a DSP56001 assembler +# +# Written by Quinn C. Jensen +# July 1990 +# +####################################################### + +# Copyright (C) 2012 Thorsten Alteholz +# +# 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 +# . +# +# This file incorporates work covered by the following copyright and +# permission notice: +# +# Copyright (C) 1990-1998 Quinn C. Jensen +# +# Permission to use, copy, modify, distribute, and sell this +# software and its documentation for any purpose is hereby granted +# without fee, provided that the above copyright notice appear in all +# copies and that both that copyright notice and this permission +# notice appear in supporting documentation. The author makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied +# warranty. + +# environment definitions +# uncomment the ones you like + +# generic unix +CC = cc +HOSTCC = cc +YACC = yacc +CCDEFS = -DLDEBUG +MV = mv +YTABC = y.tab.c +YTABH = y.tab.h +POSTPROCESS = echo + +# gcc & bison +#CC = gcc +#HOSTCC = gcc +#YACC = bison -y +#CCDEFS = +#MV = mv +#YTABC = y.tab.c +#YTABH = y.tab.h +#POSTPROCESS = echo + +# Delorie's DOS gcc (from ftp://omnigate.clarkson.edu/pub/msdos/djgpp) +#CC = gcc +#HOSTCC = gcc +#YACC = bison -y +#CCDEFS = +#MV = ren +#YTABC = y_tab.c +#YTABH = y_tab.h +#POSTPROCESS = coff2exe + +# gcc cross-compile to go32 environment +#CC = i386-go32-gcc +#HOSTCC = cc +#YACC = yacc +#CCDEFS = +#MV = mv +#YTABC = y.tab.c +#YTABH = y.tab.h +#POSTPROCESS = echo + +####################################################### + +# -O or -g +#DEBUG = -O -Olimit 3000 +DEBUG = -O + +SRCS = main.c a56.y lex.c subs.c getopt.c kparse.key +OBJS = main.o gram.o lex.o toktab.o subs.o getopt.o kparse.o + +DEFINES = $(CCDEFS) +#DEFINES = -DYYDEBUG -DLDEBUG $(CCDEFS) + +CFLAGS = $(DEBUG) $(DEFINES) $(CPPFLAGS) $(LDFLAGS) + +all: keybld a56 toomf + +a56: $(OBJS) + $(CC) $(CFLAGS) -o a56 $(OBJS) -lm + @$(POSTPROCESS) a56 + +keybld: keybld.o ksubs.o + $(HOSTCC) $(CFLAGS) -o keybld keybld.o ksubs.o + @$(POSTPROCESS) keybld + +keybld.o: keybld.c + $(HOSTCC) $(CFLAGS) -c keybld.c + +ksubs.o: subs.c + $(HOSTCC) $(CFLAGS) -c subs.c + $(MV) subs.o ksubs.o + +lex.o: lex.c gram.h + +kparse.c: a56.key keybld + ./keybld < a56.key > kparse.c + +gram.c gram.h: a56.y + @echo "[expect 2 shift/reduce conflicts here]" + $(YACC) -d a56.y + $(MV) $(YTABC) gram.c + $(MV) $(YTABH) gram.h + +toktab.c: gram.h + awk -f tok.awk < gram.h > toktab.c + +y.output: a56.y + $(YACC) -v a56.y + +toomf: toomf.o + $(CC) -o toomf $(CFLAGS) toomf.o + @$(POSTPROCESS) toomf + +torom: torom.o subs.o + $(CC) -o torom $(CFLAGS) torom.o subs.o + +tape: toktab.c + csh -c 'tar cvbf 1 - `cat files` | gzip > a56.tar.gz' + +main.o gram.o lex.o: a56.h + +clean: ; rm -f a56 toomf y.output *.o *.out tmp *.bak a56.tar.gz keybld + +spotless: clean + rm -f gram.c lexyy.c gram.h toktab.c kparse.c diff --git a/src/a56.1 b/src/a56.1 new file mode 100644 index 0000000..2ad66ba --- /dev/null +++ b/src/a56.1 @@ -0,0 +1,39 @@ +.\" +.\" Copyright (C) 1990-1998 Quinn C. Jensen +.\" +.\" Permission to use, copy, modify, distribute, and sell this software +.\" and its documentation for any purpose is hereby granted without fee, +.\" provided that the above copyright notice appear in all copies and +.\" that both that copyright notice and this permission notice appear +.\" in supporting documentation. The author makes no representations +.\" about the suitability of this software for any purpose. It is +.\" provided "as is" without express or implied warranty. +.\" +.\" +.TH A56 1 "April 28, 2010" +.SH NAME +A56 \- Motorola DSP56001 assembler +.SH SYNOPSIS +.B a56 +[\fI\-b\fR] [\fI\-l\fR] [\fI\-o output\-file\fR] file [...] +.SH DESCRIPTION +This manual page documents briefly the +.B a56 +command. +.PP +a56 is an assembler for the Motorola DSP56001 family of microcontrollers. +It is capable of compiling the firmware used in Linux dsp56k.c driver. +.SH OPTIONS +.TP +\fB\-b\fR +Adds binary to the listing. +.TP +\fB\-l\fR +Causes included files to be listed. +.TP +\fB\-o\fR +Directs the output to the specified file rather than the default. +.SH AUTHORS +Copyright (C) 1990-1998 Quinn C. Jensen. +This manual page was written by Denis Briand , +for the Debian GNU/Linux system (but may be used by others). diff --git a/src/a56.h b/src/a56.h new file mode 100644 index 0000000..3415001 --- /dev/null +++ b/src/a56.h @@ -0,0 +1,119 @@ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************\ + +/* + * Copyright (C) 2008 Robert Millan + * Copyright (C) 2012 Thorsten Alteholz + * + * 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 + * . + * + * 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 +#include +#include + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#define NOT ! +typedef int BOOL; +#endif + +struct sym { + char *name; + struct n { + short type; +#define UNDEF -1 +#define INT 0 +#define FLT 1 + short seg; +#define NONE 0 +#define PROG 1 +#define XDATA 2 +#define YDATA 3 +#define LDATA 4 +#define ANY 5 + union val { + int i; + double f; + } val; + } n; + struct sym *next; +} *find_sym(); + +extern int pass; + +#define NEW(object) ((object *)alloc(sizeof(object))) + +#define MAX_NEST 20 /* maximum include file nesting */ + +struct inc { + char *file; + FILE *fp; + int line; +}; +extern struct inc inc[]; +extern int inc_p; +#define curfile inc[inc_p].file +#define curline inc[inc_p].line + +extern int ldebug; + +struct psect { + char *name; + int seg; + unsigned int pc, bottom, top; + struct psect *next; +} *find_psect(), *new_psect(); + +FILE *open_read(), *open_write(), *open_append(); + + /* save string s somewhere */ +#define strsave(s) ((s) != NULL ? \ + (char *)strcpy((char *)malloc(strlen(s)+1),(s)) : NULL) + + /* after a call to fgets(), remove the newline character */ +#define rmcr(s) {if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0';}; + +#define ASSERT(expr, str) \ + if(expr) fprintf(stderr, "ASSERT: %s: line %d: %s\n", __FILE__, __LINE__, str); + +char *alloc (int size); +char *fixstring (char *s); diff --git a/src/a56.key b/src/a56.key new file mode 100644 index 0000000..ae7c52b --- /dev/null +++ b/src/a56.key @@ -0,0 +1,193 @@ +.code #include "a56.h" +.code #include "gram.h" +X: {return XMEM;} +Y: {return YMEM;} +L: {return LMEM;} +P: {return PMEM;} +A10 {return A10;} +A {return AAAA;} +B10 {return B10;} +B {return BBBB;} +AB {return AABB;} +BA {return BBAA;} +X {return XXXX;} +Y {return YYYY;} +SR {return SR;} +MR {return MR;} +CCR {return CCR;} +OMR {return OMR;} +SP {return SP;} +SSH {return SSH;} +SSL {return SSL;} +LA {return LA;} +LC {return LC;} +A0 {yylval.ival = 0; return AREG;} +A1 {yylval.ival = 1; return AREG;} +A2 {yylval.ival = 2; return AREG;} +B0 {yylval.ival = 0; return BREG;} +B1 {yylval.ival = 1; return BREG;} +B2 {yylval.ival = 2; return BREG;} +M0 {yylval.ival = 0; return MREG;} +M1 {yylval.ival = 1; return MREG;} +M2 {yylval.ival = 2; return MREG;} +M3 {yylval.ival = 3; return MREG;} +M4 {yylval.ival = 4; return MREG;} +M5 {yylval.ival = 5; return MREG;} +M6 {yylval.ival = 6; return MREG;} +M7 {yylval.ival = 7; return MREG;} +N0 {yylval.ival = 0; return NREG;} +N1 {yylval.ival = 1; return NREG;} +N2 {yylval.ival = 2; return NREG;} +N3 {yylval.ival = 3; return NREG;} +N4 {yylval.ival = 4; return NREG;} +N5 {yylval.ival = 5; return NREG;} +N6 {yylval.ival = 6; return NREG;} +N7 {yylval.ival = 7; return NREG;} +R0 {yylval.ival = 0; return RREG;} +R1 {yylval.ival = 1; return RREG;} +R2 {yylval.ival = 2; return RREG;} +R3 {yylval.ival = 3; return RREG;} +R4 {yylval.ival = 4; return RREG;} +R5 {yylval.ival = 5; return RREG;} +R6 {yylval.ival = 6; return RREG;} +R7 {yylval.ival = 7; return RREG;} +X0 {yylval.ival = 0; return XREG;} +X1 {yylval.ival = 1; return XREG;} +Y0 {yylval.ival = 0; return YREG;} +Y1 {yylval.ival = 1; return YREG;} +ABS {return OP_ABS;} +ADC {return OP_ADC;} +ADD {return OP_ADD;} +ADDL {return OP_ADDL;} +ADDR {return OP_ADDR;} +ASL {return OP_ASL;} +ASR {return OP_ASR;} +CLR {return OP_CLR;} +CMP {return OP_CMP;} +CMPM {return OP_CMPM;} +DIV {return OP_DIV;} +MAC {return OP_MAC;} +MACR {return OP_MACR;} +MPY {return OP_MPY;} +MPYR {return OP_MPYR;} +NEG {return OP_NEG;} +NORM {return OP_NORM;} +RND {return OP_RND;} +SBC {return OP_SBC;} +SUB {return OP_SUB;} +SUBL {return OP_SUBL;} +SUBR {return OP_SUBR;} +TCC {yylval.cond = 0x0; return OP_TCC;} +THS {yylval.cond = 0x0; return OP_TCC;} +TGE {yylval.cond = 0x1; return OP_TCC;} +TNE {yylval.cond = 0x2; return OP_TCC;} +TPL {yylval.cond = 0x3; return OP_TCC;} +TNN {yylval.cond = 0x4; return OP_TCC;} +TEC {yylval.cond = 0x5; return OP_TCC;} +TLC {yylval.cond = 0x6; return OP_TCC;} +TGT {yylval.cond = 0x7; return OP_TCC;} +TCS {yylval.cond = 0x8; return OP_TCC;} +TLO {yylval.cond = 0x8; return OP_TCC;} +TLT {yylval.cond = 0x9; return OP_TCC;} +TEQ {yylval.cond = 0xA; return OP_TCC;} +TMI {yylval.cond = 0xB; return OP_TCC;} +TNR {yylval.cond = 0xC; return OP_TCC;} +TES {yylval.cond = 0xD; return OP_TCC;} +TLS {yylval.cond = 0xE; return OP_TCC;} +TLE {yylval.cond = 0xF; return OP_TCC;} +TFR {return OP_TFR;} +TST {return OP_TST;} +AND {return OP_AND;} +ANDI {return OP_ANDI;} +EOR {return OP_EOR;} +LSL {return OP_LSL;} +LSR {return OP_LSR;} +NOT {return OP_NOT;} +OR {return OP_OR;} +ORI {return OP_ORI;} +ROL {return OP_ROL;} +ROR {return OP_ROR;} +BCLR {return OP_BCLR;} +BSET {return OP_BSET;} +BCHG {return OP_BCHG;} +BTST {return OP_BTST;} +DO {return OP_DO;} +ENDDO {return OP_ENDDO;} +LUA {return OP_LUA;} +MOVE {return OP_MOVE;} +MOVEC {return OP_MOVEC;} +MOVEM {return OP_MOVEM;} +MOVEP {return OP_MOVEP;} +INCLUDE {return OP_INCLUDE;} +ILLEGAL {return OP_ILLEGAL;} +JCC {yylval.cond = 0x0; return OP_JCC;} +JHS {yylval.cond = 0x0; return OP_JCC;} +JGE {yylval.cond = 0x1; return OP_JCC;} +JNE {yylval.cond = 0x2; return OP_JCC;} +JPL {yylval.cond = 0x3; return OP_JCC;} +JNN {yylval.cond = 0x4; return OP_JCC;} +JEC {yylval.cond = 0x5; return OP_JCC;} +JLC {yylval.cond = 0x6; return OP_JCC;} +JGT {yylval.cond = 0x7; return OP_JCC;} +JCS {yylval.cond = 0x8; return OP_JCC;} +JLO {yylval.cond = 0x8; return OP_JCC;} +JLT {yylval.cond = 0x9; return OP_JCC;} +JEQ {yylval.cond = 0xA; return OP_JCC;} +JMI {yylval.cond = 0xB; return OP_JCC;} +JNR {yylval.cond = 0xC; return OP_JCC;} +JES {yylval.cond = 0xD; return OP_JCC;} +JLS {yylval.cond = 0xE; return OP_JCC;} +JLE {yylval.cond = 0xF; return OP_JCC;} +JMP {return OP_JMP;} +JCLR {return OP_JCLR;} +JSET {return OP_JSET;} +JSCC {yylval.cond = 0x0; return OP_JSCC;} +JSHS {yylval.cond = 0x0; return OP_JSCC;} +JSGE {yylval.cond = 0x1; return OP_JSCC;} +JSNE {yylval.cond = 0x2; return OP_JSCC;} +JSPL {yylval.cond = 0x3; return OP_JSCC;} +JSNN {yylval.cond = 0x4; return OP_JSCC;} +JSEC {yylval.cond = 0x5; return OP_JSCC;} +JSLC {yylval.cond = 0x6; return OP_JSCC;} +JSGT {yylval.cond = 0x7; return OP_JSCC;} +JSCS {yylval.cond = 0x8; return OP_JSCC;} +JSLO {yylval.cond = 0x8; return OP_JSCC;} +JSLT {yylval.cond = 0x9; return OP_JSCC;} +JSEQ {yylval.cond = 0xA; return OP_JSCC;} +JSMI {yylval.cond = 0xB; return OP_JSCC;} +JSNR {yylval.cond = 0xC; return OP_JSCC;} +JSES {yylval.cond = 0xD; return OP_JSCC;} +JSLS {yylval.cond = 0xE; return OP_JSCC;} +JSLE {yylval.cond = 0xF; return OP_JSCC;} +JSR {return OP_JSR;} +JSCLR {return OP_JSCLR;} +JSSET {return OP_JSSET;} +NOP {return OP_NOP;} +REP {return OP_REP;} +RESET {return OP_RESET;} +RTI {return OP_RTI;} +RTS {return OP_RTS;} +STOP {return OP_STOP;} +SWI {return OP_SWI;} +WAIT {return OP_WAIT;} +EQU {return OP_EQU;} +ORG {return OP_ORG;} +DC {return OP_DC;} +DS {return OP_DS;} +DSM {return OP_DSM;} +INT {return OP_INT;} +END {return OP_END;} +PAGE {return OP_PAGE;} +PSECT {return OP_PSECT;} +ALIGN {return OP_ALIGN;} +PI {return OP_PI;} +SIN {return OP_SIN;} +COS {return OP_COS;} +TAN {return OP_TAN;} +ATAN {return OP_ATAN;} +ASIN {return OP_ASIN;} +ACOS {return OP_ACOS;} +EXP {return OP_EXP;} +LN {return OP_LN;} +LOG {return OP_LOG;} +POW {return OP_POW;} diff --git a/src/a56.y b/src/a56.y new file mode 100644 index 0000000..9c3399b --- /dev/null +++ b/src/a56.y @@ -0,0 +1,2114 @@ +%{ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************/ + +/* + * Copyright (C) 1990-1994 Quinn C. Jensen + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. The author makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. + * + */ + +/* + * a56.y - The YACC grammar for the assembler. + * + * Note: This module requires a "BIG" version of YACC. I had to + * recompile YACC in the largest mode available. + * + * Other notes: + * + * MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure + * out which form to use. + * + */ + +#include "a56.h" +#include + +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 CHEX CDEC FRAC +%token AREG BREG MREG NREG RREG XREG YREG +%token OP OPA OPP +%token OP_JCC OP_JSCC OP_TCC +%token SYM +%token STRING +%token 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 num num_or_sym +%type num_or_sym_expr +%type expr +%type ix +%type ix_long + +%type abs_addr abs_short_addr io_short_addr +%type a_b x_or_y ea b5_10111_max +%type p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12 +%type ea_short +%type prog_ctl_reg +%type op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8 +%type mpy_arg mpy_srcs plus_minus +%type sd3 +%type funky_ctl_reg tcc_sd space +%type opt_label + +%type regs +%type 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 = ""; + 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 +#include +#include + +int yydebug; + +struct n binary_op(a1, op, a2) +struct n a1, a2; +int op; +{ + struct n result; + int iarg1, iarg2; + double farg1, farg2; + + if(a1.type == UNDEF || a2.type == UNDEF) { + result.type = UNDEF; + return result; + } + + iarg1 = a1.type == INT ? a1.val.i : a1.val.f; + iarg2 = a2.type == INT ? a2.val.i : a2.val.f; + + farg1 = a1.type == INT ? a1.val.i : a1.val.f; + farg2 = a2.type == INT ? a2.val.i : a2.val.f; + + /* figure out target segment */ + + if(a1.seg == a2.seg) + result.seg = a1.seg; + else if(a1.seg == ANY) + result.seg = a2.seg; + else if(a2.seg == ANY) + result.seg = a1.seg; + else + result.seg = NONE; + + /* promote to float automatically */ + + if(a1.type != a2.type) { + if(a1.type == INT) { + a1.val.f = a1.val.i; /* truncate */ + a1.type = FLT; + } else { + a2.val.f = a2.val.i; /* truncate */ + } + } + result.type = a1.type; + + /* do the op */ + + switch(op) { + case '+': + if(result.type == INT) result.val.i = a1.val.i + a2.val.i; + else result.val.f = a1.val.f + a2.val.f; + break; + case '-': + if(result.type == INT) result.val.i = a1.val.i - a2.val.i; + else result.val.f = a1.val.f - a2.val.f; + break; + case '*': + if(result.type == INT) result.val.i = a1.val.i * a2.val.i; + else result.val.f = a1.val.f * a2.val.f; + break; + case '/': + if(result.type == INT) result.val.i = a1.val.i / a2.val.i; + else result.val.f = a1.val.f / a2.val.f; + break; + case '%': + result.val.i = iarg1 % iarg2; + result.type = INT; + break; + case SHL: + result.val.i = iarg1 << iarg2; + result.type = INT; + break; + case SHR: + result.val.i = iarg1 >> iarg2; + result.type = INT; + break; + case '|': + result.val.i = iarg1 | iarg2; + result.type = INT; + break; + case '&': + result.val.i = iarg1 & iarg2; + result.type = INT; + break; + case '^': + result.val.i = iarg1 ^ iarg2; + result.type = INT; + break; + case 'p': + result.val.f = pow(farg1, farg2); + result.type = FLT; + } + + return result; +} + +jmp_buf unary_env; + +void +sigfpu() +{ + longjmp(unary_env, 1); +} + +char *unary_name(op) +{ + switch(op) { + case 's': return "sin"; + case 'c': return "cos"; + case 't': return "tan"; + case 'S': return "asin"; + case 'C': return "acos"; + case 'T': return "atan"; + case 'e': return "exp"; + case 'l': return "ln"; + case 'L': return "log"; + case 'a': return "abs"; + } +} + +struct n unary_op(op, a1) +int op; +struct n a1; +{ + struct n result; + void (*orig)(); + double farg; + + if(a1.type == UNDEF) { + result.type = UNDEF; + return result; + } + + result.seg = a1.seg; + + /* do the op */ + + orig = signal(SIGFPE, sigfpu); + if(setjmp(unary_env)) { + yyerror("floating point exception in function %s", unary_name(op)); + result.val.i = result.val.f = 0; + } else { + farg = a1.type == INT ? (double)a1.val.i : a1.val.f; + switch(op) { + case '-': + result.type = a1.type; + if(a1.type == INT) result.val.i = -a1.val.i; + else result.val.f = -a1.val.f; + break; + case '~': + result.type = a1.type; + if(a1.type == INT) result.val.i = ~a1.val.i; + else result.val.f = ~(int)a1.val.f; + break; + case 'a': + result.type = a1.type; + if(a1.type == INT) result.val.i = a1.val.i < 0 ? -a1.val.i : a1.val.i; + else result.val.f = result.val.f = a1.val.f < 0 ? -a1.val.f : a1.val.f; + break; + case 's': + result.type = FLT; + result.val.f = sin(farg); + break; + case 'c': + result.type = FLT; + result.val.f = cos(farg); + break; + case 't': + result.type = FLT; + result.val.f = tan(farg); + break; + case 'S': + result.type = FLT; + result.val.f = asin(farg); + break; + case 'C': + result.type = FLT; + result.val.f = acos(farg); + break; + case 'T': + result.type = FLT; + result.val.f = atan(farg); + break; + case 'e': + result.type = FLT; + result.val.f = exp(farg); + break; + case 'l': + result.type = FLT; + result.val.f = log(farg); + break; + case 'L': + result.type = FLT; + result.val.f = log10(farg); + break; + } + } + signal(SIGFPE, orig); + + return result; +} + +n2int(n) +struct n n; +{ + if(n.type == UNDEF) + return UNDEF; + else if(n.type == INT) + return n.val.i; + else + return n.val.f; +} + +n2frac(n) +struct n n; +{ + double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f; + + if(n.type == UNDEF) + return UNDEF; + else if(n.type == INT) + return n.val.i; + else if(n.val.f == -1.0) + return 0x800000; + + adval -= (double)(int)adval; + adval *= (double)0x800000; + adval += 0.5; + + if(n.val.f >= 0.0) + return adval; + else + return -adval; +} + +extern struct {int n; char *name;} tok_tab[]; +extern int n_tok; + +char *tok_print(tok) +int tok; +{ + int i; + static char buf[32]; + + if(tok == '1') { + i = 1; + } + + if(tok < 256) { + sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF); + return buf; + } else { + for(i = 0; i < n_tok; i++) { + if(tok == tok_tab[i].n) + return tok_tab[i].name; + } + } + return "*bogus*"; +} + +yyerror(s, a0, a1, a2, a3) +char *s, *a0, *a1, *a2, *a3; +{ + extern int error; + char buf[1024]; + + error++; + sprintf(buf, s, a0, a1, a2, a3); + + if(pass == 2) { + fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, + buf, tok_print(yychar)); + fprintf(stderr, "%s\n", cur_line); + printf("%s: line %d: %s (tok=%s)\n", curfile, curline, + buf, tok_print(yychar)); + } +} + +yywarning(s, a0, a1, a2, a3) +char *s, *a0, *a1, *a2, *a3; +{ + extern int warning; + char buf[1024]; + + warning++; + sprintf(buf, s, a0, a1, a2, a3); + + if(pass == 2) { + fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, + buf, tok_print(yychar)); + fprintf(stderr, "%s\n", cur_line); + printf("%s: line %d: %s (tok=%s)\n", curfile, curline, + buf, tok_print(yychar)); + } +} + +char *luntab(s) +char *s; +{ + static char buf[1024]; + int p; + + strcpy(buf, s); + + untab(buf); + p = strlen(buf); + + if(buf[p - 1] == '\n') + buf[p - 1] = '\0'; + + return buf; +} diff --git a/src/frac2int.c b/src/frac2int.c new file mode 100644 index 0000000..8f01796 --- /dev/null +++ b/src/frac2int.c @@ -0,0 +1,118 @@ +#if 0 ++----------------------------------------------------------------------+ +| Question: My filter design package gives me decimal fractional | +| numbers as output for my FIR filter coefficients. | +| How do I convert these decimal fractions into the | +| DSP56200's format? | ++----------------------------------------------------------------------+ + + Answer: + It's fairly easy to convert decimal fractions into the + data format required by the DSP56200. The DSP56200 coeffi- + cients are represented as 24-bit signed, fractional, 2's + complement numbers as shown in Table 1. + + TABLE 1 - Representations for FIR Filter Coefficients + ----------------------------------------------------- + + Decimal Hexadecimal + Fraction 24-Bit Binary Value Coefficient + -------- ------------------- ---------- + + 0.75 0.1100000 00000000 00000000 60 00 00 + 0.5 0.1000000 00000000 00000000 40 00 00 + 0.25 0.0100000 00000000 00000000 20 00 00 + 0.125 0.0010000 00000000 00000000 10 00 00 + -0.125 1.1110000 00000000 00000000 F0 00 00 + -0.75 1.0100000 00000000 00000000 A0 00 00 + + Each 24-bit coefficient is separated into three bytes + corresponding to the high, middle, and low bytes. The high + byte is written to the DSP56200 at address 0A (hex), the + middle byte to address 0B (hex), and the low byte to address + 0C (hex). + + Conversion Procedure: + + Step 1: Multiply the decimal fraction by 8388608.0 (decimal). + Note that 8388608 = 2 raised to the 23rd power. + Step 2: Truncate or round the result into an integer. + Step 3: Logically AND this integer with 00FFFFFF (hex). + Step 4: Write the result to an output file as a hex integer. + + It is easy to write a program to perform this conversion on + a set of coefficients. If done by computer program, make + sure that all integer variables are represented with at + least 24-bits. An example of a short "C" program is + included at the end of this answer. + + Things to watch for: + + (1) Avoid letting a coefficient value be exactly 800000 + (-1.0 in a fractional system). If this coefficient + is multiplied by a data sample with value -1.0, the + result is -1.0 instead of +1.0 as expected. This is + because +1.0 cannot be represented in a signed, 2's + complement, fractional system. + + (2) The filter coefficients must be carefully selected + to prevent overflow. If there is a possibility of + overflow with a set of filter coefficients, then all + coefficients must be scaled by a constant value. The + DSP56200's 24-bit coefficients allow plenty of room + for scaling. If 12-bit input data samples are used + in a system, the potential for overflow is greatly + reduced if the samples are right justified and sign- + extended four bits before they are sent to the + DSP56200. + +"C" Program: +#endif + /****************************************\ + ** DECIMAL FRACTION TO HEX CONVERSION ** + \****************************************/ + +/******************************************************************\ +* This program converts one decimal, fractional number to a hex * +* number which can be written to the DSP56200's Coefficient RAM * +* Access registers. It prompts the user for a decimal fraction * +* and returns the corresponding hex number. * +* * +* Examples of Program Results (useful for checking programs) * +* Inputs Outputs * +* ------ ------- * +* 0.750 => 600000 * +* 0.500 => 400000 * +* 0.250 => 200000 * +* 0.125 => 100000 * +* -0.125 => f00000 * +* -0.750 => a00000 * +* 0.00784313678741455 => 010101 * +* -0.00784313678741455 => fefeff * +* * +* Note: The program assumes that the variable type "long" is an * +* integer which is at least 24-bits wide. * +* * +* Also: The DSP56200 cannot use any coefficient value with a * +* magnitude of 1.0 or larger. All coefficients must be * +* signed, fractional quantities. * +\******************************************************************/ + +main() +{ + double fractnum; /* double precision floating pt */ + long hexval; /* long integer */ + + for(;;) { + /* Read 1 Decimal Floating Point Number from the Keyboard */ + printf("Enter the decimal fraction: "); + scanf("%lf", &fractnum); + + /* Convert to a Hex Integer which can be used by the DSP56200 */ + hexval = (long) (8388608.0 * fractnum); + hexval = 0x00ffffffL & hexval; + + /* Write the Hex number out to the Terminal */ + printf("DSP56200 Coefficient = %06lx\n", hexval); + } +} diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 0000000..6d74b39 --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,129 @@ +/* + 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 + +#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); + + +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 */ +} + + +#ifdef GETOPT + +#ifndef lint +static char sccspid[] = "@(#) getopt.c 5.1 (WangInst) 6/15/85"; +#endif + +main (argc, argv) char **argv; + { + char *optstring = argv[1]; + char *argv0 = argv[0]; + extern int optind; + extern char *optarg; + int opterr = 0; + int C; + char *opi; + if (argc == 1) + { + fprintf (stderr, "Usage: %s optstring args\n", argv0); + exit (1); + } + argv++; + argc--; + argv[0] = argv0; + while ((C = getopt (argc, argv, optstring)) != EOF) + { + if (C == BADCH) opterr++; + printf ("-%c ", C); + opi = index (optstring, C); + if (opi && opi[1] == ARGCH) + if (optarg) + printf ("\"%s\" ", optarg); + else opterr++; + } + printf ("%s", ENDARGS); + while (optind < argc) + printf (" \"%s\"", argv[optind++]); + putchar ('\n'); + exit (opterr); + } + +#endif diff --git a/src/keybld.1 b/src/keybld.1 new file mode 100644 index 0000000..758349c --- /dev/null +++ b/src/keybld.1 @@ -0,0 +1,24 @@ +.\" +.\" 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 , +for the Debian GNU/Linux system (but may be used by others). diff --git a/src/keybld.c b/src/keybld.c new file mode 100644 index 0000000..f3d6ce6 --- /dev/null +++ b/src/keybld.c @@ -0,0 +1,231 @@ +/* + * 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 +#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, ""); + + snew->seen = strsave(tmp); + + return snew; +} + +dump_machine() +{ + struct state *sp; + struct user_action *up; + int n, a; + + printf("/* state machine generated by keybld */\n"); + printf("/* states=%d actions=%d */\n", n_states, n_user_actions); + printf("/* %d bytes required for transition table storage */\n", + sizeof(short) * TRANSITIONS * n_states); + + printf("short transitions[%d][%d] = {\n", n_states, TRANSITIONS); + for(n = 0, sp = stop; sp; sp = sp->next, n++) { + printf(" /* state %d: \"%s\" */\n", n, sp->seen); + printf(" {"); + for(a = 0; a < TRANSITIONS; a++) { + struct trans *tp = sp->trans + a; + switch(tp->action) { + case GOTO: + printf("%d", ((struct state *)tp->arg)->number); + break; + case TERMINAL: + printf("%d", -(int)tp->arg - 1); + break; + case NOMATCH: + printf("0"); + break; + } + printf(",%s", a % 20 == 19 ? "\n\t\t" : ""); + }; + printf("},\n"); + } + + printf("};\n"); + + printf("\ +\n\ +kparse(kp)\n\ +char *kp;\n\ +{\n\ + int state = 0;\n\ +\n\ + for(;;) {\n\ + short transition = transitions[state][*kp];\n"); + +printf("\ + if(transition == 0) {\n\ + return 0;\n\ + } else if(transition > 0) {\n\ + kp++;\n\ + state = transition;\n\ + } else {\n\ + switch(-transition) {\n"); + + for(n = 1, up = utop; up; up = up->next, n++) { + printf("\ + case %d:\n\ + %s;\n\ + break;\n", n, up->action); + } + + printf("\ + }\n\ + return transition;\n\ + }\n\ + }\n\ +}\n"); + +} diff --git a/src/lex.c b/src/lex.c new file mode 100644 index 0000000..2f09a34 --- /dev/null +++ b/src/lex.c @@ -0,0 +1,509 @@ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************\ + +/* + * Copyright (C) 2012 Thorsten Alteholz + * + * 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 + * . + * + * 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("\n"); + return EOF; + break; + case '\0': + c = '\n'; + case '\n': + clp = NULL; + break; + default: + break; + } + + if(ldebug) + printf(c < ' ' ? "<\\z%02X>%s" : "<%c>", c, c == '\n' ? "\n" : ""); + + return c; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..2d6b759 --- /dev/null +++ b/src/main.c @@ -0,0 +1,487 @@ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************\ + +/* + * Copyright (C) 2008 Robert Millan + * Copyright (C) 2012 Thorsten Alteholz + * Copyright (C) 2014 Arthur Marble + * + * 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 + * . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (C) 1990-1994 Quinn C. Jensen + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. The author makes no representations + * about the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. + * + */ +static char *Copyright = "Copyright (C) 1990-1994 Quinn C. Jensen"; + +/* + * main.c - The "main" code for the assembler. + * + */ + +#include "a56.h" + +#define MAX 1024 + +int pass; +int error, warning; +extern unsigned int pc; +extern int seg; +BOOL binary_listing = FALSE; +BOOL list_includes = FALSE; +FILE *obj = NULL; +extern BOOL list_on; +BOOL list_on_next = TRUE; + +main(argc,argv) +int argc; +char *argv[]; +{ + int i; + extern char *optarg; + extern int optind; + int c; + char *output_file = "a56.out"; + char *input_file; + char *usage = "usage: a56 [-b] [-l] [-d] [-o output-file] input-file\n"; + + while((c = getopt(argc, argv, "bldo:")) != EOF) switch (c) { + case 'b': + binary_listing++; + break; + case 'l': + list_includes++; + break; + case 'd': + ldebug++; + break; + case 'o': + output_file = optarg; + break; + case '?': + default: + fatal(usage); + } + input_file = argv[optind++]; + if(input_file == NULL) fatal(usage); + obj = open_write(output_file); + + pc = 0; + seg = 0; + pass = 1; + reset_psects(); + include(input_file); + + pc = 0; + seg = 0; + pass = 2; + reset_psects(); + include(input_file); + + psect_summary(); + dump_symtab(); + fclose(obj); + printf("errors=%d\n", error); + printf("warnings=%d\n", warning); + return error ? 1 : 0; +} + +struct inc inc[MAX_NEST]; +int inc_p = 0; +FILE *yyin; + +include(file) +char *file; +{ + FILE *fp = open_read(file); + + inc_p++; + if(inc_p >= MAX_NEST) + fatal("%s: include nesting too deep\n", file); + + inc[inc_p].file = file; + inc[inc_p].fp = fp; + inc[inc_p].line = 1; + + list_on_next = TRUE; + if(inc_p > 1 && NOT list_includes) + list_on_next = FALSE; + + yyin = inc[inc_p].fp; + if(inc_p == 1) +#ifdef FLEX + { + static int started = 0; + if(started) + yyrestart(yyin); + else + started = 1; + yyparse(); + } +#else + yyparse(); +#endif +} + +yywrap() +{ + fclose(inc[inc_p].fp); + inc_p--; + list_on = list_on_next = TRUE; + if(inc_p > 1) + list_on = list_on_next = FALSE; + if(inc_p) { + yyin = inc[inc_p].fp; + return 0; + } else { + return 1; + } +} + +struct n +sym_ref(sym) /* return symbol value or UNDEF if not defined yet */ +char *sym; +{ + struct sym *sp, *find_sym(); + struct n result; + + result.type = UNDEF; + + sp = find_sym(sym); + if(NOT sp) { + if(pass == 2) { + yyerror("%s: undefined symbol", sym); + } + return result; + } + + return sp->n; +} + +#define HASHSIZE 128 + +#define HASH(sym) (((sym)[0] ^ sym[1]) % HASHSIZE) + +struct sym *symtab[HASHSIZE]; + +sym_def(sym, type, seg, i, f) +char *sym; +int type; +int seg; +int i; +double f; +{ + struct sym *sp, **stop, *find_sym(); + + if(pass == 1) { + if(find_sym(sym)) { + pass = 2; /* what a kludge */ + yyerror("%s: multiply defined symbol", sym); + pass = 1; + return 1; + } + stop = &symtab[HASH(sym)]; + sp = NEW(struct sym); + sp->next = *stop; + *stop = sp; + sp->name = strsave(sym); + sp->n.type = type; + sp->n.seg = seg; + if(type == INT) + sp->n.val.i = i & 0xFFFFFF; + else + sp->n.val.f = f; + } else { + sp = find_sym(sym); + if(NOT sp) + fatal("internal error 304\n"); + if(sp->n.type != type || + type == INT && sp->n.val.i != (i & 0xFFFFFF) || + type == FLT && sp->n.val.f != f) + yyerror("%s: assembler phase error", sym); + } +} + +struct sym *find_sym(sym) +char *sym; +{ + struct sym *sp, **stop; + + stop = &symtab[HASH(sym)]; + for(sp = *stop; sp; sp = sp->next) + if(strcmp(sp->name, sym) == 0) + return sp; + + return NULL; +} + +extern char segs[]; +dump_symtab() +{ + struct sym *sp, **stop; + int i; + + printf("\n\ +Symbol Table\n\ +-------------------------------------\n"); +/* +SSSSSSSSSSSSSSSS S XXXXXX +SSSSSSSSSSSSSSSS S DDDDDDDDD.DDDDDDDDDD +*/ + + for(i = 0, stop = symtab; i < HASHSIZE; i++, stop++) { + for(sp = *stop; sp; sp = sp->next) { + if(sp->n.type == INT) { + printf("%16s %c %06X\n", sp->name, segs[sp->n.seg], sp->n.val.i); + fprintf(obj, "I %06X %s\n", sp->n.val.i, sp->name); + } else { + printf("%16s %c %.10f\n", sp->name, segs[sp->n.seg], sp->n.val.f); + fprintf(obj, "F %.10f %s\n", sp->n.val.f, sp->name); + } + } + } +} + +char *printcode(word) +int word; +{ + static char list[MAX], *lp; + int i; + + word &= 0xFFFFFF; + + if(binary_listing) { + sprintf(list, "%06X<", word); + for(i = 0, lp = &list[7]; i < 24; i++, lp++) { + *lp = word & 1 << 23 - i ? '1' : '0'; + if(i && i % 4 == 3) + *++lp = i % 8 == 7 ? ' ' : ','; + } + lp[-1] = '>'; + lp[0] = '\0'; + } else { + sprintf(list, "%06X", word); + } + return list; +} + +char *spacespace[2] = { +/*P:XXXX_XXXXXX_*/ + " ", +/*P:XXXX_XXXXXX(XXXX_XXXX_XXXX_XXXX_XXXX_XXXX)_*/ + " "}; +char *spaces(n) +int n; +{ + return spacespace[binary_listing ? 1 : 0] + n; +} + +extern char segs[]; + +gencode(seg, pc, word) +int seg, pc, word; +{ + fprintf(obj, "%c %04X %06X\n", segs[seg], pc, word & 0xFFFFFF); +} + +char fixbuf[1024]; + +char *fixstring(s) +char *s; +{ + char *bp = fixbuf; + int ival; + + while(*s) { + switch (*s) { + case '\'': + case '\"': + s++; + break; + case '\\': + switch (*++s) { + case 'b': *bp++ = '\b'; break; + case 'r': *bp++ = '\r'; break; + case 'f': *bp++ = '\f'; break; + case 'n': *bp++ = '\n'; break; + case 't': *bp++ = '\t'; break; + case '\\': *bp++ = '\\'; break; + case '0': + ival = 0; + while(*s >= '0' && *s <= '9') { + ival <<= 3; + ival += *s++ - '0'; + } + *bp++ = ival; + break; + } + break; + default: + *bp++ = *s++; + break; + } + } + *bp = '\0'; + return fixbuf; +} + +#define ONE 0x4000000 + +makefrac(s) +char *s; +{ + int frac = 0, div = 1; + int scale = 1; + + while(*s) { + switch(*s) { + case '-': + scale = -1; + break; + case '.': + div = 10; + break; + default: + frac += (*s - '0') * scale * ONE / div; + div *= 10; + break; + } + s++; + } + + return frac + scale * 4 >> 3 & 0xFFFFFF; +} + +/***************** psect stuff ************************/ + +struct psect *ptop = NULL, *cur_psect = NULL; + +reset_psects() +{ + struct psect *pp; + + for(pp = ptop; pp; pp = pp->next) { + pp->pc = pp->bottom; + } + + set_psect(NULL); +} + +psect_summary() +{ + printf("\nSummary of psect usage\n\n"); + + printf("\ + section seg base last top used avail total\n\ +-------------------------------------------------------------------------\n"); +/* +SSSSSSSSSSSSSSSSSSSSSSSS X FFFF FFFF FFFF 99999 100% 99999 100% 99999 +*/ + + summarize(ptop); /* do it recursively to place back in order */ + printf("\n"); +} + +summarize(pp) +struct psect *pp; +{ + int used, avail, of; + + if(pp == NULL) + return 1; + + used = pp->pc - pp->bottom; + avail = pp->top - pp->pc; + of = pp->top - pp->bottom; + + summarize(pp->next); + + printf("%24.24s %c %04X %04X %04X %5d %3d%% %5d %3d%% %5d\n", + pp->name, segs[pp->seg], pp->bottom, pp->pc, pp->top, + used, of ? used * 100 / of : 0, avail, of ? avail * 100 / of : 0, + of); +} + +struct psect *find_psect(name) +char *name; +{ + struct psect *pp; + + for(pp = ptop; pp; pp = pp->next) + if(strcmp(pp->name, name) == 0) + return pp; + + return NULL; +} + +set_psect(pp) +struct psect *pp; +{ + cur_psect = pp; +} + +check_psect(seg, pc) +int seg; +unsigned int pc; +{ + if(cur_psect) { + if(seg == cur_psect->seg && pc >= cur_psect->bottom && + pc <= cur_psect->top) { + cur_psect->pc = pc; + return TRUE; + } else { + return FALSE; + } + } else { + return TRUE; + } +} + +struct psect *new_psect(name, seg, bottom, top) +char *name; +int seg; +unsigned int bottom, top; +{ + struct psect *pp = find_psect(name); + + if(NOT pp) { + pp = (struct psect *)alloc(sizeof *pp); + pp->next = ptop; + ptop = pp; + pp->name = strsave(name); + pp->seg = seg; + pp->pc = bottom; + } + pp->bottom = bottom; + pp->top = top; + + return pp; +} diff --git a/src/subs.c b/src/subs.c new file mode 100644 index 0000000..5166717 --- /dev/null +++ b/src/subs.c @@ -0,0 +1,183 @@ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************\ + +/* + * Copyright (C) 2008 Robert Millan + * Copyright (C) 2012 Thorsten Alteholz + * + * 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 + * . + * + * 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; +} diff --git a/src/tok.awk b/src/tok.awk new file mode 100644 index 0000000..44e02aa --- /dev/null +++ b/src/tok.awk @@ -0,0 +1,4 @@ +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");} diff --git a/src/toktab.c b/src/toktab.c new file mode 100644 index 0000000..e70ea14 --- /dev/null +++ b/src/toktab.c @@ -0,0 +1,131 @@ +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; diff --git a/src/toomf.c b/src/toomf.c new file mode 100644 index 0000000..f5c28bb --- /dev/null +++ b/src/toomf.c @@ -0,0 +1,81 @@ +/******************************************************* + * + * a56 - a DSP56001 assembler + * + * Written by Quinn C. Jensen + * July 1990 + * + *******************************************************\ + +/* + * Copyright (C) 2012 Thorsten Alteholz + * + * 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 + * . + * + * 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 + +/* + * 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); +} diff --git a/src/torom.c b/src/torom.c new file mode 100644 index 0000000..afb79c2 --- /dev/null +++ b/src/torom.c @@ -0,0 +1,70 @@ +/******************************************************* + * + * 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); +} diff --git a/subs.c b/subs.c deleted file mode 100644 index 5166717..0000000 --- a/subs.c +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************\ - -/* - * Copyright (C) 2008 Robert Millan - * Copyright (C) 2012 Thorsten Alteholz - * - * 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 - * . - * - * 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; -} diff --git a/tok.awk b/tok.awk deleted file mode 100644 index 44e02aa..0000000 --- a/tok.awk +++ /dev/null @@ -1,4 +0,0 @@ -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");} diff --git a/toktab.c b/toktab.c deleted file mode 100644 index e70ea14..0000000 --- a/toktab.c +++ /dev/null @@ -1,131 +0,0 @@ -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; diff --git a/toomf.c b/toomf.c deleted file mode 100644 index f5c28bb..0000000 --- a/toomf.c +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************\ - -/* - * Copyright (C) 2012 Thorsten Alteholz - * - * 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 - * . - * - * 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 - -/* - * 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); -} diff --git a/torom.c b/torom.c deleted file mode 100644 index afb79c2..0000000 --- a/torom.c +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************\ - -/* - * Copyright (C) 1990-1994 Quinn C. Jensen - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. The author makes no representations - * about the suitability of this software for any purpose. It is - * provided "as is" without express or implied warranty. - * - */ -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); -}