From 333b605b2afd472b823aeda0adf0e8b1ea9843c0 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Mon, 27 May 2019 02:41:51 +0100 Subject: initial commit from asl-1.41r8.tar.gz --- as1750.c | 1295 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1295 insertions(+) create mode 100644 as1750.c (limited to 'as1750.c') diff --git a/as1750.c b/as1750.c new file mode 100644 index 0000000..13301b4 --- /dev/null +++ b/as1750.c @@ -0,0 +1,1295 @@ +/***************************************************************************/ +/* */ +/* Project : as1750 -- Mil-Std-1750 Assembler and Linker */ +/* */ +/* Component : as1750.c -- 1750 instruction assembly */ +/* */ +/* Copyright : (C) Daimler-Benz Aerospace AG, 1994-1997 */ +/* */ +/* Author : Oliver M. Kellogg, Dornier Satellite Systems, */ +/* Dept. RST13, D-81663 Munich, Germany. */ +/* Contact : oliver.kellogg@space.otn.dasa.de */ +/* */ +/* Disclaimer: */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 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, write to the Free Software */ +/* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/***************************************************************************/ + +#ifdef AS1750 +#include "common.h" +#include "utils.h" +#else /* ASL */ +#include +#include +#include +#include +#include "datatypes.h" +#include "strutil.h" +#include "asmdef.h" +#include "asmsub.h" +#include "asmpars.h" +#include "as1750.h" +#define bool char +#define ushort unsigned short +#define ulong unsigned long +#define status unsigned +#define dtoi(ascii_char) (ascii_char - '0') +#endif + + +#ifndef AS1750 +static +#endif + status /* Output an error text (printf style). */ +error (char *layout,...) /* Return the ERROR status code. */ +{ + va_list vargu; + char output_line[132]; + + va_start (vargu, layout); + vsprintf (output_line, layout, vargu); +#ifdef AS1750 + fprintf (stderr, "%s line%5d: %s\n", nopath (file[curr_file].name), + file[curr_file].line_number, output_line); +#else /* ASL */ + WrErrorString (output_line, "\0", 0, 0); +#endif + va_end (vargu); + return ERROR; +} + + +/* Get a number. Return pointer to first position in s after the end of + * the number, or NULL for error. + * Will also read character constants of the form: 'x', and two-character + * packed strings of the form "xy" (where x=>highbyte,y=>lowbyte.) + */ + +#ifdef AS1750 + +char * +get_num (char *s, int *outnum) +{ + bool is_neg = FALSE, intel = FALSE, c_lang = FALSE, tld = FALSE; + char *start; + + *outnum = 0; + if (*s == '-') + { + is_neg = TRUE; + ++s; + } + else if (*s == '+') + ++s; + /* determine if Intel format */ + if (isdigit (*s)) + { + char *p = s; + while (isxdigit (*++p)) + ; + if (upcase (*p) == 'H') + intel = TRUE; + } + if (intel + || (c_lang = (*s == '0' && upcase (*(s + 1)) == 'X')) + || (tld = strncmp (s, "16#", 3) == 0)) + { + s += c_lang ? 2 : tld ? 3 : 0; + start = s; + while (isxdigit (*s)) + { + *outnum = (*outnum << 4) | xtoi (*s); + ++s; + } + if (s - start > 4) + { + error ("get_num -- number at '%s' too large", start); + return NULL; + } + if (intel) + s++; + else if (tld) + { + if (*s != '#') + { + error ("get_num -- expecting '#' at end of number"); + return NULL; + } + s++; + } + } + else if (*s == '0' || (tld = (*s == '8' && *(s + 1) == '#'))) + { + s += tld ? 2 : 1; + start = s; + while (*s >= '0' && *s <= '7') + { + *outnum = (*outnum << 3) | (*s - '0'); + ++s; + } + if (s - start > 6) + { + error ("get_num -- number at '%s' too large", start); + return NULL; + } + if (tld) + { + if (*s != '#') + { + error ("get_num -- expecting '#' at end of number"); + return NULL; + } + ++s; + } + } + else if (*s == '@' || (tld = (*s == '2' && *(s + 1) == '#'))) + { + s += (tld ? 2 : 1); + start = s; + while (*s == '0' || *s == '1') + { + *outnum = (*outnum << 1) | (*s - '0'); + ++s; + } + if (s - start > 16) + { + error ("get_num -- number at '%s' too large", start); + return NULL; + } + if (tld) + { + if (*s != '#') + { + error ("get_num -- expecting '#' at end of number"); + return NULL; + } + ++s; + } + } + else if (isdigit (*s)) + { + start = s; + while (isdigit (*s)) + { + *outnum = (*outnum * 10) + dtoi (*s); + ++s; + } + if (s - start > 5) + { + error ("get_num -- number at '%s' too large", start); + return NULL; + } + } + else if (*s == '\'') + { + start = s; + if (*++s == '\\') + { + switch (*++s) + { + case 't': + *outnum = 9; + break; + case 'n': + *outnum = 10; + break; + case 'r': + *outnum = 13; + break; + default: + error ("get_num -- unknown escape '\\%c'", *s); + return NULL; + } + } + else + *outnum = (int) *s & 0xFF; + if (*++s != '\'') + { + error ("get_num -- character constant incorrectly terminated", start); + return NULL; + } + ++s; + } + else if (*s == '"') + { + start = s; + *outnum = ((int) *++s & 0xFF) << 8; + *outnum |= (int) *++s & 0xFF; + if (*++s != '"') + { + error ("get_num -- character tuple incorrectly terminated", start); + return NULL; + } + ++s; + } + else + return NULL; + if (is_neg) + *outnum = -*outnum; + return s; +} + +/* Get a constant symbol (previously defined by EQU) or a number. + * Return pointer to first character after the symbol or number consumed, + * or NULL if reading the symbol or number was unsuccessful. + */ +char * +get_sym_num (char *s, int *outnum) +{ + char *p, c; + symbol_t sym; + + if ((p = get_num (s, outnum)) != NULL) + return p; + + /* Didn't find a raw number; try symbol. */ + if (!issymstart (*s)) + { + error ("expecting symbol at '%s'", s); + return NULL; + } + p = s; + while (issymchar (*p)) + p++; + c = *p; + *p = '\0'; + if ((sym = find_symbol (s)) == SNULL) + { + error ("unidentified symbol at '%s'", s); + return NULL; + } + *p = c; + if (!sym->is_constant) + { + error ("symbol must be constant in this context"); + return NULL; + } + *outnum = (int) sym->value; + return p; +} + + +extern int curr_frag; /* imported from main.c */ + +/* Enter a 16-bit word into the object space */ +void +add_word (ushort word) +{ + struct objblock *obj = &objblk[curr_frag]; + + if (obj->data == (ushort *) 0) + { + obj->n_allocated = 256; + obj->data = (ushort *) malloc (obj->n_allocated * sizeof (ushort)); + obj->line = (struct linelist **) malloc + (obj->n_allocated * sizeof (struct linelist *)); + } + else if (obj->n_used == obj->n_allocated) + { + obj->n_allocated *= 2; + obj->data = (ushort *) realloc (obj->data, + obj->n_allocated * sizeof (ushort)); + obj->line = (struct linelist **) realloc (obj->line, + obj->n_allocated * sizeof (struct linelist *)); + } + if (obj->data == (ushort *) 0 || obj->line == (struct linelist **) 0) + problem ("request for object space refused by OS"); + obj->data[obj->n_used] = word; + obj->line[obj->n_used] = line; + obj->n_used++; +} + +void +add_reloc (symbol_t sym) /* auxiliary to parse_addr() */ +{ + struct reloc *rel; + + if (relblk.data == (struct reloc *) 0) + { + relblk.n_allocated = 256; + relblk.data = (struct reloc *) malloc + (relblk.n_allocated * sizeof (struct reloc)); + } + else if (relblk.n_used == relblk.n_allocated) + { + relblk.n_allocated *= 2; + relblk.data = (struct reloc *) realloc (relblk.data, + relblk.n_allocated * sizeof (struct reloc)); + } + if (relblk.data == (struct reloc *) 0) + problem ("request for relocation space refused by OS"); + rel = &relblk.data[relblk.n_used]; + rel->done = FALSE; /* default initializations */ + rel->reltype = Word_Reloc; + rel->frag_index = curr_frag; + rel->obj_index = objblk[curr_frag].n_used; + rel->sym = sym; + relblk.n_used++; +} + + +/* Parse the address expression at s into object space. + Returns OKAY or ERROR. */ +status +parse_addr (char *s) +{ + int num; + char *p, c, c1; + symbol_t sym, sym1; + + if (issymstart (*s)) + { + p = skip_symbol (s); + c = *p; /* prepare for symbol lookup */ + *p = '\0'; + if ((sym = find_or_enter (s)) == SNULL) + return ERROR; + sym->is_referenced = TRUE; + *p = c; + s = p++; + if (c == '\0') + { + if (sym->is_constant) + add_word ((ushort) sym->value); + else + { + add_reloc (sym); + add_word (0); + } + } + else if (c != '+' && c != '-') + return error ("error after symbolname at: %s", s); + else if (issymstart (*p)) + { + s = skip_symbol (p); + if (*s != '\0' && *s != ',') + return error ("address expression too complex"); + c1 = *s; /* prepare for symbol lookup */ + *s = '\0'; + if ((sym1 = find_or_enter (p)) == SNULL) + return ERROR; + sym1->is_referenced = TRUE; + *s = c1; + if (c == '+') + { + if (sym->is_constant) + { + if (sym1->is_constant) + { + long sum = sym->value + sym1->value; + if (sum < -0x8000L) + return error ("negative overflow in symbol addition"); + else if (sum > 0xFFFFL) + return error ("positive overflow in symbol addition"); + add_word ((ushort) sum); + } + else + { + add_reloc (sym1); + add_word ((ushort) sym->value); + } + } + else + { + if (sym1->is_constant) + { + add_reloc (sym); + add_word ((ushort) sym1->value); + } + else + return error ("cannot add relocatable symbols"); + } + } + else + /* subtraction */ + { + if (sym->is_constant) + { + if (sym1->is_constant) + { + long dif = sym->value - sym1->value; + if (dif < -0x8000L) + return error ("negative overflow in symbol subtraction"); + else if (dif > 0xFFFFL) + return error ("positive overflow symbol subtraction"); + add_word ((ushort) dif); + } + else + error ("cannot subtract relocatable symbol from constant symbol"); + } + else + { + if (sym1->is_constant) + { + add_reloc (sym); + add_word ((ushort) - sym1->value); + } + else + { + if (objblk[sym->frag_index].section != + objblk[sym1->frag_index].section) + return error + ("cannot subtract relocatable symbols from different fragments"); + if (sym->value < sym1->value) + error ("warning: strange subtraction of relocatable symbols"); + add_word ((ushort) (sym->value - sym1->value)); + } + } + } + } + else + { + if (get_num (s, &num) == NULL) + return ERROR; + if (sym->is_constant) + { + long sum = sym->value + (long) num; + if (sum < -32768L) + return error ("neg. overflow in symbolic expression"); + else if (sum > 65535L) + return error ("overflow in symbolic expression"); + add_word ((ushort) sum); + } + else + { + add_reloc (sym); + add_word ((ushort) num); + } + } + } + else if ((s = get_num (s, &num)) == NULL) + return ERROR; + else + { + if (*s == '\0') + add_word ((ushort) num); + else if (*s != '+') + return error ("expected '+' in address expression at: %s", s); + else + { + ++s; + if (!issymstart (*s)) + return error ("expected symbolname in address expression at: %s", s); + p = skip_symbol (s); + if (*p != '\0' && *p != ',') + return error ("illegal characters after symbolname at: %s", s); + c = *p; /* prepare for symbol lookup */ + *p = '\0'; + if ((sym = find_or_enter (s)) == SNULL) + return ERROR; + sym->is_referenced = TRUE; + *p = c; + s = p; + if (sym->is_constant) + add_word ((ushort) (sym->value + (long) num)); + else + { + add_reloc (sym); + add_word ((ushort) num); + } + } + } + return OKAY; +} + +#else /* ASL */ + +static char * +get_sym_num (char *s, int *outnum) +{ + Boolean okay; + *outnum = (int) EvalIntExpression (s, Int16, &okay); + if (!okay) + return NULL; + return (s + strlen (s)); /* Any non-NULL value will do here. */ +} + + +#define add_word(word) WAsmCode[CodeLen++]=word + +static status +parse_addr (char *s) +{ + int value; + Boolean okay; + value = (int) EvalIntExpression (s, Int16, &okay); + if (!okay) + return ERROR; + add_word ((ushort) value); + return OKAY; +} + +#endif /* from #else of #ifdef AS1750 */ + +/* From here on, everything is identical between as1750 and ASL. */ + +static ushort +get_num_bounded (char *s, int lowlim, int highlim) +{ + int num; + if (get_sym_num (s, &num) == NULL) + return ERROR; + if (num < lowlim || num > highlim) + return error ("number not in range %d..%d", lowlim, highlim); + return (ushort) num; +} + +static ushort +get_regnum (char *s) +{ + ushort regnum; + *s = toupper (*s); + if (*s != 'R') + return error ("expecting register at '%s'", s); + ++s; + if (!isdigit (*s)) + return error ("expecting register at '%s'", s); + regnum = dtoi (*s); + ++s; + if (isdigit (*s)) + { + regnum = regnum * 10 + dtoi (*s); + if (regnum > 15) + return error ("register number out of range"); + ++s; + } + return regnum; +} + + +/**********************************************************************/ +/* Functions to process opcode arguments according to addressing mode */ + +static int n_args; +static char *arg[4]; + +static status +check_indexreg (void) +{ + if (n_args > 2) + { + ushort rx; + + if ((rx = get_regnum (arg[2])) == ERROR) + return ERROR; + if (rx == 0) + return error ("R0 not an index register"); +#ifdef AS1750 + objblk[curr_frag].data[objblk[curr_frag].n_used - 2] |= rx; +#else /* ASL */ + WAsmCode[0] |= rx; +#endif + } + return OKAY; +} + + +static ushort +as_r (ushort oc) +{ + ushort ra, rb; + if (n_args != 2) + return error ("incorrect number of operands"); + if ((ra = get_regnum (arg[0])) == ERROR) + return ERROR; + if ((rb = get_regnum (arg[1])) == ERROR) + return ERROR; + + add_word (oc | (ra << 4) | rb); + return 1; +} + +static ushort +as_mem (ushort oc) +{ + ushort ra; + if (n_args < 2) + return error ("insufficient number of operands"); + if ((ra = get_regnum (arg[0])) == ERROR) + return ERROR; + add_word (oc | (ra << 4)); + if (parse_addr (arg[1])) + return ERROR; + if (check_indexreg ()) + return ERROR; + return 2; +} + +static ushort +as_addr (ushort oc) /* LST and LSTI */ +{ + if (n_args < 1) + return error ("insufficient number of operands"); + add_word (oc); + if (parse_addr (arg[0])) + return ERROR; + n_args++; /* cheat check_indexreg() */ + arg[2] = arg[1]; + if (check_indexreg ()) + return ERROR; + return 2; +} + +static ushort +as_xmem (ushort oc) /* MIL-STD-1750B extended mem. addr. */ +{ + ushort ra; + + if (n_args < 2) + return error ("insufficient number of operands"); + if ((ra = get_regnum (arg[0])) == ERROR) + return ERROR; + add_word (oc | (ra << 4)); + if (parse_addr (arg[1])) + return ERROR; + if (n_args > 2) + { + ushort rx; + if ((rx = get_regnum (arg[2])) == ERROR) + return ERROR; +#ifdef AS1750 + objblk[curr_frag].data[objblk[curr_frag].n_used - 2] |= rx; +#else /* ASL */ + WAsmCode[0] |= rx; +#endif + } + return 2; +} + +static ushort +as_im_0_15 (ushort oc) /* for STC, LM, TB,SB,RB,TSB */ +{ + ushort ra; + if (n_args < 2) + return error ("insufficient number of operands"); + if ((ra = get_num_bounded (arg[0], 0, 15)) == ERROR) + return ERROR; + add_word (oc | (ra << 4)); + if (parse_addr (arg[1])) + return ERROR; + if (check_indexreg ()) + return ERROR; + return 2; +} + +static ushort +as_im_1_16 (ushort oc) +{ + ushort ra; + if (n_args < 2) + return error ("insufficient number of operands"); + if ((ra = get_num_bounded (arg[0], 1, 16)) == ERROR) + return ERROR; + add_word (oc | ((ra - 1) << 4)); + if (parse_addr (arg[1])) + return ERROR; + if (check_indexreg ()) + return ERROR; + return 2; +} + +static ushort +as_im_ocx (ushort oc) +{ + ushort ra; + if (n_args != 2) + return error ("incorrect number of operands"); + if ((ra = get_regnum (arg[0])) == ERROR) + return ERROR; + add_word (oc | (ra << 4)); /* oc has OCX in LSnibble */ + if (parse_addr (arg[1])) + return ERROR; + return 2; +} + +static ushort +as_is (ushort oc) +{ + ushort ra, i; + if (n_args != 2) + return error ("incorrect number of operands"); + if ((ra = get_regnum (arg[0])) == ERROR) + return ERROR; + if ((i = get_num_bounded (arg[1], 1, 16)) == ERROR) + return ERROR; + add_word (oc | (ra << 4) | (i - 1)); + return 1; +} + +static ushort +as_icr (ushort oc) +{ +#ifdef AS1750 + struct objblock *obj = &objblk[curr_frag]; + int last = obj->n_used; +#endif + if (n_args != 1) + return error ("incorrect number of operands"); + if (parse_addr (arg[0])) + return ERROR; +#ifdef AS1750 + /* If symbol relocation, then set the relocation type to Byte_Reloc */ + if (relblk.n_used > 0) + { + struct reloc *rel = &relblk.data[relblk.n_used - 1]; + if (rel->frag_index == curr_frag && rel->obj_index == last) + rel->reltype = Byte_Reloc; + } + obj->data[last] &= 0x00FF; + obj->data[last] |= oc; +#else /* ASL */ + { + const short target = (short) WAsmCode[0]; + const long curr_pc = (long) EProgCounter () & 0xFFFFL; + const long diff = (long) target - curr_pc; + if (diff < -128L || diff > 127L) + return error + ("address distance too large in Instruction Counter Relative operation"); + WAsmCode[0] = oc | (ushort) (diff & 0xFFL); + } +#endif + return 1; +} + +static ushort +as_b (ushort oc) +{ + char r; + ushort br, lobyte; + if (n_args != 2) + return error ("incorrect number of operands"); + r = toupper (*arg[0]); + if (r != 'B' && r != 'R') + return error ("expecting base register"); + if ((br = get_num_bounded (arg[0] + 1, 12, 15)) == ERROR) + return ERROR; + if ((lobyte = get_num_bounded (arg[1], 0, 255)) == ERROR) + return ERROR; + add_word (oc | ((br - 12) << 8) | lobyte); + return 1; +} + +static ushort +as_bx (ushort oc) +{ + char r; + ushort br, rx = 0; + if (n_args != 2) + return error ("incorrect number of operands"); + r = toupper (*arg[0]); + if ((r != 'B' && r != 'R') + || (br = get_num_bounded (arg[0] + 1, 12, 15)) == ERROR) + return error ("expecting base register"); + if ((rx = get_regnum (arg[1])) == ERROR) + return ERROR; + if (rx == 0) + return error ("R0 not an index register"); + add_word (oc | ((br - 12) << 8) | rx); + return 1; +} + +static ushort +as_r_imm (ushort oc) /* for shifts with immediate shiftcount */ +{ + ushort rb, n; + if (n_args != 2) + return error ("incorrect number of operands"); + if ((rb = get_regnum (arg[0])) == ERROR) + return ERROR; + if ((n = get_num_bounded (arg[1], 1, 16)) == ERROR) + return ERROR; + add_word (oc | ((n - 1) << 4) | rb); + return 1; +} + +static ushort +as_imm_r (ushort oc) /* for test/set/reset-bit in reg. */ +{ + ushort n, rb; + if (n_args != 2) + return error ("incorrect number of operands"); + if ((n = get_num_bounded (arg[0], 0, 15)) == ERROR) + return ERROR; + if ((rb = get_regnum (arg[1])) == ERROR) + return ERROR; + add_word (oc | (n << 4) | rb); + return 1; +} + +static ushort +as_jump (ushort oc) +{ + ushort condcode = 0xFFFF; + static const struct + { + char *name; + ushort value; + } + cond[] = + { /* CPZN */ + { "LT", 0x1 }, /* 0001 */ + { "LZ", 0x1 }, /* 0001 */ + { "EQ", 0x2 }, /* 0010 */ + { "EZ", 0x2 }, /* 0010 */ + { "LE", 0x3 }, /* 0011 */ + { "LEZ", 0x3 }, /* 0011 */ + { "GT", 0x4 }, /* 0100 */ + { "GTZ", 0x4 }, /* 0100 */ + { "NE", 0x5 }, /* 0101 */ + { "NZ", 0x5 }, /* 0101 */ + { "GE", 0x6 }, /* 0110 */ + { "GEZ", 0x6 }, /* 0110 */ + { "ALL", 0x7 }, /* 0111 */ + { "CY", 0x8 }, /* 1000 */ + { "CLT", 0x9 }, /* 1001 */ + { "CEQ", 0xA }, /* 1010 */ + { "CEZ", 0xA }, /* 1010 */ + { "CLE", 0xB }, /* 1011 */ + { "CGT", 0xC }, /* 1100 */ + { "CNZ", 0xD }, /* 1101 */ + { "CGE", 0xE }, /* 1110 */ + { "UC", 0xF } /* 1111 */ + }; + if (n_args < 2) + return error ("insufficient number of operands"); + if (isalpha (*arg[0])) + { + int i; + for (i = 0; i < 22; i++) + if (!strcasecmp (arg[0], cond[i].name)) + { + condcode = cond[i].value; + break; + } + } + if (condcode == 0xFFFF) + if ((condcode = get_num_bounded (arg[0], 0, 15)) == ERROR) + return ERROR; + add_word (oc | (condcode << 4)); + if (parse_addr (arg[1])) + return ERROR; + if (check_indexreg ()) + return ERROR; + return 2; +} + +static ushort +as_s (ushort oc) /* For the moment, BEX only. */ +{ + ushort lsnibble; + if (n_args != 1) + return error ("incorrect number of operands"); + if ((lsnibble = get_num_bounded (arg[0], 0, 15)) == ERROR) + return ERROR; + add_word (oc | lsnibble); + return 1; +} + +static ushort +as_sr (ushort oc) /* XBR and URS. */ +{ + ushort hlp; + if (n_args != 1) + return error ("incorrect number of operands"); + if ((hlp = get_regnum (arg[0])) == ERROR) + return ERROR; + add_word (oc | (hlp << 4)); + return 1; +} + +static ushort +as_xio (ushort oc) +{ + ushort ra; + int cmdfld = -1; + static const struct + { + char *mnem; + ushort cmd; + } + xio[] = + { + { "SMK", 0x2000 }, + { "CLIR", 0x2001 }, + { "ENBL", 0x2002 }, + { "DSBL", 0x2003 }, + { "RPI", 0x2004 }, + { "SPI", 0x2005 }, + { "OD", 0x2008 }, + { "RNS", 0x200A }, + { "WSW", 0x200E }, + { "CO", 0x4000 }, + { "CLC", 0x4001 }, + { "MPEN", 0x4003 }, + { "ESUR", 0x4004 }, + { "DSUR", 0x4005 }, + { "DMAE", 0x4006 }, + { "DMAD", 0x4007 }, + { "TAS", 0x4008 }, + { "TAH", 0x4009 }, + { "OTA", 0x400A }, + { "GO", 0x400B }, + { "TBS", 0x400C }, + { "TBH", 0x400D }, + { "OTB", 0x400E }, + { "LMP", 0x5000 }, + { "WIPR", 0x5100 }, + { "WOPR", 0x5200 }, + { "RMP", 0xD000 }, + { "RIPR", 0xD100 }, + { "ROPR", 0xD200 }, + { "RMK", 0xA000 }, + { "RIC1", 0xA001 }, + { "RIC2", 0xA002 }, + { "RPIR", 0xA004 }, + { "RDOR", 0xA008 }, + { "RDI", 0xA009 }, + { "TPIO", 0xA00B }, + { "RMFS", 0xA00D }, + { "RSW", 0xA00E }, + { "RCFR", 0xA00F }, + { "CI", 0xC000 }, + { "RCS", 0xC001 }, + { "ITA", 0xC00A }, + { "ITB", 0xC00E }, + { "", 0xFFFF } + }; + + if (n_args < 2) + return error ("incorrect number of operands"); + if ((ra = get_regnum (arg[0])) == ERROR) + return ERROR; + add_word (oc | (ra << 4)); + /* Get the XIO command field. */ + if (isalpha (*arg[1])) + { + int i; + for (i = 0; xio[i].cmd != 0xFFFF; i++) + if (!strcasecmp (arg[1], xio[i].mnem)) + break; + if (xio[i].cmd != 0xFFFF) + cmdfld = xio[i].cmd; + } + if (cmdfld == -1) + if (get_sym_num (arg[1], &cmdfld) == NULL) + return ERROR; + add_word ((ushort) cmdfld); + if (check_indexreg ()) + return ERROR; + return 2; +} + +static ushort +as_none (ushort oc) +{ + add_word (oc); + return 1; +} + +/* end of argument assembly functions */ + +/***********************************************************************/ + +static struct + { + char *mnemon; + ushort opcode; + ushort (*as_args) (ushort); + } optab[] = + { + { "AISP", 0xA200, as_is }, /* Sorted by beginning letter. */ + { "AIM", 0x4A01, as_im_ocx }, /* Within each beginning letter, */ + { "AR", 0xA100, as_r }, /* sorted by approximate */ + { "A", 0xA000, as_mem }, /* instruction frequency. */ + { "ANDM", 0x4A07, as_im_ocx }, + { "ANDR", 0xE300, as_r }, + { "AND", 0xE200, as_mem }, + { "ABS", 0xA400, as_r }, + { "AB", 0x1000, as_b }, + { "ANDB", 0x3400, as_b }, + { "ABX", 0x4040, as_bx }, + { "ANDX", 0x40E0, as_bx }, + { "BEZ", 0x7500, as_icr }, + { "BNZ", 0x7A00, as_icr }, + { "BGT", 0x7900, as_icr }, + { "BLE", 0x7800, as_icr }, + { "BGE", 0x7B00, as_icr }, + { "BLT", 0x7600, as_icr }, + { "BR", 0x7400, as_icr }, + { "BEX", 0x7700, as_s }, + { "BPT", 0xFFFF, as_none }, + { "BIF", 0x4F00, as_s }, + { "CISP", 0xF200, as_is }, + { "CIM", 0x4A0A, as_im_ocx }, + { "CR", 0xF100, as_r }, + { "C", 0xF000, as_mem }, + { "CISN", 0xF300, as_is }, + { "CB", 0x3800, as_b }, + { "CBL", 0xF400, as_mem }, + { "CBX", 0x40C0, as_bx }, + { "DLR", 0x8700, as_r }, + { "DL", 0x8600, as_mem }, + { "DST", 0x9600, as_mem }, + { "DSLL", 0x6500, as_r_imm }, + { "DSRL", 0x6600, as_r_imm }, + { "DSRA", 0x6700, as_r_imm }, + { "DSLC", 0x6800, as_r_imm }, + { "DSLR", 0x6D00, as_r }, + { "DSAR", 0x6E00, as_r }, + { "DSCR", 0x6F00, as_r }, + { "DECM", 0xB300, as_im_1_16 }, + { "DAR", 0xA700, as_r }, + { "DA", 0xA600, as_mem }, + { "DSR", 0xB700, as_r }, + { "DS", 0xB600, as_mem }, + { "DMR", 0xC700, as_r }, + { "DM", 0xC600, as_mem }, + { "DDR", 0xD700, as_r }, + { "DD", 0xD600, as_mem }, + { "DCR", 0xF700, as_r }, + { "DC", 0xF600, as_mem }, + { "DLB", 0x0400, as_b }, + { "DSTB", 0x0C00, as_b }, + { "DNEG", 0xB500, as_r }, + { "DABS", 0xA500, as_r }, + { "DR", 0xD500, as_r }, + { "D", 0xD400, as_mem }, + { "DISP", 0xD200, as_is }, + { "DIM", 0x4A05, as_im_ocx }, + { "DISN", 0xD300, as_is }, + { "DVIM", 0x4A06, as_im_ocx }, + { "DVR", 0xD100, as_r }, + { "DV", 0xD000, as_mem }, + { "DLI", 0x8800, as_mem }, + { "DSTI", 0x9800, as_mem }, + { "DB", 0x1C00, as_b }, + { "DBX", 0x4070, as_bx }, + { "DLBX", 0x4010, as_bx }, + { "DSTX", 0x4030, as_bx }, + { "DLE", 0xDF00, as_xmem }, + { "DSTE", 0xDD00, as_xmem }, + { "EFL", 0x8A00, as_mem }, + { "EFST", 0x9A00, as_mem }, + { "EFCR", 0xFB00, as_r }, + { "EFC", 0xFA00, as_mem }, + { "EFAR", 0xAB00, as_r }, + { "EFA", 0xAA00, as_mem }, + { "EFSR", 0xBB00, as_r }, + { "EFS", 0xBA00, as_mem }, + { "EFMR", 0xCB00, as_r }, + { "EFM", 0xCA00, as_mem }, + { "EFDR", 0xDB00, as_r }, + { "EFD", 0xDA00, as_mem }, + { "EFLT", 0xEB00, as_r }, + { "EFIX", 0xEA00, as_r }, + { "FAR", 0xA900, as_r }, + { "FA", 0xA800, as_mem }, + { "FSR", 0xB900, as_r }, + { "FS", 0xB800, as_mem }, + { "FMR", 0xC900, as_r }, + { "FM", 0xC800, as_mem }, + { "FDR", 0xD900, as_r }, + { "FD", 0xD800, as_mem }, + { "FCR", 0xF900, as_r }, + { "FC", 0xF800, as_mem }, + { "FABS", 0xAC00, as_r }, + { "FIX", 0xE800, as_r }, + { "FLT", 0xE900, as_r }, + { "FNEG", 0xBC00, as_r }, + { "FAB", 0x2000, as_b }, + { "FABX", 0x4080, as_bx }, + { "FSB", 0x2400, as_b }, + { "FSBX", 0x4090, as_bx }, + { "FMB", 0x2800, as_b }, + { "FMBX", 0x40A0, as_bx }, + { "FDB", 0x2C00, as_b }, + { "FDBX", 0x40B0, as_bx }, + { "FCB", 0x3C00, as_b }, + { "FCBX", 0x40D0, as_bx }, + { "INCM", 0xA300, as_im_1_16 }, + { "JC", 0x7000, as_jump }, + { "J", 0x7400, as_icr }, /* TBD (GAS) */ + { "JEZ", 0x7500, as_icr }, /* TBD (GAS) */ + { "JLE", 0x7800, as_icr }, /* TBD (GAS) */ + { "JGT", 0x7900, as_icr }, /* TBD (GAS) */ + { "JNZ", 0x7A00, as_icr }, /* TBD (GAS) */ + { "JGE", 0x7B00, as_icr }, /* TBD (GAS) */ + { "JLT", 0x7600, as_icr }, /* TBD (GAS) */ + { "JCI", 0x7100, as_jump }, + { "JS", 0x7200, as_mem }, + { "LISP", 0x8200, as_is }, + { "LIM", 0x8500, as_mem }, + { "LR", 0x8100, as_r }, + { "L", 0x8000, as_mem }, + { "LISN", 0x8300, as_is }, + { "LB", 0x0000, as_b }, + { "LBX", 0x4000, as_bx }, + { "LSTI", 0x7C00, as_addr }, + { "LST", 0x7D00, as_addr }, + { "LI", 0x8400, as_mem }, + { "LM", 0x8900, as_im_0_15 }, + { "LUB", 0x8B00, as_mem }, + { "LLB", 0x8C00, as_mem }, + { "LUBI", 0x8D00, as_mem }, + { "LLBI", 0x8E00, as_mem }, + { "LE", 0xDE00, as_xmem }, + { "MISP", 0xC200, as_is }, + { "MSIM", 0x4A04, as_im_ocx }, + { "MSR", 0xC100, as_r }, + { "MS", 0xC000, as_mem }, + { "MISN", 0xC300, as_is }, + { "MIM", 0x4A03, as_im_ocx }, + { "MR", 0xC500, as_r }, + { "M", 0xC400, as_mem }, + { "MOV", 0x9300, as_r }, + { "MB", 0x1800, as_b }, + { "MBX", 0x4060, as_bx }, + { "NEG", 0xB400, as_r }, + { "NOP", 0xFF00, as_none }, + { "NIM", 0x4A0B, as_im_ocx }, + { "NR", 0xE700, as_r }, + { "N", 0xE600, as_mem }, + { "ORIM", 0x4A08, as_im_ocx }, + { "ORR", 0xE100, as_r }, + { "OR", 0xE000, as_mem }, + { "ORB", 0x3000, as_b }, + { "ORBX", 0x40F0, as_bx }, + { "PSHM", 0x9F00, as_r }, + { "POPM", 0x8F00, as_r }, + { "RBR", 0x5400, as_imm_r }, + { "RVBR", 0x5C00, as_r }, + { "RB", 0x5300, as_im_0_15 }, + { "RBI", 0x5500, as_im_0_15 }, + { "ST", 0x9000, as_mem }, + { "STC", 0x9100, as_im_0_15 }, + { "SISP", 0xB200, as_is }, + { "SIM", 0x4A02, as_im_ocx }, + { "SR", 0xB100, as_r }, + { "S", 0xB000, as_mem }, + { "SLL", 0x6000, as_r_imm }, + { "SRL", 0x6100, as_r_imm }, + { "SRA", 0x6200, as_r_imm }, + { "SLC", 0x6300, as_r_imm }, + { "SLR", 0x6A00, as_r }, + { "SAR", 0x6B00, as_r }, + { "SCR", 0x6C00, as_r }, + { "SJS", 0x7E00, as_mem }, + { "STB", 0x0800, as_b }, + { "SBR", 0x5100, as_imm_r }, + { "SB", 0x5000, as_im_0_15 }, + { "SVBR", 0x5A00, as_r }, + { "SOJ", 0x7300, as_mem }, + { "SBB", 0x1400, as_b }, + { "STBX", 0x4020, as_bx }, + { "SBBX", 0x4050, as_bx }, + { "SBI", 0x5200, as_im_0_15 }, + { "STZ", 0x9100, as_addr }, + { "STCI", 0x9200, as_im_0_15 }, + { "STI", 0x9400, as_mem }, + { "SFBS", 0x9500, as_r }, + { "SRM", 0x9700, as_mem }, + { "STM", 0x9900, as_im_0_15 }, + { "STUB", 0x9B00, as_mem }, + { "STLB", 0x9C00, as_mem }, + { "SUBI", 0x9D00, as_mem }, + { "SLBI", 0x9E00, as_mem }, + { "STE", 0xDC00, as_xmem }, + { "TBR", 0x5700, as_imm_r }, + { "TB", 0x5600, as_im_0_15 }, + { "TBI", 0x5800, as_im_0_15 }, + { "TSB", 0x5900, as_im_0_15 }, + { "TVBR", 0x5E00, as_r }, + { "URS", 0x7F00, as_sr }, + { "UAR", 0xAD00, as_r }, + { "UA", 0xAE00, as_mem }, + { "USR", 0xBD00, as_r }, + { "US", 0xBE00, as_mem }, + { "UCIM", 0xF500, as_im_ocx }, + { "UCR", 0xFC00, as_r }, + { "UC", 0xFD00, as_mem }, + { "VIO", 0x4900, as_mem }, + { "XORR", 0xE500, as_r }, + { "XORM", 0x4A09, as_im_ocx }, + { "XOR", 0xE400, as_mem }, + { "XWR", 0xED00, as_r }, + { "XBR", 0xEC00, as_sr }, + { "XIO", 0x4800, as_xio }, + { "", 0, as_none } /* end-of-array marker */ +}; + +/* Offset table with indexes into optab: indexed by starting letter + (A => 0, B => 1, ..., Z => 25), returns the starting index + and number of entries for that letter in optab[]. + start_index is -1 if no entries for that starting letter in optab[]. */ + +static struct + { + int start_index; + int n_entries; + } +ofstab[26]; + +/* Initialize ofstab[]. This must be called before as1750() can be used. */ +void +init_as1750 () +{ + int optab_ndx, ofstab_ndx = 1; + char c; + + ofstab[0].start_index = 0; + ofstab[0].n_entries = 1; + for (optab_ndx = 1; (c = *optab[optab_ndx].mnemon) != '\0'; optab_ndx++) + { + if (c != *optab[optab_ndx - 1].mnemon) + { + while (ofstab_ndx != c - 'A') + ofstab[ofstab_ndx++].start_index = -1; + ofstab[ofstab_ndx].start_index = optab_ndx; + ofstab[ofstab_ndx++].n_entries = 1; + } + else + ofstab[ofstab_ndx - 1].n_entries++; + } +} + + +/************************** HERE'S THE BEEF: ****************************/ + +ushort +as1750 (char *operation, int n_operands, char *operand[]) +{ + int i, optab_ndx, firstletter; + bool found = FALSE; + + if (n_operands < 0 || n_operands > 3 || *operation < 'A' || *operation > 'X') + return NO_OPCODE; + n_args = n_operands; + for (i = 0; i < n_args; i++) + arg[i] = operand[i]; + firstletter = (int) (*operation - 'A'); + if ((optab_ndx = ofstab[firstletter].start_index) < 0) + return NO_OPCODE; + for (i = 0; i < ofstab[firstletter].n_entries; i++, optab_ndx++) + if (!strcmp (operation + 1, optab[optab_ndx].mnemon + 1)) + { + found = TRUE; + break; + } + if (!found) + return NO_OPCODE; + return (*optab[optab_ndx].as_args) (optab[optab_ndx].opcode); +} + -- cgit v1.2.3