/*
 * AS-Portierung 
 *
 * AS-Codegeneratormodul fuer die Texas Instruments TMS320C5x-Familie
 *
 * (C) 1996 Thomas Sailer <sailer@ife.ee.ethz.ch>
 *
 * 20.08.96: Erstellung
 *  7.07.1998 Fix Zugriffe auf CharTransTable wg. signed chars
 * 18.08.1998 BookKeeping-Aufruf in RES
 *  9. 1.1999 ChkPC jetzt ueber SegLimits
 * 30. 5.1999 Erweiterung auf C203 abgeschlossen, Hashtabelle fuer
 *            Prozessorbefehle erledigt
 */

#include "stdinc.h"
#include <string.h>
#include <ctype.h>

#include "nls.h"
#include "bpemu.h"
#include "strutil.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmitree.h"
#include "codepseudo.h"
#include "endian.h"

#include "code3202x.h"

/* ---------------------------------------------------------------------- */

typedef struct {
	char *name;
	CPUVar mincpu;
	Word code;
} cmd_fixed;
typedef struct {
	char *name;
	CPUVar mincpu;
	Word code;
	Boolean cond;
} cmd_jmp;
typedef struct {
	char *name;
	CPUVar mincpu;
	Word mode;
} adr_mode_t;
typedef struct {
	char *name;
	CPUVar mincpu;
	Word codeand;
	Word codeor;
	Byte iszl;
	Byte isc;
	Byte isv;
	Byte istp;
} condition;
typedef struct {
	char *name;
	CPUVar mincpu;
	Word code;
} bit_table_t;

static cmd_fixed *cmd_fixed_order;
#define cmd_fixed_cnt 45
static cmd_fixed *cmd_adr_order;
#define cmd_adr_cnt 32
static cmd_jmp *cmd_jmp_order;
#define cmd_jmp_cnt 11
static cmd_fixed *cmd_plu_order;
#define cmd_plu_cnt 7
static adr_mode_t *adr_modes;
#define adr_mode_cnt 10
static condition *cond_tab;
#define cond_cnt 15
static bit_table_t *bit_table;
#define bit_cnt 9

static Word adr_mode;
static Boolean adr_ok;

static CPUVar cpu_320203;
static CPUVar cpu_32050;
static CPUVar cpu_32051;
static CPUVar cpu_32053;

static PInstTable InstTable;

/* ---------------------------------------------------------------------- */

static Word eval_ar_expression(char *asc, Boolean *ok)
{
	*ok = True;

	if ((toupper(asc[0]) == 'A') && (toupper(asc[1]) == 'R') && (asc[2] >= '0') && 
	    (asc[2] <= '7') && (asc[3] <= '\0'))
		return asc[2] - '0';
	return EvalIntExpression(asc, UInt3, ok);
}

/* ---------------------------------------------------------------------- */

	static Boolean decode_adr(char *arg, int aux, Boolean must1)
{
  Word h;
  adr_mode_t *am = adr_modes;

  /* Annahme: nicht gefunden */

  adr_ok = False;

  /* Adressierungsmodus suchen */

  while (am->name && strcasecmp(am->name, arg))
   am++;

  /* nicht gefunden: dann absolut */

  if (!am->name)
   BEGIN
    /* ARn-Register darf dann nicht vorhanden sein */
    if (aux <= ArgCnt)
     BEGIN
      WrError(1110); return FALSE;
     END

    /* Adresse berechnen */
    h = EvalIntExpression(arg, Int16, &adr_ok);
    if (!adr_ok) return FALSE;

    /* Adresslage pruefen */
    if (must1 && (h >= 0x80) && (!FirstPassUnknown))
     BEGIN
      WrError(1315); 
      adr_ok = False;
      return FALSE;
     END

    /* nur untere 7 Bit gespeichert */
    adr_mode = h & 0x7f; 
    ChkSpace(SegData);
   END

  /* ansonsten evtl. noch Adressregister dazu */

  else
   BEGIN
    /* auf dieser CPU nicht erlaubter Modus ? */

    if (am->mincpu > MomCPU)
     BEGIN
      WrError(1505); return FALSE;
     END

    adr_mode = am->mode;
    if (aux <= ArgCnt)
     BEGIN
      h = eval_ar_expression(ArgStr[aux], &adr_ok);
      if (adr_ok) adr_mode |= 0x8 | h;
     END
    else
     adr_ok = True;
   END

  return adr_ok;
END

/* ---------------------------------------------------------------------- */

static Word decode_cond(int argp)
{
	condition *cndp;
	Byte cntzl = 0, cntc = 0, cntv = 0, cnttp = 0;
	Word ret = 0x300;

	while(argp <= ArgCnt) {
		for(cndp = cond_tab; 
		    cndp->name && strcasecmp(cndp->name, ArgStr[argp]); cndp++);
		if (!cndp->name) {
			WrError(1360);
			return ret;
		}
		ret &= cndp->codeand;
		ret |= cndp->codeor;
		cntzl += cndp->iszl;
		cntc += cndp->isc;
		cntv += cndp->isv;
		cnttp += cndp->istp;
		argp++;
	}
	if ((cnttp > 1) || (cntzl > 1) || (cntv > 1) || (cntc > 1)) 
		WrXError(1200, ArgStr[argp]); /* invalid condition */
	return ret;
}

/* ---------------------------------------------------------------------- */

	static Word DecodeShift(char *arg, Boolean *ok)
BEGIN
   Word Shift;

   FirstPassUnknown = False;
   Shift = EvalIntExpression(arg, UInt5, ok);
   if (*ok)
    BEGIN
     if (FirstPassUnknown) Shift &= 15;
     *ok = ChkRange(Shift, 0, 16);
    END
   return Shift;
END

/* ---------------------------------------------------------------------- */

	static void DecodeFixed(Word Index)
BEGIN
   cmd_fixed *fo = cmd_fixed_order + Index;

   if (ArgCnt != 0)
    BEGIN
     WrError(1110);
     return;
    END

   if (fo->mincpu > MomCPU)
    BEGIN
     WrError(1500);
     return;
    END

   CodeLen = 1; 
   WAsmCode[0] = fo->code;
END

	static void DecodeCmdAdr(Word Index)
BEGIN
   cmd_fixed *fo = cmd_adr_order + Index;

   if ((ArgCnt < 1) OR (ArgCnt > 2))
    BEGIN
     WrError(1110);
     return;
    END

   if (MomCPU < fo->mincpu)
    BEGIN
     WrError(1500);
     return;
    END

   decode_adr(ArgStr[1], 2, False);
   if (adr_ok)
    BEGIN
     CodeLen = 1; 
     WAsmCode[0] = fo->code | adr_mode;
    END
END

	static void DecodeCmdJmp(Word Index)
BEGIN
   cmd_jmp *jo = cmd_jmp_order + Index;
   Boolean ok;

   if (MomCPU < jo->mincpu)
    BEGIN
     WrError(1500);
     return;
    END

   if ((ArgCnt < 1) || ((ArgCnt > 3) && (!jo->cond)))
    BEGIN
     WrError(1110);
     return;
    END

   adr_mode  =  0;
   if (jo->cond)
    adr_mode = decode_cond(2);
   else if (ArgCnt > 1)
    BEGIN
     decode_adr(ArgStr[2], 3, False);
     if (adr_mode < 0x80)
      BEGIN
       WrError(1350);
       return;
      END
     adr_mode &= 0x7f;
    END

   WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
   if (!ok) return;         

   CodeLen = 2; 
   WAsmCode[0] = jo->code | adr_mode;
END

	static void DecodeCmdPlu(Word Index)
BEGIN
   Boolean ok;

   cmd_fixed *fo = cmd_plu_order + Index;

   if (MomCPU < fo->mincpu) WrError(1500);
   else if (*ArgStr[1] == '#')
    BEGIN
     if ((ArgCnt < 2) OR (ArgCnt > 3)) WrError(1110);
     else
      BEGIN
       decode_adr(ArgStr[2], 3, False);
       WAsmCode[1] = EvalIntExpression(ArgStr[1] + 1, Int16, &ok);
       if ((ok) AND (adr_ok)) 
        BEGIN
         CodeLen = 2;
         WAsmCode[0] = fo->code | 0x0400 | adr_mode;
        END
      END
    END
   else if (strlen(OpPart) == 4) WrError(1120);
   else
    BEGIN
     if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
     else
      BEGIN
       decode_adr(ArgStr[1], 2, False);
       if (adr_ok)
        BEGIN
         CodeLen = 1;
         WAsmCode[0] = fo->code | adr_mode;
        END
      END
    END
END

	static void DecodeADDSUB(Word Index)
BEGIN
   Word Shift;
   LongInt adr_long;
   Boolean ok;

   if ((ArgCnt < 1) || (ArgCnt > 3)) WrError(1110);
   else
    BEGIN
     if (*ArgStr[1] == '#')
      BEGIN
       if (ArgCnt > 2) WrError(1110);
       else
        BEGIN
         ok = True;
         if (ArgCnt == 1) Shift = 0;
         else Shift = EvalIntExpression(ArgStr[2], UInt4, &adr_ok);
         if (ok)
          BEGIN
           adr_long = EvalIntExpression(ArgStr[1] + 1, UInt16, &ok);
           if (ok)
            if ((Shift == 0) && (Hi(adr_long) == 0))
             BEGIN
              CodeLen = 1;
              WAsmCode[0] = (Index << 9) | 0xb800 | (adr_long & 0xff);
             END
            else
             BEGIN
              CodeLen = 2;
              WAsmCode[0] = ((Index << 4) + 0xbf90) | (Shift & 0xf);
              WAsmCode[1] = adr_long;
             END
          END
        END
      END
     else
      BEGIN
       decode_adr(ArgStr[1], 3, False);
       if (adr_ok)
        BEGIN
         ok = True;
         if (ArgCnt >= 2)
          Shift = DecodeShift(ArgStr[2], &ok);
         else
          Shift = 0;
         if (ok)
          BEGIN
           CodeLen = 1;
           if (Shift == 16)
            WAsmCode[0] = ((Index << 10) | 0x6100) | adr_mode;
           else
            WAsmCode[0] = ((Index << 12) | 0x2000) | ((Shift & 0xf) << 8) | adr_mode;
          END
        END
      END
    END
END

	static void DecodeADRSBRK(Word Index)
BEGIN
   Word adr_word;
   Boolean ok;

   if (ArgCnt != 1)
    BEGIN
     WrError(1110);
     return;
    END

   if (*ArgStr[1] != '#')
    BEGIN
     WrError(1120); /*invalid parameter*/
     return;
    END

   adr_word = EvalIntExpression(ArgStr[1] + 1, UInt8, &ok);
   if (ok)
    BEGIN
     CodeLen = 1;
     WAsmCode[0] = (Index << 10)| 0x7800 | (adr_word & 0xff);
    END
END

	static void DecodeLogic(Word Index)
BEGIN
   Boolean adr_ok, ok;
   Word Shift;

   if ((ArgCnt != 1) AND (ArgCnt != 2))
    BEGIN
     WrError(1110);
     return;
    END

   if (*ArgStr[1] == '#')
    BEGIN
     WAsmCode[1] = EvalIntExpression((ArgStr[1])+1, UInt16, &ok);
     Shift = 0;
     adr_ok = True;
     if (ArgCnt >= 2) 
      Shift = DecodeShift(ArgStr[2], &adr_ok);
     if ((ok) AND (adr_ok))
      BEGIN
       CodeLen = 2;
       if (Shift >= 16)
        WAsmCode[0] = 0xbe80 | Lo(Index);
       else
        WAsmCode[0] = 0xbfa0 + ((Index & 3) << 4) + (Shift & 0xf);
      END
    END
   else
    BEGIN
     if (decode_adr(ArgStr[1], 2, False))
      BEGIN
       CodeLen = 1; 
       WAsmCode[0] = (Index & 0xff00) | adr_mode;
      END
    END
END

	static void DecodeBIT(Word Index)
BEGIN
   Word bit;
   Boolean ok;

   if ((ArgCnt < 2) || (ArgCnt > 3))
    BEGIN
     WrError(1110);
     return;
    END

   bit = EvalIntExpression(ArgStr[2], UInt4, &ok);

   decode_adr(ArgStr[1], 3, False);

   if ((adr_ok) AND (ok))
    BEGIN
     CodeLen = 1;
     WAsmCode[0] = 0x4000 | adr_mode | ((bit & 0xf) << 8);
    END
END

	static void DecodeBLDD(Word Index)
BEGIN
   Boolean ok;

   if ((ArgCnt < 2) || (ArgCnt > 3))
    BEGIN
     WrError(1110);
     return;
    END

   if (!strcasecmp(ArgStr[1], "BMAR"))
    BEGIN
     if (MomCPU < cpu_32050) WrError(1500);
     else
      BEGIN
       decode_adr(ArgStr[2], 3, False);
       if (!adr_ok) return;
       CodeLen = 1;
       WAsmCode[0] = 0xac00 | adr_mode;
      END
     return;
    END

   if (!strcasecmp(ArgStr[2], "BMAR"))
    BEGIN
     if (MomCPU < cpu_32050) WrError(1500);
     else
      BEGIN
       decode_adr(ArgStr[1], 3, False);
       if (!adr_ok) return;
       CodeLen = 1;
       WAsmCode[0] = 0xad00 | adr_mode;
      END
     return;
    END

   if (*ArgStr[1] == '#')
    BEGIN
     WAsmCode[1] = EvalIntExpression((ArgStr[1])+1, Int16, &ok);
     decode_adr(ArgStr[2], 3, False);
     if ((!adr_ok) || (!ok)) return;
     CodeLen = 2;
     WAsmCode[0] = 0xa800 | adr_mode;          
     return;
    END

   if (*ArgStr[2] == '#')
    BEGIN
     WAsmCode[1] = EvalIntExpression((ArgStr[2])+1, Int16, &ok);
     decode_adr(ArgStr[1], 3, False);
     if ((!adr_ok) || (!ok)) return;
     CodeLen = 2;
     WAsmCode[0] = 0xa900 | adr_mode;
     return;
    END

   WrError(1350); /* invalid addr mode */
END

	static void DecodeBLPD(Word Index)
BEGIN
   Boolean ok;

   if ((ArgCnt < 2) || (ArgCnt > 3))
    BEGIN
     WrError(1110);
     return;
    END

   if (!strcasecmp(ArgStr[1], "BMAR"))
    BEGIN
     if (MomCPU < cpu_32050) WrError(1500);
     else
      BEGIN
       decode_adr(ArgStr[2], 3, False);
       if (!adr_ok) return;
       CodeLen = 1;
       WAsmCode[0] = 0xa400 | adr_mode;		
      END
     return;
    END

   if (*ArgStr[1] == '#')
    BEGIN
     WAsmCode[1] = EvalIntExpression((ArgStr[1])+1, Int16, &ok);
     decode_adr(ArgStr[2], 3, False);
     if ((!adr_ok) || (!ok)) return;
     CodeLen = 2;
     WAsmCode[0] = 0xa500 | adr_mode;          
     return;
    END

   WrError(1350); /* invalid addressing mode */
END

	static void DecodeCLRSETC(Word Index)
BEGIN
  bit_table_t *bitp;

  if (ArgCnt != 1)
   BEGIN
    WrError(1110);
    return;
   END

  WAsmCode[0] = Index; NLS_UpString(ArgStr[1]);

  for(bitp = bit_table; bitp->name; bitp++)
   if (!strcmp(ArgStr[1], bitp->name))
    BEGIN
     if (bitp->mincpu > MomCPU) WrError(1500);
     else
      BEGIN
       WAsmCode[0] |= bitp->code;
       CodeLen = 1;
      END
     return;
    END

  WrXError(1445, ArgStr[1]); /* invalid instruction */
END

	static void DecodeCMPRSPM(Word Index)
BEGIN
  Boolean ok;

  if (ArgCnt != 1)
   BEGIN
    WrError(1110);
    return;
   END

  WAsmCode[0] = Index | (EvalIntExpression(ArgStr[1], UInt2, &ok) & 3);
  if (!ok) return;
  CodeLen = 1;
END

	static void DecodeIO(Word Index)
BEGIN
  Boolean ok;

  if ((ArgCnt < 2) || (ArgCnt > 3))
   BEGIN
    WrError(1110);
    return;
   END

  decode_adr(ArgStr[1],3,False);
  if (!adr_ok) return;

  WAsmCode[1] = EvalIntExpression(ArgStr[2], UInt16, &ok);
  if (!ok) return;
  ChkSpace(SegIO);

  CodeLen = 2;
  WAsmCode[0] = Index | adr_mode;
END

	static void DecodeINTR(Word Index)
BEGIN
   Boolean ok;

   if (ArgCnt != 1)
    BEGIN
     WrError(1110);
     return;
    END

   WAsmCode[0] = EvalIntExpression(ArgStr[1], UInt5, &ok) | 0xbe60;
   if (!ok) return;
   CodeLen = 1;
END

	static void DecodeLACC(Word Index)
BEGIN
  Boolean ok;
  LongWord adr_long;
  Word Shift;

  if ((ArgCnt < 1) || (ArgCnt > 3))
   BEGIN
    WrError(1110);
    return;
   END

  if (*ArgStr[1] == '#')
   BEGIN
    if (ArgCnt > 2) WrError(1110);
    else
     BEGIN
      adr_long = EvalIntExpression(ArgStr[1] + 1, Int16, &ok);
      if (ok)
       BEGIN
        Shift = 0;
        adr_ok = True;
        if (ArgCnt > 1) 
         Shift = EvalIntExpression(ArgStr[2], UInt4, &adr_ok);
	if (adr_ok)
         BEGIN
          CodeLen = 2;
          WAsmCode[0] = 0xbf80 | (Shift & 0xf);
          WAsmCode[1] = adr_long;
         END
       END
     END
   END
  else
   BEGIN
    decode_adr(ArgStr[1], 3, False);
    if (adr_ok)
     BEGIN
      Shift = 0; ok = True;
      if (ArgCnt >= 2)
       Shift = DecodeShift(ArgStr[2], &ok);
      if (ok)
       BEGIN
        CodeLen = 1;
        if (Shift >= 16)
         WAsmCode[0] = 0x6a00 | adr_mode;
	else
         WAsmCode[0] = 0x1000 | ((Shift & 0xf) << 8) | adr_mode;
       END
     END
   END
END

	static void DecodeLACL(Word Index)
BEGIN
   Boolean ok;

   if (*ArgStr[1] == '#')
    BEGIN
     if (ArgCnt != 1) WrError(1110);
     else
      BEGIN
       WAsmCode[0] = EvalIntExpression(ArgStr[1] + 1, UInt8, &ok);
       if (!ok) return;
       CodeLen = 1;
       WAsmCode[0] |= 0xb900;	
      END
    END
   else
    BEGIN
     if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
     else
      BEGIN
       decode_adr(ArgStr[1], 2, False);
       if (adr_ok)
        BEGIN
         WAsmCode[0] = 0x6900 | adr_mode;
         CodeLen = 1;
        END
      END
    END
END

	static void DecodeLAR(Word Index)
BEGIN
   Word Reg;
   LongWord adr_long;
   Boolean ok;

   if ((ArgCnt < 2) || (ArgCnt > 3))
    BEGIN
     WrError(1110);
     return;
    END

   Reg = eval_ar_expression(ArgStr[1], &ok);
   if (!ok) return;

   if (*ArgStr[2] == '#')
    BEGIN
     if (ArgCnt > 2) WrError(1110);
     adr_long = EvalIntExpression(ArgStr[2] + 1, Int16,
   				     &adr_ok) & 0xffff;
     if (adr_ok)
      if (adr_long > 255)
       BEGIN
        CodeLen = 2;
        WAsmCode[0] = 0xbf08 | (Reg & 7);
        WAsmCode[1] = adr_long;
       END
      else
       BEGIN
   	CodeLen = 1;
   	WAsmCode[0] = 0xb000 | ((Reg & 7) << 8) | (adr_long & 0xff);
       END
    END
   else
    BEGIN
     decode_adr(ArgStr[2], 3, False);
     if (adr_ok)
      BEGIN
       CodeLen = 1;
       WAsmCode[0] = 0x0000 | ((Reg & 7) << 8) | adr_mode;
      END
    END
END

	static void DecodeLDP(Word Index)
BEGIN
   Word konst;
   Boolean ok;

   if (*ArgStr[1] == '#')
    BEGIN
     if (ArgCnt != 1) WrError(1110);
     else
      BEGIN
       konst = EvalIntExpression(ArgStr[1] + 1, UInt9, &ok);
       if (ok)
        BEGIN
         CodeLen = 1;
         WAsmCode[0] = (konst & 0x1ff) | 0xbc00;	
        END
      END
    END
   else
    BEGIN
     if ((ArgCnt != 1) AND (ArgCnt != 2)) WrError(1110);
     else
      BEGIN
       decode_adr(ArgStr[1], 2, False);
       if (adr_ok)
        BEGIN
         CodeLen = 1;
         WAsmCode[0] = 0x0d00 | adr_mode;
        END
      END
    END
END

	static void DecodeLSST(Word Index)
BEGIN
  Word konst;
  Boolean ok;

  if ((ArgCnt < 2) || (ArgCnt > 3))
   BEGIN
    WrError(1110);
    return;
   END

  if (*ArgStr[1] != '#')
   BEGIN
    WrError(1120); /* invalid instruction */
   END

  konst = EvalIntExpression(ArgStr[1] + 1, UInt1, &ok);
  decode_adr(ArgStr[2], 3, Index);
  if ((ok) AND (adr_ok))
   BEGIN
    CodeLen = 1;
    WAsmCode[0] = 0x0e00 | (Index << 15) | ((konst & 1) << 8) | adr_mode;
   END
END

	static void DecodeMAC(Word Index)
BEGIN
   Boolean ok;

   if ((ArgCnt < 2) OR (ArgCnt > 3))
    BEGIN
     WrError(1110);
     return;
    END

   WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
   ChkSpace(SegCode);

   decode_adr(ArgStr[2], 3, False);

   if ((adr_ok) AND (ok))
    BEGIN
     CodeLen = 2;
     WAsmCode[0] = 0xa200 | (Index << 8) | adr_mode;
    END
END

	static void DecodeMPY(Word Index)
BEGIN
   LongInt Imm;
   Boolean ok;

   if (*ArgStr[1] == '#')
    BEGIN
     if (ArgCnt != 1) WrError(1110);
     else
      BEGIN
       FirstPassUnknown = FALSE;
       Imm = EvalIntExpression(ArgStr[1] + 1, SInt16, &ok);
       if (FirstPassUnknown) Imm &= 0xfff;
       if (ok)
        if ((Imm < -4096) || (Imm > 4095))
         BEGIN
          if (MomCPU < cpu_32050) WrError(1500);
          else
           BEGIN
            CodeLen = 2;              /* What does that mean? */
            WAsmCode[0] = 0xbe80;
            WAsmCode[1] = Imm; 
           END
         END
        else
         BEGIN
          CodeLen = 1;
          WAsmCode[0] = 0xc000 | (Imm & 0x1fff);
         END
      END
    END
   else
    BEGIN
     if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
     else
      BEGIN
       decode_adr(ArgStr[1], 2, Index);
       if (adr_ok)
        BEGIN
         CodeLen = 1;
         WAsmCode[0] = 0x5400 | adr_mode;
        END
      END
    END
END

	static void DecodeNORM(Word Index)
BEGIN
  if ((ArgCnt < 1) || (ArgCnt > 2))
   BEGIN
    WrError(1110);
    return;
   END

  decode_adr(ArgStr[1], 2, False);
  if (adr_ok)
   if (adr_mode < 0x80) WrError(1350);
   else
    BEGIN
     CodeLen = 1;
     WAsmCode[0] = 0xa080 | (adr_mode & 0x7f);
    END
END

	static void DecodeRETC(Word Index)
BEGIN
   if (ArgCnt < 1) WrError(1110);
   else if ((Memo("RETCD")) AND (MomCPU < cpu_32050)) WrError(1500);
   else
    BEGIN
     CodeLen = 1;
     WAsmCode[0] = 0xec00 | (Index << 12) | decode_cond(1);
    END
END

	static void DecodeRPT(Word Index)
BEGIN
   Word Imm;
   Boolean ok;

   if (*ArgStr[1] == '#')
    BEGIN
     if (ArgCnt != 1) WrError(1110);
     else
      BEGIN
       Imm = EvalIntExpression(ArgStr[1] + 1, (MomCPU >= cpu_32050) ? UInt16 : UInt8, &ok);
       if (ok)
        if (Imm > 255)
         BEGIN
          CodeLen = 2;
          WAsmCode[0] = 0xbec4;
          WAsmCode[1] = Imm;
         END
        else
         BEGIN
          CodeLen = 1;
          WAsmCode[0] = 0xbb00 | (Imm & 0xff);
         END
      END
    END
   else
    BEGIN
     if ((ArgCnt != 1) AND (ArgCnt != 2)) WrError(1110);
     else
      BEGIN
       decode_adr(ArgStr[1], 2, False);
       if (adr_ok)
        BEGIN
         CodeLen = 1;
         WAsmCode[0] = 0x0b00 | adr_mode;
        END
      END
    END
END

	static void DecodeSAC(Word Index)
BEGIN
  Boolean ok;
  Word Shift;

  if ((ArgCnt < 1) || (ArgCnt > 3))
   BEGIN
    WrError(1110);
    return;
   END

  ok = True;
  Shift = 0;
  if (ArgCnt >= 2) 
   Shift = EvalIntExpression(ArgStr[2], UInt3, &ok);

  decode_adr(ArgStr[1], 3, False);

  if ((adr_ok) AND (ok))
   BEGIN
    CodeLen = 1;
    WAsmCode[0] = (Index << 11) | 0x9000 | adr_mode | ((Shift & 7) << 8);
   END
END

	static void DecodeSAR(Word Index)
BEGIN
  Word Reg;
  Boolean ok;

  if ((ArgCnt < 2) || (ArgCnt > 3))
   BEGIN
    WrError(1110);
    return;
   END

  Reg = eval_ar_expression(ArgStr[1], &ok);
  decode_adr(ArgStr[2], 3, False);

  if ((adr_ok) AND (ok))
   BEGIN
    CodeLen = 1;
    WAsmCode[0] = 0x8000 | ((Reg & 7) << 8) | adr_mode;
   END
END

	static void DecodeBSAR(Word Index)
BEGIN
   Word Shift;
   Boolean ok;

   if (ArgCnt != 1) WrError(1110);
   else if (MomCPU < cpu_32050) WrError(1500);
   else
    BEGIN
     FirstPassUnknown = False;
     Shift = EvalIntExpression(ArgStr[1], UInt5, &ok);
     if (FirstPassUnknown) Shift = 1;
     if (ok)
      if (ChkRange(Shift, 1, 16))
       BEGIN
        CodeLen = 1;
        WAsmCode[0] = 0xbfe0 | ((Shift - 1) & 0xf);
       END
    END
END

	static void DecodeLSAMM(Word Index)
BEGIN
   if ((ArgCnt < 1) OR (ArgCnt > 2)) WrError(1110);
   else if (MomCPU < cpu_32050) WrError(1500);
   else
    BEGIN
     decode_adr(ArgStr[1], 2, True);
     if (adr_ok)
      BEGIN
       CodeLen = 1;
       WAsmCode[0] = 0x0800 | (Index << 15) | adr_mode;
      END
    END
END

	static void DecodeLSMMR(Word Index)
BEGIN
   Boolean ok;

   if ((ArgCnt < 2) OR (ArgCnt > 3)) WrError(1110);
   else if (MomCPU < cpu_32050) WrError(1500);
   else if (ArgStr[2][0] != '#') WrError(1120);
   else
    BEGIN
     WAsmCode[1] = EvalIntExpression(ArgStr[2] + 1, Int16, &ok);
     decode_adr(ArgStr[1], 3, True);
     if ((adr_ok) AND (ok))
      BEGIN
       CodeLen = 2;
       WAsmCode[0] = 0x0900 | (Index << 15) | adr_mode;
      END
    END
END

	static void DecodeRPTB(Word Index)
BEGIN
   Boolean ok;

   if (ArgCnt != 1) WrError(1110);
   else if (MomCPU < cpu_32050) WrError(1500);
   else
    BEGIN
     WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
     if (ok)
      BEGIN
       CodeLen = 2;
       WAsmCode[0] = 0xbec6;
      END
    END
END

	static void DecodeRPTZ(Word Index)
BEGIN
   Boolean ok;

   if (ArgCnt != 1) WrError(1110);
   else if (MomCPU < cpu_32050) WrError(1500);
   else if (*ArgStr[1] != '#') WrError(1120);
   else
    BEGIN
     WAsmCode[1] = EvalIntExpression(ArgStr[1] + 1, Int16, &ok);
     if (ok)
      BEGIN
       CodeLen = 2;
       WAsmCode[0] = 0xbec5;
      END
    END
END

	static void DecodeXC(Word Index)
BEGIN
   Word Mode; 
   Boolean ok;

   if (ArgCnt < 2) WrError(1110);
   else if (MomCPU < cpu_32050) WrError(1500);
   else
    BEGIN
     FirstPassUnknown = False;
     Mode = EvalIntExpression(ArgStr[1], UInt2, &ok);
     if (ok)
      if ((Mode != 1) && (Mode != 2) && (!FirstPassUnknown)) WrError(1315);
      else
       BEGIN
        CodeLen = 1;
        WAsmCode[0] = (0xd400 + (Mode << 12)) | decode_cond(2);
       END
    END
END

/* ---------------------------------------------------------------------- */

static int instrz;

static void addfixed(char *nname, CPUVar mincpu, Word ncode)
{
	if (instrz>=cmd_fixed_cnt) exit(255);
	cmd_fixed_order[instrz].name = nname;
	cmd_fixed_order[instrz].mincpu = mincpu;
	cmd_fixed_order[instrz].code = ncode;
	AddInstTable(InstTable, nname, instrz++, DecodeFixed);
}

static void addadr(char *nname, CPUVar mincpu, Word ncode)
{
	if (instrz>=cmd_adr_cnt) exit(255);
	cmd_adr_order[instrz].name = nname;
	cmd_adr_order[instrz].mincpu = mincpu;
	cmd_adr_order[instrz].code = ncode;
	AddInstTable(InstTable, nname, instrz++, DecodeCmdAdr);
}

static void addjmp(char *nname, CPUVar mincpu, Word ncode, Boolean ncond)
{
	if (instrz>=cmd_jmp_cnt) exit(255);
	cmd_jmp_order[instrz].name = nname;
	cmd_jmp_order[instrz].mincpu = mincpu;
	cmd_jmp_order[instrz].code = ncode;
	cmd_jmp_order[instrz].cond = ncond;
	AddInstTable(InstTable, nname, instrz++, DecodeCmdJmp);
}

static void addplu(char *nname, CPUVar mincpu, Word ncode)
{
	if (instrz>=cmd_plu_cnt) exit(255);
	cmd_plu_order[instrz].name = nname;
	cmd_plu_order[instrz].mincpu = mincpu;
	cmd_plu_order[instrz].code = ncode;
	AddInstTable(InstTable, nname, instrz++, DecodeCmdPlu);
}

static void addadrmode(char *nname, CPUVar mincpu, Word nmode)
{
	if (instrz>=adr_mode_cnt) exit(255);
	adr_modes[instrz].name = nname;
	adr_modes[instrz].mincpu = mincpu;
	adr_modes[instrz++].mode= nmode;
}

static void addcond(char *nname, CPUVar mincpu, Word ncodeand, Word ncodeor, Byte niszl,
		    Byte nisc, Byte nisv, Byte nistp)
{
	if (instrz>=cond_cnt) exit(255);
	cond_tab[instrz].name = nname;
	cond_tab[instrz].mincpu = mincpu;
	cond_tab[instrz].codeand = ncodeand;
	cond_tab[instrz].codeor = ncodeor;
	cond_tab[instrz].iszl = niszl;
	cond_tab[instrz].isc = nisc;
	cond_tab[instrz].isv = nisv;
	cond_tab[instrz++].istp = nistp;
}

static void addbit(char *nname, CPUVar mincpu, Word ncode)
{
	if (instrz>=bit_cnt) exit(255);
	bit_table[instrz].name = nname;
	bit_table[instrz].mincpu = mincpu;
	bit_table[instrz++].code = ncode;
}

static void initfields(void)
{
	InstTable = CreateInstTable(203);

	cmd_fixed_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_fixed_cnt); instrz = 0;
	addfixed("ABS",    cpu_320203, 0xbe00); addfixed("ADCB",   cpu_32050 , 0xbe11);
	addfixed("ADDB",   cpu_32050 , 0xbe10); addfixed("ANDB",   cpu_32050 , 0xbe12);
	addfixed("CMPL",   cpu_320203, 0xbe01); addfixed("CRGT",   cpu_32050 , 0xbe1b);
	addfixed("CRLT",   cpu_32050 , 0xbe1c); addfixed("EXAR",   cpu_32050 , 0xbe1d);
	addfixed("LACB",   cpu_32050 , 0xbe1f); addfixed("NEG",    cpu_320203, 0xbe02);
	addfixed("ORB",    cpu_32050 , 0xbe13); addfixed("ROL",    cpu_320203, 0xbe0c);
	addfixed("ROLB",   cpu_32050 , 0xbe14); addfixed("ROR",    cpu_320203, 0xbe0d);
	addfixed("RORB",   cpu_32050 , 0xbe15); addfixed("SACB",   cpu_32050 , 0xbe1e);
	addfixed("SATH",   cpu_32050 , 0xbe5a); addfixed("SATL",   cpu_32050 , 0xbe5b);
	addfixed("SBB",    cpu_32050 , 0xbe18); addfixed("SBBB",   cpu_32050 , 0xbe19);
	addfixed("SFL",    cpu_320203, 0xbe09); addfixed("SFLB",   cpu_32050 , 0xbe16);
	addfixed("SFR",    cpu_320203, 0xbe0a); addfixed("SFRB",   cpu_32050 , 0xbe17);
	addfixed("XORB",   cpu_32050 , 0xbe1a); addfixed("ZAP",    cpu_32050 , 0xbe59);
	addfixed("APAC",   cpu_320203, 0xbe04); addfixed("PAC",    cpu_320203, 0xbe03);
	addfixed("SPAC",   cpu_320203, 0xbe05); addfixed("ZPR",    cpu_32050 , 0xbe58);
	addfixed("BACC",   cpu_320203, 0xbe20); addfixed("BACCD",  cpu_32050 , 0xbe21);
	addfixed("CALA",   cpu_320203, 0xbe30); addfixed("CALAD",  cpu_32050 , 0xbe3d);
	addfixed("NMI",    cpu_320203, 0xbe52); addfixed("RET",    cpu_320203, 0xef00);
	addfixed("RETD",   cpu_32050 , 0xff00); addfixed("RETE",   cpu_32050 , 0xbe3a);
	addfixed("RETI",   cpu_32050 , 0xbe38); addfixed("TRAP",   cpu_320203, 0xbe51);
	addfixed("IDLE",   cpu_320203, 0xbe22); addfixed("NOP",    cpu_320203, 0x8b00);
	addfixed("POP",    cpu_320203, 0xbe32); addfixed("PUSH",   cpu_320203, 0xbe3c);
	addfixed("IDLE2",  cpu_32050 , 0xbe23);

	cmd_adr_order = (cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_adr_cnt); instrz = 0;
	addadr("ADDC",   cpu_320203, 0x6000); addadr("ADDS",   cpu_320203, 0x6200);
	addadr("ADDT",   cpu_320203, 0x6300); addadr("LACT",   cpu_320203, 0x6b00);
        addadr("SUBB",   cpu_320203, 0x6400); addadr("SUBC",   cpu_320203, 0x0a00);
        addadr("SUBS",   cpu_320203, 0x6600); addadr("SUBT",   cpu_320203, 0x6700);
        addadr("ZALR",   cpu_320203, 0x6800); addadr("MAR",    cpu_320203, 0x8b00);
        addadr("LPH",    cpu_320203, 0x7500); addadr("LT",     cpu_320203, 0x7300);
        addadr("LTA",    cpu_320203, 0x7000); addadr("LTD",    cpu_320203, 0x7200);
        addadr("LTP",    cpu_320203, 0x7100); addadr("LTS",    cpu_320203, 0x7400);
        addadr("MADD",   cpu_32050 , 0xab00); addadr("MADS",   cpu_32050 , 0xaa00);
        addadr("MPYA",   cpu_320203, 0x5000); addadr("MPYS",   cpu_320203, 0x5100);
        addadr("MPYU",   cpu_320203, 0x5500); addadr("SPH",    cpu_320203, 0x8d00);
        addadr("SPL",    cpu_320203, 0x8c00); addadr("SQRA",   cpu_320203, 0x5200);
        addadr("SQRS",   cpu_320203, 0x5300); addadr("BLDP",   cpu_32050 , 0x5700);
        addadr("DMOV",   cpu_320203, 0x7700); addadr("TBLR",   cpu_320203, 0xa600);
        addadr("TBLW",   cpu_320203, 0xa700); addadr("BITT",   cpu_320203, 0x6f00);
        addadr("POPD",   cpu_320203, 0x8a00); addadr("PSHD",   cpu_320203, 0x7600);

	cmd_jmp_order=(cmd_jmp *) malloc(sizeof(cmd_jmp)*cmd_jmp_cnt); instrz=0;
	addjmp("B",      cpu_320203, 0x7980,  False);
        addjmp("BD",     cpu_32050 , 0x7d80,  False);
	addjmp("BANZ",   cpu_320203, 0x7b80,  False);
        addjmp("BANZD",  cpu_32050 , 0x7f80,  False);
	addjmp("BCND",   cpu_320203, 0xe000,  True);
        addjmp("BCNDD",  cpu_32050 , 0xf000,  True);
	addjmp("CALL",   cpu_320203, 0x7a80,  False);
        addjmp("CALLD",  cpu_32050 , 0x7e80,  False);
	addjmp("CC",     cpu_320203, 0xe800,  True);
        addjmp("CCD",    cpu_32050 , 0xf800,  True);

	cmd_plu_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_plu_cnt); instrz=0;
	addplu("APL",   cpu_32050 , 0x5a00); addplu("CPL",   cpu_32050 , 0x5b00);
	addplu("OPL",   cpu_32050 , 0x5900); addplu("SPLK",  cpu_320203, 0xaa00);
	addplu("XPL",   cpu_32050 , 0x5800);

	adr_modes=(adr_mode_t *) malloc(sizeof(adr_mode_t)*adr_mode_cnt); instrz=0;
	addadrmode( "*-",     cpu_320203, 0x90 ); addadrmode( "*+",     cpu_320203, 0xa0 );
	addadrmode( "*BR0-",  cpu_320203, 0xc0 ); addadrmode( "*0-",    cpu_320203, 0xd0 );
	addadrmode( "*AR0-",  cpu_32050 , 0xd0 ); addadrmode( "*0+",    cpu_320203, 0xe0 );
	addadrmode( "*AR0+",  cpu_32050 , 0xe0 ); addadrmode( "*BR0+",  cpu_320203, 0xf0 );
	addadrmode( "*",      cpu_320203, 0x80 ); addadrmode( NULL,     cpu_32050 , 0);

	cond_tab=(condition *) malloc(sizeof(condition)*cond_cnt); instrz=0;
	addcond("EQ",  cpu_32050 , 0xf33, 0x088, 1, 0, 0, 0);
	addcond("NEQ", cpu_32050 , 0xf33, 0x008, 1, 0, 0, 0);
	addcond("LT",  cpu_32050 , 0xf33, 0x044, 1, 0, 0, 0);
	addcond("LEQ", cpu_32050 , 0xf33, 0x0cc, 1, 0, 0, 0);
	addcond("GT",  cpu_32050 , 0xf33, 0x004, 1, 0, 0, 0);
	addcond("GEQ", cpu_32050 , 0xf33, 0x08c, 1, 0, 0, 0);
	addcond("NC",  cpu_32050 , 0xfee, 0x001, 0, 1, 0, 0);
	addcond("C",   cpu_32050 , 0xfee, 0x011, 0, 1, 0, 0);
	addcond("NOV", cpu_32050 , 0xfdd, 0x002, 0, 0, 1, 0);
	addcond("OV",  cpu_32050 , 0xfdd, 0x022, 0, 0, 1, 0);
	addcond("BIO", cpu_32050 , 0x0ff, 0x000, 0, 0, 0, 1);
	addcond("NTC", cpu_32050 , 0x0ff, 0x200, 0, 0, 0, 1);
	addcond("TC",  cpu_32050 , 0x0ff, 0x100, 0, 0, 0, 1);
	addcond("UNC", cpu_32050 , 0x0ff, 0x300, 0, 0, 0, 1);
	addcond(NULL,  cpu_32050 , 0xfff, 0x000, 0, 0, 0, 0);
	
	bit_table=(bit_table_t *) malloc(sizeof(bit_table_t)*bit_cnt); instrz=0;
	addbit("OVM",  cpu_320203, 0xbe42 ); addbit("SXM",  cpu_320203, 0xbe46 );
	addbit("HM",   cpu_32050 , 0xbe48 ); addbit("TC",   cpu_320203, 0xbe4a );
	addbit("C",    cpu_320203, 0xbe4e ); addbit("XF",   cpu_320203, 0xbe4c );
	addbit("CNF",  cpu_320203, 0xbe44 ); addbit("INTM", cpu_320203, 0xbe40 );
	addbit(NULL,   cpu_32050 , 0     );

	AddInstTable(InstTable, "ADD"  , 0, DecodeADDSUB);
	AddInstTable(InstTable, "SUB"  , 1, DecodeADDSUB);
	AddInstTable(InstTable, "ADRK" , 0, DecodeADRSBRK);
	AddInstTable(InstTable, "SBRK" , 1, DecodeADRSBRK);
	AddInstTable(InstTable, "AND"  , 0x6e01, DecodeLogic);
	AddInstTable(InstTable, "OR"   , 0x6d02, DecodeLogic);
	AddInstTable(InstTable, "XOR"  , 0x6c03, DecodeLogic);
        AddInstTable(InstTable, "BIT"  , 0, DecodeBIT);
	AddInstTable(InstTable, "BLDD" , 0, DecodeBLDD);
	AddInstTable(InstTable, "BLPD" , 0, DecodeBLPD);
	AddInstTable(InstTable, "CLRC" , 0, DecodeCLRSETC);
	AddInstTable(InstTable, "SETC" , 1, DecodeCLRSETC);
	AddInstTable(InstTable, "CMPR" , 0xbf44, DecodeCMPRSPM);
	AddInstTable(InstTable, "SPM"  , 0xbf00, DecodeCMPRSPM);
	AddInstTable(InstTable, "IN"   , 0xaf00, DecodeIO);
        AddInstTable(InstTable, "OUT"  , 0x0c00, DecodeIO);
	AddInstTable(InstTable, "INTR" , 0, DecodeINTR);
	AddInstTable(InstTable, "LACC" , 0, DecodeLACC);
	AddInstTable(InstTable, "LACL" , 0, DecodeLACL);
	AddInstTable(InstTable, "LAR"  , 0, DecodeLAR);
	AddInstTable(InstTable, "LDP"  , 0, DecodeLDP);
	AddInstTable(InstTable, "SST"  , 1, DecodeLSST);
	AddInstTable(InstTable, "LST"  , 0, DecodeLSST);
	AddInstTable(InstTable, "MAC"  , 0, DecodeMAC);
	AddInstTable(InstTable, "MACD" , 1, DecodeMAC);
	AddInstTable(InstTable, "MPY"  , 0, DecodeMPY);
	AddInstTable(InstTable, "NORM" , 0, DecodeNORM);
	AddInstTable(InstTable, "RETC" , 0, DecodeRETC);
	AddInstTable(InstTable, "RETCD", 1, DecodeRETC);
	AddInstTable(InstTable, "RPT"  , 0, DecodeRPT);
	AddInstTable(InstTable, "SACL" , 0, DecodeSAC);
	AddInstTable(InstTable, "SACH" , 1, DecodeSAC);
	AddInstTable(InstTable, "SAR"  , 0, DecodeSAR);
	AddInstTable(InstTable, "BSAR" , 0, DecodeBSAR);
        AddInstTable(InstTable, "LAMM" , 0, DecodeLSAMM);
        AddInstTable(InstTable, "SAMM" , 1, DecodeLSAMM);
	AddInstTable(InstTable, "LMMR" , 1, DecodeLSMMR);
	AddInstTable(InstTable, "SMMR" , 0, DecodeLSMMR);
	AddInstTable(InstTable, "RPTB" , 0, DecodeRPTB);
	AddInstTable(InstTable, "RPTZ" , 0, DecodeRPTZ);
	AddInstTable(InstTable, "XC"   , 0, DecodeXC);
}

static void deinitfields(void)
{
	DestroyInstTable(InstTable);
	free(cmd_fixed_order);
	free(cmd_adr_order);
	free(cmd_jmp_order);
	free(cmd_plu_order);
	free(adr_modes);
	free(cond_tab);
	free(bit_table);
}

/* ---------------------------------------------------------------------- */

static void pseudo_qxx(Integer num)
{
	int z;
	Boolean ok;
	double res;

	if (!ArgCnt) {
		WrError(1110);
		return;
	}
	for(z = 1; z <= ArgCnt; z++) {
		res = ldexp(EvalFloatExpression(ArgStr[z], Float64, &ok), num);
		if (!ok) {
			CodeLen = 0;
			return;
		}
		if ((res > 32767.49) || (res < -32768.49)) {
			CodeLen = 0;
			WrError(1320);
			return;
		}
		WAsmCode[CodeLen++] = res;
	}
}

/* ---------------------------------------------------------------------- */

static void pseudo_lqxx(Integer num)
{
	int z;
	Boolean ok;
	double res;
	LongInt resli;

	if (!ArgCnt) {
		WrError(1110);
		return;
	}
	for(z = 1; z <= ArgCnt; z++) {
		res = ldexp(EvalFloatExpression(ArgStr[z], Float64, &ok), num);
		if (!ok) {
			CodeLen = 0;
			return;
		}
		if ((res > 2147483647.49) || (res < -2147483647.49)) {
			CodeLen = 0;
			WrError(1320);
			return;
		}
		resli = res;
		WAsmCode[CodeLen++] = resli & 0xffff;
		WAsmCode[CodeLen++] = resli >> 16;
	}
}

/* ---------------------------------------------------------------------- */

static void define_untyped_label(void)
{
	if (LabPart[0]) {
		PushLocHandle(-1);
		EnterIntSymbol(LabPart, EProgCounter(), SegNone, False);
		PopLocHandle();
	}
}

/* ---------------------------------------------------------------------- */

static void wr_code_byte(Boolean *ok, int *adr, LongInt val)
{
	if ((val < -128) || (val > 0xff)) {
		WrError(1320);
		*ok = False;
		return;
	}
	WAsmCode[(*adr)++] = val & 0xff;
	CodeLen = *adr;
}

/* ---------------------------------------------------------------------- */

static void wr_code_word(Boolean *ok, int *adr, LongInt val)
{
	if ((val < -32768) || (val > 0xffff)) {
		WrError(1320);
		*ok = False;
		return;
	}
	WAsmCode[(*adr)++] = val;
	CodeLen = *adr;
}

/* ---------------------------------------------------------------------- */

static void wr_code_long(Boolean *ok, int *adr, LongInt val)
{
	WAsmCode[(*adr)++] = val & 0xffff;
	WAsmCode[(*adr)++] = val >> 16;
	CodeLen = *adr;
}

/* ---------------------------------------------------------------------- */

static void wr_code_byte_hilo(Boolean *ok, int *adr, LongInt val)
{
	if ((val < -128) || (val > 0xff)) {
		WrError(1320);
		*ok = False;
		return;
	}
	if ((*adr) & 1) 
		WAsmCode[((*adr)++)/2] |= val & 0xff;
	else 
		WAsmCode[((*adr)++)/2] = val << 8;
	CodeLen = ((*adr)+1)/2;
}

/* ---------------------------------------------------------------------- */

static void wr_code_byte_lohi(Boolean *ok, int *adr, LongInt val)
{
	if ((val < -128) || (val > 0xff)) {
		WrError(1320);
		*ok = False;
		return;
	}
	if ((*adr) & 1) 
		WAsmCode[((*adr)++)/2] |= val << 8;
	else 
		WAsmCode[((*adr)++)/2] = val & 0xff;
	CodeLen = ((*adr)+1)/2;
}

/* ---------------------------------------------------------------------- */

typedef void (*tcallback)(
#ifdef __PROTOS__
Boolean *, int *, LongInt
#endif
);

static void pseudo_store(tcallback callback)
{
	Boolean ok = True;
	int adr = 0;
	int z;
	TempResult t;
	unsigned char *cp;

	if (!ArgCnt) {
		WrError(1110);
		return;
	}
	define_untyped_label();
	for(z = 1; z <= ArgCnt; z++) {
		if (!ok)
			return;
		EvalExpression(ArgStr[z], &t);
		switch(t.Typ) {
		case TempInt:
			callback(&ok, &adr, t.Contents.Int);
			break;
		case TempFloat:
			WrError(1135);
			return;
		case TempString:
			cp = (unsigned char *)t.Contents.Ascii;
			while (*cp) 
				callback(&ok, &adr, CharTransTable[((usint)*cp++)&0xff]);
			break;
		default:
			WrError(1135);
			return;
		}
	}
}

