home *** CD-ROM | disk | FTP | other *** search
- /*
- Harvest C
- Copyright 1992 Eric W. Sink. All rights reserved.
-
- This file is part of Harvest C.
-
- Harvest C is free software; you can redistribute it and/or modify
- it under the terms of the GNU Generic Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Harvest C 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 Harvest C; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Harvest C is not in any way a product of the Free Software Foundation.
- Harvest C is not GNU software.
- Harvest C is not public domain.
-
- This file may have other copyrights which are applicable as well.
-
- */
-
- /*
- * Harvest C
- *
- * Copyright 1991 Eric W. Sink All rights reserved.
- *
- * Harvest C assembler module
- *
- *
- */
-
-
- #include "conditcomp.h"
- #include <stdio.h>
- #include <string.h>
- #include "structs.h"
- #include "as.h"
- #include "lookup.h"
- #include "regs.h"
-
- #pragma segment Assembler
-
- struct regs iregs[] =
- { /* pre-defined internal register names */
- #ifdef M68020
- "CAAR", CREG, CAAR,
- "caar", CREG, CAAR,
- "CACR", CREG, CACR,
- "cacr", CREG, CACR,
- "ISP", CREG, ISP,
- "isp", CREG, ISP,
- "MSP", CREG, MSP,
- "msp", CREG, MSP,
- #endif
- "DFC", CREG, DFC,
- "dfc", CREG, DFC,
- "SFC", CREG, SFC,
- "sfc", CREG, SFC,
- "USP", CREG, USP,
- "usp", CREG, USP,
- "VBR", CREG, VBR,
- "vbr", CREG, VBR,
-
- /* extended indexed addressing registers */
- "ZA0", ZAREG, 0,
- "za0", ZAREG, 0,
- "ZA1", ZAREG, 1,
- "za1", ZAREG, 1,
- "ZA2", ZAREG, 2,
- "za2", ZAREG, 2,
- "ZA3", ZAREG, 3,
- "za3", ZAREG, 3,
- "ZA4", ZAREG, 4,
- "za4", ZAREG, 4,
- "ZA5", ZAREG, 5,
- "za5", ZAREG, 5,
- "ZA6", ZAREG, 6,
- "za6", ZAREG, 6,
- "ZA7", ZAREG, 7,
- "za7", ZAREG, 7,
- "ZD0", ZDREG, 0,
- "zd0", ZDREG, 0,
- "ZD1", ZDREG, 1,
- "zd1", ZDREG, 1,
- "ZD2", ZDREG, 2,
- "zd2", ZDREG, 2,
- "ZD3", ZDREG, 3,
- "zd3", ZDREG, 3,
- "ZD4", ZDREG, 4,
- "zd4", ZDREG, 4,
- "ZD5", ZDREG, 5,
- "zd5", ZDREG, 5,
- "ZD6", ZDREG, 6,
- "zd6", ZDREG, 6,
- "ZD7", ZDREG, 7,
- "zd7", ZDREG, 7,
- "zpc", ZPC, 0,
- "ZPC", ZPC, 0,
-
- #ifdef FLOAT
- "FP0", FREG, 0,
- "fp0", FREG, 0,
- "FP1", FREG, 1,
- "fp1", FREG, 1,
- "FP2", FREG, 2,
- "fp2", FREG, 2,
- "FP3", FREG, 3,
- "fp3", FREG, 3,
- "FP4", FREG, 4,
- "fp4", FREG, 4,
- "FP5", FREG, 5,
- "fp5", FREG, 5,
- "FP6", FREG, 6,
- "fp6", FREG, 6,
- "FP7", FREG, 7,
- "fp7", FREG, 7,
- "FPCR", FCREG, FPCR,
- "fpcr", FCREG, FPCR,
- "FPSR", FCREG, FPSR,
- "fpsr", FCREG, FPSR,
- "FPIAR", FCREG, FPIAR,
- "fpiar", FCREG, FPIAR,
- #endif
-
- #ifdef PMMU
- "AC", PREG, AC,
- "ac", PREG, AC,
- "BAC0", PREG, BAC0,
- "bac0", PREG, BAC0,
- "BAC1", PREG, BAC1,
- "bac1", PREG, BAC1,
- "BAC2", PREG, BAC2,
- "bac2", PREG, BAC2,
- "BAC3", PREG, BAC3,
- "bac3", PREG, BAC3,
- "BAC4", PREG, BAC4,
- "bac4", PREG, BAC4,
- "BAC5", PREG, BAC5,
- "bac5", PREG, BAC5,
- "BAC6", PREG, BAC6,
- "bac6", PREG, BAC6,
- "BAC7", PREG, BAC7,
- "bac7", PREG, BAC7,
- "BAD0", PREG, BAD0,
- "bad0", PREG, BAD0,
- "BAD1", PREG, BAD1,
- "bad1", PREG, BAD1,
- "BAD2", PREG, BAD2,
- "bad2", PREG, BAD2,
- "BAD3", PREG, BAD3,
- "bad3", PREG, BAD3,
- "BAD4", PREG, BAD4,
- "bad4", PREG, BAD4,
- "BAD5", PREG, BAD5,
- "bad5", PREG, BAD5,
- "BAD6", PREG, BAD6,
- "bad6", PREG, BAD6,
- "BAD7", PREG, BAD7,
- "bad7", PREG, BAD7,
- "CAL", PREG, CAL,
- "cal", PREG, CAL,
- "CRP", PREG, CRP,
- "crp", PREG, CRP,
- "DRP", PREG, DRP,
- "drp", PREG, DRP,
- "PCSR", PREG, PCSR,
- "pcsr", PREG, PCSR,
- "PSR", PREG, PSR,
- "psr", PREG, PSR,
- "SCC", PREG, SCC,
- "scc", PREG, SCC,
- "SRP", PREG, SRP,
- "srp", PREG, SRP,
- "TC", PREG, TC,
- "tc", PREG, TC,
- "VAL", PREG, VAL,
- "val", PREG, VAL,
- "TT0", PREG, TT0,
- "tt0", PREG, TT0,
- "TT1", PREG, TT1,
- "tt1", PREG, TT1,
- #endif
-
- "A0", AREG, 0,
- "a0", AREG, 0,
- "A1", AREG, 1,
- "a1", AREG, 1,
- "A2", AREG, 2,
- "a2", AREG, 2,
- "A3", AREG, 3,
- "a3", AREG, 3,
- "A4", AREG, 4,
- "a4", AREG, 4,
- "A5", AREG, 5,
- "a5", AREG, 5,
- "A6", AREG, 6,
- "a6", AREG, 6,
- "A7", AREG, 7,
- "SP", AREG, 7,
- "a7", AREG, 7,
- "sp", AREG, 7,
- "D0", DREG, 0,
- "d0", DREG, 0,
- "D1", DREG, 1,
- "d1", DREG, 1,
- "D2", DREG, 2,
- "d2", DREG, 2,
- "D3", DREG, 3,
- "d3", DREG, 3,
- "D4", DREG, 4,
- "d4", DREG, 4,
- "D5", DREG, 5,
- "d5", DREG, 5,
- "D6", DREG, 6,
- "d6", DREG, 6,
- "D7", DREG, 7,
- "d7", DREG, 7,
- "CCR", SREG, CCR,
- "ccr", SREG, CCR,
- "SR", SREG, SR,
- "sr", SREG, SR,
- "PC", PC, 0,
- "pc", PC, 0,
- NULL, 0, 0
- };
-
- unsigned char *BitsBuffer;
- int BBIndex;
- int thesz; /* bitmap form of Ext */
- int Pass;
- int Pc = 0; /* Program Counter */
- int Old_pc = 0; /* Program Counter at
- * beginning */
- int Fwdsize = W; /* default fwd ref size */
-
- void
- MPW_Reference(unsigned char FlagsByte, unsigned short RefID, long
- offset, MPWListVia_t Records);
- unsigned short
- NameID(MPWDictListVia_t Dicts, char *name, unsigned char FlagsByte, int
- isdefined, MPWListVia_t Records);
-
- void Gen68Error(char *);
-
- /*
- * loword --- return low word of a long
- */
- int
- loword(long i)
- {
- return (i & 0xFFFF);
- }
-
- /*
- * hiword --- return high word of a long
- */
- int
- hiword(long i)
- {
- return ((i >> 16) & 0xFFFF);
- }
-
- /*
- * lobyte --- return low byte of an int
- */
- int
- lobyte(int i)
- {
- return (i & 0xFF);
- }
-
- /*
- * hibyte --- return high byte of a short int
- */
- int
- hibyte(int i)
- {
- return ((i >> 8) & 0xFF);
- }
-
- /*
- * reverse --- reverse the bits in an int
- *
- * Algorithm from Dr. Dobbs Journal #46, June/July 1980, p.48 Original by C.
- * Strachey [CACM 4:3 961 p.146]
- */
- int
- reverse(int val)
- {
- static int mask[] =
- {0x55555555, 0x33333333,
- 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
- register int i = val;
- register int j = 16;
- register int k = 4;
-
- while (j) {
- i = ((i & mask[k]) << j) | ((i >> j) & mask[k]);
- j >>= 1;
- k--;
- }
- return (i);
- }
-
-
- /*
- * emit --- emit a byte to code file
- */
- void
- emit(unsigned char bt)
- {
- Pc++;
- BitsBuffer[BBIndex++] = bt;
- }
-
-
- /*
- * eword --- emit a word to code file
- */
- void
- eword(int wd)
- {
- emit(hibyte(wd));
- emit(lobyte(wd));
- }
-
- /*
- * elong --- emit a long to code file
- */
- void
- elong(long wd)
- {
- eword(hiword(wd));
- eword(loword(wd));
- }
-
- /*
- * mne_lookOP --- mnemonic lookup
- *
- * Return pointer to an mne structure if found.
- */
- struct mne *
- mne_lookOP(Opcode_t OP)
- {
- register struct mne *low, *high;
- extern struct mne mnemonic[];
- extern int Nmne;
-
- low = &mnemonic[0];
- high = &mnemonic[Nmne - 1]; /* last entry in table is always empty */
- while (low <= high) {
- if (low->OP == OP)
- return low;
- low++;
- }
- return (NULL);
- }
-
- /*
- * mne_look --- mnemonic lookup
- *
- * Return pointer to an mne structure if found.
- */
- struct mne *
- mne_look(EString_t str)
- {
- register struct mne *low, *high, *mid;
- int cond;
- extern struct mne mnemonic[];
- extern int Nmne;
-
- low = &mnemonic[0];
- high = &mnemonic[Nmne - 1]; /* last entry in table is always empty */
- while (low <= high) {
- mid = low + (high - low) / 2;
- if ((cond = strcmp(Via(str), mid->mne_name)) < 0)
- high = mid - 1;
- else if (cond > 0)
- low = mid + 1;
- else
- return (mid);
- }
- return (NULL);
- }
-
-
- void
- PutEA(LocAMVia_t loc, struct ea * e)
- {
- if (!loc)
- return;
- if (!e)
- return;
- e->MPWRef = NULL;
- e->siz = 0;
- e->konst = 0;
- switch (GetLocAM(loc)) {
- #ifdef INLINEASM
- case M68am_OtherFormat:
- *e = Via(*(Via(loc)->OtherFormat));
- break;
- #endif
- case M68am_DReg:
- e->type = DN;
- e->reg = GetLocDReg(loc);
- break;
- case M68am_ARegDirect:
- e->type = AN;
- e->reg = GetLocAReg(loc);
- break;
- case M68am_ARegIndirect:
- e->type = ANI;
- e->reg = GetLocAReg(loc);
- break;
- case M68am_ARegPostInc:
- e->type = PSTINC;
- e->reg = GetLocAReg(loc);
- break;
- case M68am_ARegPreDec:
- e->type = PREDEC;
- e->reg = GetLocAReg(loc);
- break;
- case M68am_FSANEtemp:
- case M68am_ARegDisplaceFIELD:
- case M68am_ARegDisplace:
- e->type = INDEX;
- e->itype = D16AN;
- e->reg = GetLocAReg(loc);
- e->konst = GetLocConstant(loc);
- e->siz = 2;
- break;
- case M68am_ARegDispIndx:
- /* Not done */
- e->type = EMPTY;
- e->itype = D16AN;
- e->MPWRef = NULL;
- e->reg = GetLocAReg(loc);
- e->konst = 0;
- e->siz = 2;
- break;
- case M68am_AbsShort:
- e->type = EXPR;
- e->konst = GetLocConstant(loc);
- e->siz = 2;
- break;
- case M68am_AbsLong:
- e->type = EXPR;
- e->konst = GetLocConstant(loc);
- e->siz = 4;
- break;
- case M68am_PCLabelDisplace:
- e->type = PCINDEX;
- e->itype = D16AN;
- e->siz = 2;
- if (Via(GetLocLabel(loc))->M68kDef.where)
- e->konst = Via(Via(GetLocLabel(loc))->M68kDef.where)->Address;
- else
- e->konst = 0;
- break;
- case M68am_PCDisplace:
- e->type = PCINDEX;
- e->itype = D16AN;
- e->konst = GetLocConstant(loc);
- e->siz = 2;
- break;
- case M68am_PCDispIndx:
- /* Not done */
- e->type = EMPTY;
- e->itype = D16AN;
- e->MPWRef = NULL;
- e->reg = GetLocAReg(loc);
- e->konst = 0;
- e->siz = 2;
- break;
- case M68am_Immediate:
- e->type = IMMED;
- e->konst = GetLocConstant(loc);
- break;
- case M68am_MultReg* Not done */
- e->type = EMPTY;
- e->itype = D16AN;
- e->MPWRef = NULL;
- e->reg = GetLocAReg(loc);
- e->konst = 0;
- e->siz = 0;
- break;
- case M68am_SR:
- e->type = SR;
- break;
- case M68am_CCR:
- e->type = CCR;
- break;
- case M68am_USP:
- /* Not done */
- e->type = EMPTY;
- e->itype = D16AN;
- e->MPWRef = NULL;
- e->reg = GetLocAReg(loc);
- e->konst = 0;
- e->siz = 0;
- break;
- case M68am_Label:
- e->type = EXPR;
- e->MPWRef = GetLocLabel(loc);
- if (Via(GetLocLabel(loc))->M68kDef.where)
- e->konst = Via(Via(GetLocLabel(loc))->M68kDef.where)->Address;
- else
- e->konst = 0;
- e->siz = 2;
- break;
- case M68am_FReg:
- e->type = FN;
- e->reg = GetLocFReg(loc);
- break;
- case M68am_ARegLabelDisplace:
- e->type = INDEX;
- e->itype = D16AN; /* Unless we are using 68020 >32k globals */
- e->MPWRef = GetLocLabel(loc);
- e->reg = GetLocAReg(loc);
- e->konst = 0;
- e->siz = 2;
- break;
- case M68am_LargeGlobal:
- e->type = IMMED;
- e->MPWRef = GetLocLabel(loc);
- e->konst = 0;
- e->siz = 2;
- break;
- case M68am_WhatModeIsThis:
- default:
- /* Some sort of error here ? */
- break;
- }
- }
-
- #define MAXEA 30
-
- struct ea Eas[MAXEA] =
- {0}; /* parsed ea's */
- #define sDN (1<<DN)
- #define sAN (1<<AN)
- #define sANI (1<<ANI)
- #define sPREDEC (1<<PREDEC)
- #define sPSTINC (1<<PSTINC)
- #define sINDEX (1<<INDEX)
- #define sEXPR (1<<EXPR)
- #define sIMMED (1<<IMMED)
- #define sPCINDEX (1<<PCINDEX)
- #define sCN (1<<CN)
-
- /*
- * eatab --- bit map of legal modes for composite EA types
- */
- int eatab[] =
- {
- sDN | sAN, /* Rn */
- sDN | sAN | sANI | sPREDEC | sPSTINC | sINDEX | sEXPR | sIMMED | sPCINDEX, /* anyea */
- sANI | sINDEX | sEXPR | sPCINDEX, /* control */
- sANI | sPREDEC | sPSTINC | sINDEX | sEXPR, /* altmem */
- sDN | sANI | sPREDEC | sPSTINC | sINDEX | sEXPR, /* datalt */
- sDN | sAN | sANI | sPREDEC | sPSTINC | sINDEX | sEXPR, /* alter */
- sDN | sANI | sPREDEC | sPSTINC | sINDEX | sEXPR | sIMMED | sPCINDEX, /* data */
- sANI | sPREDEC | sINDEX | sEXPR, /-GÄh */
- sANI | sPSTINC | sINDEX | sEXPR | sPCINDEX, /* ctlpst */
- sANI | sINDEX | sEXPR, /* ctlalt */
- sANI | sPREDEC | sPSTINC | sINDEX | sEXPR | sIMMED | sPCINDEX, /* memory */
- sDN | sEXPR | sCN, /* PEA1 */
- 0 /* multi */
- };
-
- /*
- * eamatch --- match a general ea class against the specific operand
- *
- * gen is taken from the template, and spec comes from the type field of the
- * scanned ea. Gen classes less than RN are basic types, classes RN and
- * above are composite types. This routine will break if there are more
- * basic types than bits in an int.
- */
- int
- eamatch(int gen, int spec)
- {
- if (gen < RN)
- return (gen == spec);
- return (eatab[gen - RN] & (1 << spec));
- }
-
- /*
- * tmpl_match --- match size and operands of instruction
- *
- * Given a pointer to N entries in the template table, scan and try to match the
- * operand field of the line with one of them. Return NULL if nothing
- * matches, otherwise a pointer to the matching entry.
- *
- * A successful match will leave the processed operands in the Eas array. The
- * first unused entry in Eas will have a type of EMPTY.
- *
- * To be a successful match, the template must first match the size field. After
- * this, if the type is EMPTY the match is successful. Also, if the type is
- * MULTI, an open ended number of EXPR's will be scanned.
- */
- struct tmpl *
- tmpl_match(struct tmpl * p, int n, InstVia_t inst)
- {
- register struct ea *e = Eas;
-
- Eas[0].type = Eas[1].type = Eas[2].type = Eas[3].type = EMPTY;
-
- PutEA(Via(inst)->left, e++);
- PutEA(Via(inst)->right, e++);
-
- /* 1-4 ea's now in Eas */
-
- while (n--) {
- if ((thesz & p->sizes) &&
- eamatch(p->modes[0], Eas[0].type) &&
- eamatch(p->modes[1], Eas[1].type) &&
- eamatch(p->modes[2], Eas[2].type) &&
- eamatch(p->modes[3], Eas[3].type))
- return (p);
- p++;
- }
- return (NULL);
- }
-
-
- #define cpid(x) ((x)<<9) /* coprocessor id field */
-
- #ifdef PMMU
- int Ppid = cpid(0); /* PMMU coprocessor ID */†≈hU
-
- #ifdef FLOAT
-
- int Fpid = cpid(1); /* floating point coprocessor
- * ID */
- int o_fpid(), o_round(), o_prec();
-
- #endif
-
- /* range checking categories */
- #define UBYTE 0 /* unsigned byte */
- #define SBYTE 1 /* signed byte */
- #define XBYTE 2 /* extended byte */
- #define UWORD 3 /* unsigned word */
- #define SWORD 4 /* signed word */
- #define XWORD 5 /* extended word */
- #define QUK 6 /* quick value 1-8 */
- #define LOW3 7 /* 3 bit field */
- #define LOW4 8 /* 4 */
- #define LOW5 9 /* 5 */
- #define LOW6 10 /* 6 */
- #define LOW7 11 /* 7 */
- #define LOW7S 12 /* 7, signed */
-
- struct ranges {
- int r_min; /* minimum value allowed */
- int r_max; /* max. allowed */
- int r_mask; /* return value mask */
- };
-
- struct ranges ckrange[] =
- {
- 0, MAXUBYTE, 0x00FF,
- MINBYTE, MAXBYTE, 0x00FF,
- MINBYTE, MAXUBYTE, 0x00FF,
- 0, MAXUWORD, 0xFFFF,
- MINWORD, MAXWORD, 0xFFFF,
- MINWORD, MAXUWORD, 0xFFFF,
- 1, 8, 0x0007,
- 0, 7, 0x0007,
- 0, 15, 0x000F,
- 0, 31, 0x001F,
- 0, 63, 0x003F,
- 0, 127, 0x007F,
- -64, 63, 0x007F,
- };
-
- /*
- * fsizchk --- check that size of instruction matches src/dst
- */
- void
- fsizchk(struct ea * e)
- {
- if ((thesz & (D | X | P)) && e->type == DN)
- Gen68Error("Bad size");
- }
-
- /*
- * check --- verify that constant is within bounds
- */
- int
- check(int konst, int type)
- {
- int lo, hi;
-
- lo = ckrange[type].r_min;
- hi = ckrange[type].r_max;
- if (konst < lo || konst > hi) {
- /* TODO Generate a warning */
- }
- return (konst & ckrange[type].r_mask);
- }
-
- /*
- * size76 --- compute opcode bits 7 and 6 from thesz specifier
- */
- int
- size76(void)
- {
- int s = 0;
-
- switch (thesz) {
- case B:
- s = 0x00;
- break;
- case W:
- case U:
- s = 0x40;
- break;
- case L:
- s = 0x80;
- break;
- default:
- Gen68Error("Bad size in size76");
- åDç return (s);
- }
-
- /*
- * size109 --- compute opcode bits 10 and 9 from size specifier
- */
- int
- size109(void)
- {
- int s = 0;
-
- switch (thesz) {
- case B:
- s = 0x000;
- break;
- case W:
- case U:
- s = 0x200;
- break;
- case L:
- s = 0x400;
- break;
- default:
- Gen68Error("Bad size in size109");
- }
- return (s);
- }
-
- /*
- * size109b --- compute opcode bits 10 and 9 from size specifier (alternate)
- */
- int
- size109b(void)
- {
- int s = 0;
-
- switch (thesz) {
- case B:
- s = 0x200;
- break;
- case W:
- case U:
- s = 0x400;
- break;
- case L:
- s = 0x600;
- break;
- default:
- Gen68Error("Bad size in size109b");
- }
- return (s);
- }
-
- /*
- * adreg --- return 4 bit encoding for An or Dn (shift left by 12)
- */
- int
- adreg(struct ea * e)
- {
- int r = e->reg;
-
- if (e->type == AN)
- r += 8;
- return (r << 12);
- }
-
- /*
- * modreg --- generate mode/register field from ea structure
- *
- * return is a 6-bit field suitable for adding to a base opcode.
- */
- int
- modreg(struct ea * e)
- {
- register int mr = 0;
-
- switch (e->type) {
- case DN:
- mr = 000 + e->reg;
- break;
- case AN:
- mr = 010 + e->reg;
- break;
- case ANI:
- mr = 020 + e->reg;
- break;
- case PSTINC:
- mr = 030 + e->reg;
- break;
- case PREDEC:
- mr = 040 + e->reg;
- break;
- case INDEX:
- mr = e->itype == D16AN ? 050 + e->reg : 060 + e->reg;
- break;
- case IMMED:
- mr = 074;
- break;
- case EXPR:
- mr = e->siz == L ? 071 : 070;
- break;
- case PCINDEX:
- mr = e->itype == D16AN ? 072 : 073;
- break;
- default:
- Gen68Error("Bad type in modreg");
- }
- return (mr);
- }
-
- /*
- * genxreg --- generate index register spec for indexed postword
- */
- int
- genxreg(struct ea * e)
- {
- int wrd;
-
- wrd = e->stat2 ? 0x8000 : 0x0000;
- wrd += e->reg2 << 12;
- if (e->siz == L)
- wrd += (1 << 11);
- wrd += e->scl << 9;
- return (wrd);
- }
-
- /*
- * finish --- generate post-words for an instruction
- */
- void
- finish(struct ea ˇä„ if (e->MPWRef && Pass == 2) {
- int id;
- #ifdef OLDMEM
- HLock((Handle) e->MPWRef);
- #endif
- id = NameID(OBJNameList, Via(e->MPWRef)->name, 0, 0, GlobalRecords);
- #ifdef OLDMEM
- HUnlock((Handle) e->MPWRef);
- #endif
- MPW_Reference(128 + 16, id, Pc, GlobalRecords);
- }
- switch (e->type) {
- case DN:
- case AN:
- case ANI:
- case PSTINC:
- case PREDEC:
- break;
- case PCINDEX:
- e->konst -= Pc;
- case INDEX:
- switch (e->itype) {
- case D16AN:
- eword(check(e->konst, SWORD));
- break;
- case BRIEF:
- eword(genxreg(e) + check(e->konst, SBYTE));
- break;
- case FULL:
- if (e->xn_sup && e->prepst) /* reserved combination */
- e->prepst = 0;
- eword(genxreg(e) + 0x100 + (e->br_sup << 7) +
- (e->xn_sup << 6) + (e->bdsiz << 4) +
- (e->prepst << 2) + e->odsiz);
- switch (e->bdsiz) {
- case 1:
- break; /* supressed */
- case 2:
- eword(check(e->konst, SWORD));
- break;
- case 3:
- elong(e->konst);
- break;
- default:
- Gen68Error("finish1");
- }
- switch (e->odsiz) {
- case 0: /* to allow An indirect w/ index */
- case 1:
- break; /* supressed */
- case 2:
- eword(check(e->const2, SWORD));
- break;
- case 3:
- elong(e->const2);
- break;
- default:
- Gen68Error("finish2");
- }
- break;
- default:
- Gen68Error("finish3");
- }
- break;
- case IMMED:
- if (thesz == L)
- elong(e->konst);
- else
- eword(e->konst); /* note: no range check here */
- break;
- case EXPR:
- if (e->siz == L)
- elong(e->konst);
- else
- eword(check(e->konst, SWORD));
- break;
- default:
- Gen68Error("finish4");
- }
- }
-
- /*
- * fsize --- return encoded size for floating point ea
- */
- int
- fsize(void)
- {
- int sz = 0;
-
- switch (thesz) {
- case L:
- sz = 0x0000;
- break;
- case S:
- sz = 0x0400;
- break;
- case X:
- sz = 0x0800;
- break;
- case P:
- sz = 0x0C00;
- break;
- case W:
- sz = 0x1000;
- break;
- case D:
- sz = 0x1400;
- break;
- case B:
- sz = 0x1800;
- break;
- /* case P: sz = 0x1C00; break; ~zñz d? */
- default:
- Gen68Error("Bad size in fsize");
- }
- return (sz);
- }
-
- /*
- * checkfclist --- look for invalid fclist combinations
- *
- * Dn addressing allowed on ea only if there is a single register in the list.
- * An addressing is allowed only if the single register FPIAR is specified.
- */
- void
- checkfclist(int r, struct ea * e)
- { /* r is a register list */
- if (e->type == AN && (r & (FPCR | FPSR)))
- Gen68Error("An addressing allowed only on FPIAR");
- else if (e->type == DN) {
- if (r != FPCR && r != FPSR && r != FPIAR)
- Gen68Error("Only a single FP ctrl. reg may be selected");
- }
- }
-
- /*
- * getrlist --- return register list mask for an EA
- */
- int
- getrlist(struct ea * e)
- {
- int rlist = 0;
-
- switch (e->type) {
- case AN:
- rlist = 1 << (e->reg + 8);
- break;
- case DN:
- rlist = 1 << e->reg;
- break;
- case RLIST:
- rlist = e->reg;
- break;
- default:
- Gen68Error("getrlist");
- }
- return (rlist);
- }
-
- /*
- * bitfld --- return bit field extension word
- */
- int
- bitfld(struct ea * e, int r)
- {
- int offset, width;
-
- if (e->type != FIELD)
- Gen68Error("Botch in bitfld");
-
- if (e->stat)
- offset = check(e->konst, LOW5);
- else
- offset = e->reg + 0x20;
-
- if (e->stat2)
- width = check(e->const2, LOW5);
- else
- width = e->reg2 + 0x20;
-
- return ((r << 12) + (offset << 6) + width);
- }
-
- /*
- * do_op --- process mnemonic
- */
- void
- do_op(int opclass, int op, int op2)
- {
- extern struct ea Eas[];
- register struct ea *ea1 = &Eas[0];
- register struct ea *ea2 = &Eas[1];
- register struct ea *ea3 = &Eas[2];
- register int tmp;
- register int dist; /* distance on branches */
- register int rlist; /* bit map of register list */
-
- switch (opclass) {
- case INH: /* inherent */
- eword(op);
- break;
-
- case RXRY: /* Rx and Ry, no size */
- eword(op + (ea2->reg << 9) + ea1->reg);
- break;
-
- case RXRYS: xKü7 nd Ry, sized */
- eword(op + (ea2->reg << 9) + size76() + ea1->reg);
- break;
-
- case RXRYR: /* Rx and Ry, reversed */
- eword(op + (ea1->reg << 9) + ea2->reg);
- break;
-
- case RXRYP: /* Rx and Ry, pack/unpack */
- eword(op + (ea2->reg << 9) + ea1->reg);
- eword(check(ea3->konst, UWORD));
- break;
-
- case EAREG: /* ea to register */
- eword(op + (ea2->reg << 9) + modreg(ea1));
- finish(ea1);
- break;
-
- case EAREGS: /* ea to register, sized */
- eword(op + (ea2->reg << 9) + size76() + modreg(ea1));
- finish(ea1);
- break;
-
- case REGEA: /* register to ea */
- eword(op + (ea1->reg << 9) + modreg(ea2));
- finish(ea2);
- break;
-
- case REGEAS: /* register to ea, signed */
- eword(op + (ea1->reg << 9) + size76() + modreg(ea2));
- finish(ea2);
- break;
-
- case IMMEAS: /* immediate to ea, sized */
- eword(op + size76() + modreg(ea2));
- if (thesz == L)
- elong(ea1->konst);
- else
- eword(ea1->konst);
- finish(ea2);
- break;
-
- case QUKEA: /* quick immediate to ea */
- if ((thesz & B) && ea2->type == AN)
- Gen68Error("Byte not allowed to address reg.");
- eword(op + (check(ea1->konst, QUK) << 9) + size76() + modreg(ea2));
- finish(ea2);
- break;
-
- case IMMB: /* immediate byte */
- eword(op);
- eword(check(ea1->konst, UBYTE));
- break;
-
- case IMMW: /* immediate word */
- eword(op);
- eword(check(ea1->konst, XWORD));
- break;
-
- case IMMWS: /* immediate word, signed */
- eword(op);
- eword(check(ea1->konst, SWORD));
- break;
-
- case IMM3: /* immediate value, 3 bits */
- eword(op + check(ea1->konst, LOW3));
- break;
-
- case IMM4: /* immediate value, 4 bits */
- eword(op + check(ea1->konst, LOW4));
- break;
-
- case RSHIFT: /* register shift */
- eword(op + (ea1->reg << 9) + size76() + ea2->reg);
- break;
-
- case QSHIFT: /* immediate (quick fmt) shift */
- eword(op + (check(ea1->konst, QUK) << 9) + size76() + ea2->reg);
- break;
-
- case EA: /* ea */
- eword(op + modreg(ea1));
- finish(ea1);
- break;
-
- case EAREV: /* ea, reversed */
- eword(op + modreg(ea2));
- finish(ea2);
- break;
-
- case EAS: ‚cz• ized */
- eword(op + size76() + modreg(ea1));
- finish(ea1);
- break;
-
- case BCC: /* conditional branches */
- dist = ea1->konst - (Pc + 2); /* TODO See if word and long branches
- * work */
- #ifdef UNDEFINED
- if (thesz == U && ea1->force)
- thesz = Fwdsize;
- if (thesz == U) {
- if (dist < MINWORD || dist > MAXWORD)
- thesz = L;
- else if (dist < MINBYTE || dist > MAXBYTE)
- thesz = W;
- else
- thesz = B;
- }
- #else
- thesz = W;
- #endif
- switch (thesz) {
- case B:
- if (dist == 0 || dist == -1)
- Gen68Error("Bad branch destination");
- eword(op + check(dist, SBYTE));
- break;
- case W:
- if (dist == 0 || dist == -1)
- Gen68Error("Bad branch destination");
- eword(op);
- eword(check(dist, SWORD));
- break;
- case L:
- eword(op + 0xFF);
- elong(dist);
- break;
- }
- break;
-
- case BIT: /* single bit manipulation */
- eword(op + modreg(ea2));
- eword(check(ea1->konst, LOW5));
- finish(ea2);
- break;
-
- case BITFLD: /* bit fields */
- eword(op + modreg(ea1));
- eword(bitfld(ea2, 0)); /* {Dn/#:Dn/#} formatted word */
- finish(ea1);
- break;
-
- case BITFLD2: /* bit fields, second format */
- if (ea2->type == FIELD) {
- eword(op + modreg(ea1));
- eword(bitfld(ea2, ea3->reg)); /* {Dn/#:Dn/#} formatted word */
- finish(ea1);
- } else { /* bfins is backwards */
- eword(op + modreg(ea2));
- eword(bitfld(ea3, ea1->reg)); /* {Dn/#:Dn/#} formatted word */
- finish(ea2);
- }
- break;
-
- case CALLM: /* callm */
- eword(op + modreg(ea2));
- eword(check(ea1->konst, UBYTE));
- finish(ea2);
- break;
-
- case CAS: /* cas */
- eword(op + size109b() + modreg(ea3));
- eword((ea2->reg << 6) + ea1->reg);
- finish(ea3);
- break;
-
- case CAS2: /* cas2 */
- eword(op + size109b());
- if (ea3->stat)
- ea3->reg += 8;
- eword((ea3->reg << 12) + (ea2->reg << 6) + ea1->reg);
- if (ea3->stat2)
- ea3->reg2 += 8;
- eword((ea3->reg2 << 12) + (ea2->reg2 << 6) + ea1->reg2);
- break;
-
- case CHK: /* chk */
- if (thesz != L)
- op |= 0x0080;
- eword(op + (ea2->reg << 9) + modreg(ea1));
- fR: