aboutsummaryrefslogtreecommitdiffstats
path: root/code3202x.c
diff options
context:
space:
mode:
Diffstat (limited to 'code3202x.c')
-rw-r--r--code3202x.c1122
1 files changed, 1122 insertions, 0 deletions
diff --git a/code3202x.c b/code3202x.c
new file mode 100644
index 0000000..8e7fe9d
--- /dev/null
+++ b/code3202x.c
@@ -0,0 +1,1122 @@
+/*
+ * AS-Portierung
+ *
+ * AS-Codegeneratormodul fuer die Texas Instruments TMS320C2x-Familie
+ *
+ * (C) 1996 Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *
+ * 19.08.96: Erstellung
+ * 18.01.97: Anpassungen fuer Case-Sensitivitaet
+ * 7.07.1998 Fix Zugriffe auf CharTransTable wg. signed chars
+ * 18.08.1998 BookKeeping-Aufruf bei RES
+ * 9. 1.1999 ChkPC jetzt ueber SegLimits
+ */
+
+#include "stdinc.h"
+#include <string.h>
+#include <ctype.h>
+
+#include "strutil.h"
+#include "chunks.h"
+#include "asmdef.h"
+#include "asmsub.h"
+#include "asmpars.h"
+#include "codepseudo.h"
+#include "endian.h"
+
+#include "code3202x.h"
+
+/* ---------------------------------------------------------------------- */
+
+typedef struct {
+ char *name;
+ Word code;
+} cmd_fixed;
+typedef struct {
+ char *name;
+ Word code;
+ Boolean must1;
+} cmd_adr;
+typedef struct {
+ char *name;
+ Word code;
+ Word allow_shifts;
+} cmd_adr_shift;
+typedef struct {
+ char *name;
+ Word code;
+ Integer Min;
+ Integer Max;
+ Word mask;
+} cmd_imm;
+typedef struct {
+ char *name;
+ Word mode;
+} adr_mode_t;
+
+static cmd_fixed *cmd_fixed_order;
+#define cmd_fixed_cnt 38
+static cmd_fixed *cmd_jmp_order;
+#define cmd_jmp_cnt 17
+static cmd_adr *cmd_adr_order;
+#define cmd_adr_cnt 44
+static cmd_adr *cmd_adr_2ndadr_order;
+#define cmd_adr_2ndadr_cnt 5
+static cmd_adr_shift *cmd_adr_shift_order;
+#define cmd_adr_shift_cnt 7
+static cmd_imm *cmd_imm_order;
+#define cmd_imm_cnt 17
+static adr_mode_t *adr_modes;
+#define adr_mode_cnt 10
+
+static int instrz;
+
+static void addfixed(char *nname, Word ncode)
+{
+ if (instrz>=cmd_fixed_cnt) exit(255);
+ cmd_fixed_order[instrz].name=nname;
+ cmd_fixed_order[instrz++].code=ncode;
+}
+
+static void addjmp(char *nname, Word ncode)
+{
+ if (instrz>=cmd_jmp_cnt) exit(255);
+ cmd_jmp_order[instrz].name=nname;
+ cmd_jmp_order[instrz++].code=ncode;
+}
+
+static void addadr(char *nname, Word ncode, Boolean nmust1)
+{
+ if (instrz>=cmd_adr_cnt) exit(255);
+ cmd_adr_order[instrz].name=nname;
+ cmd_adr_order[instrz].code=ncode;
+ cmd_adr_order[instrz++].must1=nmust1;
+}
+
+static void add2ndadr(char *nname, Word ncode, Boolean nmust1)
+{
+ if (instrz>=cmd_adr_2ndadr_cnt) exit(255);
+ cmd_adr_2ndadr_order[instrz].name=nname;
+ cmd_adr_2ndadr_order[instrz].code=ncode;
+ cmd_adr_2ndadr_order[instrz++].must1=nmust1;
+}
+
+static void addshiftadr(char *nname, Word ncode, Word nallow)
+{
+ if (instrz>=cmd_adr_shift_cnt) exit(255);
+ cmd_adr_shift_order[instrz].name=nname;
+ cmd_adr_shift_order[instrz].code=ncode;
+ cmd_adr_shift_order[instrz++].allow_shifts=nallow;
+}
+
+static void addimm(char *nname, Word ncode, Integer nmin, Integer nmax,Word nmask)
+{
+ if (instrz>=cmd_imm_cnt) exit(255);
+ cmd_imm_order[instrz].name=nname;
+ cmd_imm_order[instrz].code=ncode;
+ cmd_imm_order[instrz].Min=nmin;
+ cmd_imm_order[instrz].Max=nmax;
+ cmd_imm_order[instrz++].mask=nmask;
+}
+
+static void addadrmode(char *nname, Word nmode)
+{
+ if (instrz>=adr_mode_cnt) exit(255);
+ adr_modes[instrz].name=nname;
+ adr_modes[instrz++].mode=nmode;
+}
+
+static void initfields(void)
+{
+ cmd_fixed_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_fixed_cnt); instrz=0;
+ addfixed("ABS", 0xce1b); addfixed("CMPL", 0xce27);
+ addfixed("NEG", 0xce23); addfixed("ROL", 0xce34);
+ addfixed("ROR", 0xce35); addfixed("SFL", 0xce18);
+ addfixed("SFR", 0xce19); addfixed("ZAC", 0xca00);
+ addfixed("APAC", 0xce15); addfixed("PAC", 0xce14);
+ addfixed("SPAC", 0xce16); addfixed("BACC", 0xce25);
+ addfixed("CALA", 0xce24); addfixed("RET", 0xce26);
+ addfixed("RFSM", 0xce36); addfixed("RTXM", 0xce20);
+ addfixed("RXF", 0xce0c); addfixed("SFSM", 0xce37);
+ addfixed("STXM", 0xce21); addfixed("SXF", 0xce0d);
+ addfixed("DINT", 0xce01); addfixed("EINT", 0xce00);
+ addfixed("IDLE", 0xce1f); addfixed("NOP", 0x5500);
+ addfixed("POP", 0xce1d); addfixed("PUSH", 0xce1c);
+ addfixed("RC", 0xce30); addfixed("RHM", 0xce38);
+ addfixed("ROVM", 0xce02); addfixed("RSXM", 0xce06);
+ addfixed("RTC", 0xce32); addfixed("SC", 0xce31);
+ addfixed("SHM", 0xce39); addfixed("SOVM", 0xce03);
+ addfixed("SSXM", 0xce07); addfixed("STC", 0xce33);
+ addfixed("TRAP", 0xce1e); addfixed(NULL, 0);
+
+ cmd_jmp_order=(cmd_fixed *) malloc(sizeof(cmd_fixed)*cmd_jmp_cnt); instrz=0;
+ addjmp("B", 0xff80); addjmp("BANZ", 0xfb80);
+ addjmp("BBNZ", 0xf980); addjmp("BBZ", 0xf880);
+ addjmp("BC", 0x5e80); addjmp("BGEZ", 0xf480);
+ addjmp("BGZ", 0xf180); addjmp("BIOZ", 0xfa80);
+ addjmp("BLEZ", 0xf280); addjmp("BLZ", 0xf380);
+ addjmp("BNC", 0x5f80); addjmp("BNV", 0xf780);
+ addjmp("BNZ", 0xf580); addjmp("BV", 0xf080);
+ addjmp("BZ", 0xf680); addjmp("CALL", 0xfe80);
+ addjmp(NULL, 0);
+
+ cmd_adr_order=(cmd_adr *) malloc(sizeof(cmd_adr)*cmd_adr_cnt); instrz=0;
+ addadr("ADDC", 0x4300, False); addadr("ADDH", 0x4800, False);
+ addadr("ADDS", 0x4900, False); addadr("ADDT", 0x4a00, False);
+ addadr("AND", 0x4e00, False); addadr("LACT", 0x4200, False);
+ addadr("OR", 0x4d00, False); addadr("SUBB", 0x4f00, False);
+ addadr("SUBC", 0x4700, False); addadr("SUBH", 0x4400, False);
+ addadr("SUBS", 0x4500, False); addadr("SUBT", 0x4600, False);
+ addadr("XOR", 0x4c00, False); addadr("ZALH", 0x4000, False);
+ addadr("ZALR", 0x7b00, False); addadr("ZALS", 0x4100, False);
+ addadr("LDP", 0x5200, False); addadr("MAR", 0x5500, False);
+ addadr("LPH", 0x5300, False); addadr("LT", 0x3c00, False);
+ addadr("LTA", 0x3d00, False); addadr("LTD", 0x3f00, False);
+ addadr("LTP", 0x3e00, False); addadr("LTS", 0x5b00, False);
+ addadr("MPY", 0x3800, False); addadr("MPYA", 0x3a00, False);
+ addadr("MPYS", 0x3b00, False); addadr("MPYU", 0xcf00, False);
+ addadr("SPH", 0x7d00, False); addadr("SPL", 0x7c00, False);
+ addadr("SQRA", 0x3900, False); addadr("SQRS", 0x5a00, False);
+ addadr("DMOV", 0x5600, False); addadr("TBLR", 0x5800, False);
+ addadr("TBLW", 0x5900, False); addadr("BITT", 0x5700, False);
+ addadr("LST", 0x5000, False); addadr("LST1", 0x5100, False);
+ addadr("POPD", 0x7a00, False); addadr("PSHD", 0x5400, False);
+ addadr("RPT", 0x4b00, False); addadr("SST", 0x7800, True);
+ addadr("SST1", 0x7900, True); addadr(NULL, 0, False);
+
+ cmd_adr_2ndadr_order=(cmd_adr *) malloc(sizeof(cmd_adr)*cmd_adr_2ndadr_cnt); instrz=0;
+ add2ndadr("BLKD", 0xfd00, False); add2ndadr("BLKP", 0xfc00, False);
+ add2ndadr("MAC", 0x5d00, False); add2ndadr("MACD", 0x5c00, False);
+ add2ndadr(NULL, 0, False);
+
+ cmd_adr_shift_order=(cmd_adr_shift *) malloc(sizeof(cmd_adr_shift)*cmd_adr_shift_cnt); instrz=0;
+ addshiftadr("ADD", 0x0000, 0xf); addshiftadr("LAC", 0x2000, 0xf);
+ addshiftadr("SACH", 0x6800, 0x7); addshiftadr("SACL", 0x6000, 0x7);
+ addshiftadr("SUB", 0x1000, 0xf); addshiftadr("BIT", 0x9000, 0xf);
+ addshiftadr(NULL, 0, 0);
+
+ cmd_imm_order=(cmd_imm *) malloc(sizeof(cmd_imm)*cmd_imm_cnt); instrz=0;
+ addimm("ADDK", 0xcc00, 0, 255, 0xff);
+ addimm("LACK", 0xca00, 0, 255, 0xff);
+ addimm("SUBK", 0xcd00, 0, 255, 0xff);
+ addimm("ADRK", 0x7e00, 0, 255, 0xff);
+ addimm("SBRK", 0x7f00, 0, 255, 0xff);
+ addimm("RPTK", 0xcb00, 0, 255, 0xff);
+ addimm("MPYK", 0xa000, -4096, 4095, 0x1fff);
+ addimm("SPM", 0xce08, 0, 3, 0x3);
+ addimm("CMPR", 0xce50, 0, 3, 0x3);
+ addimm("FORT", 0xce0e, 0, 1, 0x1);
+ addimm("ADLK", 0xd002, 0, 0x7fff, 0xffff);
+ addimm("ANDK", 0xd004, 0, 0x7fff, 0xffff);
+ addimm("LALK", 0xd001, 0, 0x7fff, 0xffff);
+ addimm("ORK", 0xd005, 0, 0x7fff, 0xffff);
+ addimm("SBLK", 0xd003, 0, 0x7fff, 0xffff);
+ addimm("XORK", 0xd006, 0, 0x7fff, 0xffff);
+ addimm(NULL, 0, 0, 0, 0);
+
+ adr_modes=(adr_mode_t *) malloc(sizeof(adr_mode_t)*adr_mode_cnt); instrz=0;
+ addadrmode( "*-", 0x90 ); addadrmode( "*+", 0xa0 );
+ addadrmode( "*BR0-", 0xc0 ); addadrmode( "*0-", 0xd0 );
+ addadrmode( "*AR0-", 0xd0 ); addadrmode( "*0+", 0xe0 );
+ addadrmode( "*AR0+", 0xe0 ); addadrmode( "*BR0+", 0xf0 );
+ addadrmode( "*", 0x80 ); addadrmode( NULL, 0);
+}
+
+static void deinitfields(void)
+{
+ free(cmd_fixed_order);
+ free(cmd_jmp_order);
+ free(cmd_adr_order);
+ free(cmd_adr_2ndadr_order);
+ free(cmd_adr_shift_order);
+ free(cmd_imm_order);
+ free(adr_modes);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Word adr_mode;
+static Boolean adr_ok;
+
+static CPUVar cpu_32025, cpu_32026, cpu_32028;
+
+/* ---------------------------------------------------------------------- */
+
+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 void decode_adr(char *arg, int aux, Boolean must1)
+{
+ const adr_mode_t *am = adr_modes;
+ Byte h;
+
+ adr_ok = False;
+ while (am->name && strcasecmp(am->name, arg))
+ am++;
+ if (!am->name) {
+ if (aux <= ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ h = EvalIntExpression(arg, Int16, &adr_ok);
+ if (!adr_ok)
+ return;
+ if (must1 && (h >= 0x80) && (!FirstPassUnknown)) {
+ WrError(1315);
+ adr_ok = False;
+ return;
+ }
+ adr_mode = h & 0x7f;
+ ChkSpace(SegData);
+ return;
+ }
+ adr_mode = am->mode;
+ if (aux <= ArgCnt) {
+ h = eval_ar_expression(ArgStr[aux], &adr_ok);
+ if (adr_ok)
+ adr_mode |= 0x8 | h;
+ } else
+ adr_ok = True;
+}
+
+/* ---------------------------------------------------------------------- */
+
+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(int 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, 15);
+ 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_3202x(void)
+{
+ Boolean ok;
+ Word adr_word;
+ LongInt adr_long;
+ const cmd_fixed *fo;
+ const cmd_adr *ao;
+ const cmd_adr_shift *aso;
+ const cmd_imm *io;
+
+ CodeLen = 0;
+ DontPrint = False;
+
+ /* zu ignorierendes */
+
+ if(Memo(""))
+ return;
+
+ /* Pseudoanweisungen */
+
+ if(decode_pseudo())
+ return;
+
+ /* prozessorspezifische Befehle */
+
+ if(Memo("CNFD")) {
+ if(ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ if(MomCPU == cpu_32026) {
+ WrError(1500);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = 0xce04;
+ return;
+ }
+
+ if(Memo("CNFP")) {
+ if(ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ if(MomCPU == cpu_32026) {
+ WrError(1500);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = 0xce05;
+ return;
+ }
+
+ if(Memo("CONF")) {
+ if(ArgCnt != 1) {
+ WrError(1110);
+ return;
+ }
+ if(MomCPU != cpu_32026) {
+ WrError(1500);
+ return;
+ }
+ WAsmCode[0] = 0xce3c|EvalIntExpression(ArgStr[1], UInt2, &ok);
+ if(ok)
+ CodeLen = 1;
+ return;
+ }
+
+ /* kein Argument */
+
+ for(fo = cmd_fixed_order; fo->name; fo++) {
+ if (Memo(fo->name)) {
+ if(ArgCnt) {
+ WrError(1110);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = fo->code;
+ return;
+ }
+ }
+
+ /* Spruenge */
+
+ for(fo = cmd_jmp_order; fo->name; fo++) {
+ if (Memo(fo->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ adr_mode = 0;
+ if(ArgCnt > 1) {
+ decode_adr(ArgStr[2], 3, False);
+ if(adr_mode < 0x80)
+ WrError(1350);
+ }
+ WAsmCode[1] = EvalIntExpression(ArgStr[1],
+ Int16, &ok);
+ if(ok) {
+ CodeLen = 2;
+ WAsmCode[0] = fo->code | (adr_mode & 0x7f);
+ }
+ return;
+ }
+ }
+
+ /* nur Adresse */
+
+ for(ao = cmd_adr_order; ao->name; ao++) {
+ if (Memo(ao->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 2)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 2, ao->must1);
+ if(adr_ok) {
+ CodeLen = 1;
+ WAsmCode[0] = ao->code | adr_mode;
+ }
+ return;
+ }
+ }
+
+ /* 2 Addressen */
+
+ for(ao = cmd_adr_2ndadr_order; ao->name; ao++) {
+ if (Memo(ao->name)) {
+ if((ArgCnt < 2) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ WAsmCode[1] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ decode_adr(ArgStr[2], 3, ao->must1);
+ if(ok && adr_ok) {
+ CodeLen = 2;
+ WAsmCode[0] = ao->code | adr_mode;
+ }
+ return;
+ }
+ }
+
+ /* Adresse & schieben */
+
+ for(aso = cmd_adr_shift_order; aso->name; aso++) {
+ if (Memo(aso->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 3, False);
+ if(!adr_ok)
+ return;
+ if(ArgCnt < 2) {
+ ok = True;
+ adr_word = 0;
+ } else {
+ adr_word = EvalIntExpression(ArgStr[2], Int4,
+ &ok);
+ if (ok && FirstPassUnknown)
+ adr_word = 0;
+ }
+ if(!ok)
+ return;
+ if(aso->allow_shifts < adr_word) {
+ WrError(1380);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = aso->code | adr_mode | (adr_word << 8);
+ return;
+ }
+ }
+
+ /* Ein/Ausgabe */
+
+ if((Memo("IN")) || (Memo("OUT"))) {
+ if((ArgCnt < 2) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 3, False);
+ if(!adr_ok)
+ return;
+ adr_word = EvalIntExpression(ArgStr[2], Int4, &ok);
+ if(!ok)
+ return;
+ ChkSpace(SegIO);
+ CodeLen = 1;
+ WAsmCode[0] = ((Memo("OUT")) ? 0xe000 : 0x8000) | adr_mode |
+ (adr_word << 8);
+ return;
+ }
+
+ /* konstantes Argument */
+
+ for(io = cmd_imm_order; io->name; io++) {
+ if (Memo(io->name)) {
+ if((ArgCnt < 1) || (ArgCnt > 2) ||
+ ((ArgCnt == 2) && (io->mask != 0xffff))) {
+ WrError(1110);
+ return;
+ }
+ adr_long = EvalIntExpression(ArgStr[1], Int32, &ok);
+ if(!ok)
+ return;
+ if(FirstPassUnknown)
+ adr_long &= io->mask;
+ if(io->mask == 0xffff) {
+ if(adr_long < -32768) {
+ WrError(1315);
+ return;
+ }
+ if(adr_long > 65535) {
+ WrError(1320);
+ return;
+ }
+ adr_word = 0;
+ ok = True;
+ if(ArgCnt == 2) {
+ adr_word = EvalIntExpression(ArgStr[2],
+ Int4,
+ &ok);
+ if(ok && FirstPassUnknown)
+ adr_word = 0;
+ }
+ if(!ok)
+ return;
+ CodeLen = 2;
+ WAsmCode[0] = io->code | (adr_word << 8);
+ WAsmCode[1] = adr_long;
+ return;
+ }
+ if(adr_long < io->Min) {
+ WrError(1315);
+ return;
+ }
+ if(adr_long > io->Max) {
+ WrError(1320);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = io->code | (adr_long & io->mask);
+ return;
+ }
+ }
+
+ /* mit Hilfsregistern */
+
+ if(Memo("LARP")) {
+ if(ArgCnt != 1) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ CodeLen = 1;
+ WAsmCode[0] = 0x5588 | adr_word;
+ return;
+ }
+
+ if((Memo("LAR")) OR (Memo("SAR"))) {
+ if((ArgCnt < 2) || (ArgCnt > 3)) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ decode_adr(ArgStr[2], 3, False);
+ if(!adr_ok)
+ return;
+ CodeLen = 1;
+ WAsmCode[0] = ((Memo("SAR")) ? 0x7000 : 0x3000) | adr_mode |
+ (adr_word << 8);
+ return;
+ }
+
+ if(Memo("LARK")) {
+ if(ArgCnt != 2) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ WAsmCode[0] = EvalIntExpression(ArgStr[2], Int8, &ok) & 0xff;
+ if(!ok)
+ return;
+ CodeLen = 1;
+ WAsmCode[0] |= 0xc000 | (adr_word << 8);
+ return;
+ }
+
+ if(Memo("LRLK")) {
+ if(ArgCnt != 2) {
+ WrError(1110);
+ return;
+ }
+ adr_word = eval_ar_expression(ArgStr[1], &ok);
+ if(!ok)
+ return;
+ WAsmCode[1] = EvalIntExpression(ArgStr[2], Int16, &ok);
+ if(!ok)
+ return;
+ CodeLen = 2;
+ WAsmCode[0] = 0xd000 | (adr_word << 8);
+ return;
+ }
+
+ if(Memo("LDPK")) {
+ if(ArgCnt != 1) {
+ WrError(1110);
+ return;
+ }
+ WAsmCode[0] = ConstIntVal(ArgStr[1], Int16, &ok);
+ if(ok && (!(WAsmCode[0] & (~0x1ff)))) { /* emulate Int9 */
+ CodeLen = 1;
+ WAsmCode[0] = (WAsmCode[0] & 0x1ff) | 0xc800;
+ return;
+ }
+ WAsmCode[0] = EvalIntExpression(ArgStr[1], Int16, &ok);
+ if(!ok)
+ return;
+ ChkSpace(SegData);
+ CodeLen = 1;
+ WAsmCode[0] = ((WAsmCode[0] >> 7) & 0x1ff) | 0xc800;
+ return;
+ }
+
+ if(Memo("NORM")) {
+ if((ArgCnt != 1)) {
+ WrError(1110);
+ return;
+ }
+ decode_adr(ArgStr[1], 2, False);
+ if(!adr_ok)
+ return;
+ if(adr_mode < 0x80) {
+ WrError(1350);
+ return;
+ }
+ CodeLen = 1;
+ WAsmCode[0] = 0xce82 | (adr_mode & 0x70);
+ return;
+ }
+
+ WrXError(1200, OpPart);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static Boolean is_def_3202x(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_3202x(void)
+{
+ deinitfields();
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void switch_to_3202x(void)
+{
+ TurnWords = False;
+ ConstMode = ConstModeIntel;
+ SetIsOccupied = False;
+
+ PCSymbol = "$";
+ HeaderID = 0x75;
+ NOPCode = 0x5500;
+ 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 ] = 0xf;
+
+ MakeCode = make_code_3202x;
+ IsDef = is_def_3202x; SwitchFrom = switch_from_3202x;
+ initfields();
+}
+
+/* ---------------------------------------------------------------------- */
+
+void code3202x_init(void)
+{
+ cpu_32025 = AddCPU("320C25", switch_to_3202x);
+ cpu_32026 = AddCPU("320C26", switch_to_3202x);
+ cpu_32028 = AddCPU("320C28", switch_to_3202x);
+
+ AddCopyright("TMS320C2x-Generator (C) 1994/96 Thomas Sailer");
+}