/* ---------------------------------------------------------------------- */

static Boolean decode_pseudo(void)
{
	Word size;
	Boolean ok;
	TempResult t;
	int z,z2;
	unsigned char *cp;
	float flt;
	double dbl, mant;
	int exp;
	long lmant;
	Word w;

	if (Memo("PORT")) {
		CodeEquate(SegIO,0,65535);
		return True;
	}

	if (Memo("RES") || Memo("BSS")) {
		if (ArgCnt != 1) {
			WrError(1110);
			return True;
		}
		if (Memo("BSS"))
			define_untyped_label();
		FirstPassUnknown = False;
		size = EvalIntExpression(ArgStr[1], Int16, &ok);
		if (FirstPassUnknown) {
			WrError(1820);
			return True;
		}
		if (!ok) 
			return True;
		DontPrint = True;
		CodeLen = size;
		BookKeeping();
		return True;
	}

	if (Memo("DATA")) {
		if (!ArgCnt) {
			WrError(1110);
			return True;
		}
		ok = True;
		for(z = 1; (z <= ArgCnt) && ok; z++) {
			EvalExpression(ArgStr[z], &t);
			switch(t.Typ) {
			case TempInt:  
				if ((t.Contents.Int < -32768) || 
				   (t.Contents.Int > 0xffff)) {
					WrError(1320); 
					ok = False;
				} else
					WAsmCode[CodeLen++] = t.Contents.Int;
				break;
			default:
			case TempFloat:
				WrError(1135); 
				ok = False;
				break;
			case TempString:
				z2 = 0;
				cp = (unsigned char *)t.Contents.Ascii;
				while (*cp) {
					if (z2 & 1)
						WAsmCode[CodeLen++] |= 
							(CharTransTable[((usint)*cp++)&0xff]
							 << 8);
					else
						WAsmCode[CodeLen] = 
							CharTransTable[((usint)*cp++)&0xff];
					z2++;
				}
				if (z2 & 1)
					CodeLen++;
				break;
			}
		}
		if (!ok)
			CodeLen = 0;
		return True;
	}

	if (Memo("STRING")) {
		pseudo_store(wr_code_byte_hilo); 
		return True;
	}
	if (Memo("RSTRING")) {
		pseudo_store(wr_code_byte_lohi); 
		return True;
	}
	if (Memo("BYTE")) {
		pseudo_store(wr_code_byte); 
		return True;
	}
	if (Memo("WORD")) {
		pseudo_store(wr_code_word); 
		return True;
	}
	if (Memo("LONG")) {
		pseudo_store(wr_code_long); 
		return True;
	}

	/* Qxx */

	if ((OpPart[0] == 'Q') && (OpPart[1] >= '0') && (OpPart[1] <= '9') &&
	   (OpPart[2] >= '0') && (OpPart[2] <= '9') && (OpPart[3] == '\0')) {
		pseudo_qxx(10*(OpPart[1]-'0')+OpPart[2]-'0');
		return True;
	}

	/* LQxx */

	if ((OpPart[0] == 'L') && (OpPart[1] == 'Q') && (OpPart[2] >= '0') && 
	   (OpPart[2] <= '9') && (OpPart[3] >= '0') && (OpPart[3] <= '9') && 
	   (OpPart[4] == '\0')) {
		pseudo_lqxx(10*(OpPart[2]-'0')+OpPart[3]-'0');
		return True;
	}

	/* Floating point definitions */

	if (Memo("FLOAT")) {
		if (!ArgCnt) {
			WrError(1110);
			return True;
		}
		define_untyped_label();
		ok = True;
		for(z = 1; (z <= ArgCnt) && ok; z++) {
			flt = EvalFloatExpression(ArgStr[z], Float32, &ok);
			memcpy(WAsmCode+CodeLen, &flt, sizeof(float));
			if (BigEndian) {
				w = WAsmCode[CodeLen];
				WAsmCode[CodeLen] = WAsmCode[CodeLen+1];
				WAsmCode[CodeLen+1] = w;
			}
			CodeLen += sizeof(float)/2;
		}
		if (!ok)
			CodeLen = 0;
		return True;
	}

	if (Memo("DOUBLE")) {
		if (!ArgCnt) {
			WrError(1110);
			return True;
		}
		define_untyped_label();
		ok = True;
		for(z = 1; (z <= ArgCnt) && ok; z++) {
			dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
			memcpy(WAsmCode+CodeLen, &dbl, sizeof(dbl));
			if (BigEndian) {
				w = WAsmCode[CodeLen];
				WAsmCode[CodeLen] = WAsmCode[CodeLen+3];
				WAsmCode[CodeLen+3] = w;
				w = WAsmCode[CodeLen+1];
				WAsmCode[CodeLen+1] = WAsmCode[CodeLen+2];
				WAsmCode[CodeLen+2] = w;
			}
			CodeLen += sizeof(dbl)/2;
		}
		if (!ok)
			CodeLen = 0;
		return True;
	}

	if (Memo("EFLOAT")) {
		if (!ArgCnt) {
			WrError(1110);
			return True;
		}
		define_untyped_label();
		ok = True;
		for(z = 1; (z <= ArgCnt) && ok; z++) {
			dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
			mant = frexp(dbl, &exp);
			WAsmCode[CodeLen++] = ldexp(mant, 15);
			WAsmCode[CodeLen++] = exp-1;
		}
		if (!ok)
			CodeLen = 0;
		return True;
	}

	if (Memo("BFLOAT")) {
		if (!ArgCnt) {
			WrError(1110);
			return True;
		}
		define_untyped_label();
		ok = True;
		for(z = 1; (z <= ArgCnt) && ok; z++) {
			dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
			mant = frexp(dbl, &exp);
			lmant = ldexp(mant, 31);
			WAsmCode[CodeLen++] = (lmant & 0xffff);
			WAsmCode[CodeLen++] = (lmant >> 16);
			WAsmCode[CodeLen++] = exp-1;
		}
		if (!ok)
			CodeLen = 0;
		return True;
	}

	if (Memo("TFLOAT")) {
		if (!ArgCnt) {
			WrError(1110);
			return True;
		}
		define_untyped_label();
		ok = True;
		for(z = 1; (z <= ArgCnt) && ok; z++) {
			dbl = EvalFloatExpression(ArgStr[z], Float64, &ok);
			mant = frexp(dbl, &exp);
			mant = modf(ldexp(mant, 15), &dbl);
			WAsmCode[CodeLen+3] = dbl;
			mant = modf(ldexp(mant, 16), &dbl);
			WAsmCode[CodeLen+2] = dbl;
			mant = modf(ldexp(mant, 16), &dbl);
			WAsmCode[CodeLen+1] = dbl;
			mant = modf(ldexp(mant, 16), &dbl);
			WAsmCode[CodeLen] = dbl;
			CodeLen += 4;
			WAsmCode[CodeLen++] = ((exp - 1) & 0xffff);
			WAsmCode[CodeLen++] = ((exp - 1) >> 16);
		}
		if (!ok)
			CodeLen = 0;
		return True;
	}
	return False;
}

/* ---------------------------------------------------------------------- */

	static void make_code_3205x(void)
BEGIN
  CodeLen = 0; 
  DontPrint = False;

  /* zu ignorierendes */
     
  if (Memo("")) return;

  /* Pseudoanweisungen */

  if (decode_pseudo()) return;

  /* per Hash-Tabelle */

  if (NOT LookupInstTable(InstTable, OpPart)) WrXError(1200, OpPart);
}

/* ---------------------------------------------------------------------- */

static Boolean is_def_3205x(void)
{
	static const char *defs[] = { "BSS", "PORT", "STRING", "RSTRING", 
					      "BYTE", "WORD", "LONG", "FLOAT",
					      "DOUBLE", "EFLOAT", "BFLOAT", 
					      "TFLOAT", NULL }; 
	const char **cp = defs;

	while(*cp) {
		if (Memo(*cp))
			return True;
		cp++;
	}
	return False;
}

/* ---------------------------------------------------------------------- */

static void switch_from_3205x(void)
{
	deinitfields();
}

/* ---------------------------------------------------------------------- */

static void switch_to_3205x(void)
{
	TurnWords = False;
	ConstMode = ConstModeIntel; 
	SetIsOccupied = False;

	PCSymbol = "$";
	HeaderID = 0x77; 
	NOPCode = 0x8b00;
	DivideChars = ",";
	HasAttrs = False;

	ValidSegs = (1 << SegCode) | (1 << SegData) | (1 << SegIO);
	Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
        SegLimits[SegCode] = 0xffff;
	Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0;
        SegLimits[SegData] = 0xffff;
	Grans[SegIO  ] = 2; ListGrans[SegIO  ] = 2; SegInits[SegIO  ] = 0;
        SegLimits[SegIO  ] = 0xffff;
	
	MakeCode = make_code_3205x;
	IsDef = is_def_3205x; SwitchFrom = switch_from_3205x;
	initfields();
}

/* ---------------------------------------------------------------------- */

void code3205x_init(void)
{
	cpu_320203 = AddCPU("320C203", switch_to_3205x);
	cpu_32050  = AddCPU("320C50",  switch_to_3205x);
	cpu_32051  = AddCPU("320C51",  switch_to_3205x);
	cpu_32053  = AddCPU("320C53",  switch_to_3205x);

	AddCopyright("TMS320C5x-Generator (C) 1995/96 Thomas Sailer");
}
