• R/O
  • HTTP
  • SSH
  • HTTPS

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A complete (I think) set of code generator macros to generate published op-codes


File Info

Révision b281f65ed7aeceaaf5feefa53f71dc6a4c0a99ac
Taille 18,047 octets
l'heure 2020-10-08 20:37:04
Auteur Joel Matthew Rees
Message de Log

As it survived the trip across the Mac and ocean

Content

/* code generation for the MC68000 and 68010 */
/* written for CS431 by Joel Matthew Rees, at BYU, January 1988 */
/* Assigned by the author to the public domain, February 2000, Takino, Japan. */
/* joel_rees@sannet.ne.jp */
/* http://www.page.sannet.ne.jp/joel_rees */
/* unsigned short integer should be 16 bits for native machine compile */
/* not designed for cross-compiling */

/* flag that this pass is on the code generator */
#define IS_code
#include "code.h"

/* allocation spaces */
static CODE code_array[MAXCODE];
CODE *cap = code_array;
static CODE *catop = &(code_array[MAXCODE]);
static CODE data_array[MAXDATA];
CODE *dap = data_array;
static CODE *datop = &(data_array[MAXDATA]);

/* parameters for code generators: */
/* unsigned short integer code; (cd) */
/* integer size; (sz) */
/* integer mode; (sm, mx, dm, my) containing mode and register bits */
/* integer register; (reg) containing register bits only */
/* integer index register; (sx, dx, ix) */
/*	per the 68000 index extension word */
/* long integer immediate value/offset/absolute address; */
/*	(svo, sao, soff, dvo, dao, doff, offs, addr) */
/* integer condition; (cc) for conditionals */

int _gcode(cd) /* push machine code words into the code array */
register CODE cd;
{  register int err = 0;
   register CODE *pt = cap;

   if (pt < catop)
   {  *pt++ = cd;
      cap = pt;
   }
   else
      err = CERRcful;
   return(err);
}

/* generate extension words: check errors & order before using! */
static int extension(size, mode, ix, offs) /* one extension at a time! */
register int size, mode, ix;
register long offs;
{  register int err = 0;

   if ((mode & 070) == E_AnXi || mode == E_pcXi) /* index word */
      err = _gcode((CODE) ((ix & 0xf800) | (offs & 0xff)));
   else if (mode >= E_InOFF) /* offset/address/immediate word */
   {  if (mode == E_ABSl || (mode == E_IMM && size == CLONG))
	 err = _gcode((CODE) (offs >> 16)); /* high word */
      if (mode == E_IMM && size == CBYTE)
	 offs &= 0xff;
      err = _gcode((CODE) offs); /* low word */
   }
   return(err); /* only code array full errors produced here */
}

/* macro for generating effective address fields */
/* part is (mode & 070), usually in a register */
#define EA(mode, part) \
(((mode) < E_ABSw) ? ((part) | ((mode) & 7)) : ((mode) & 077))

int fillpcR(md, pcat) /* fill in pc relative address, after instruction */
int md;
register CODE *pcat;
{  register long disp = (long) cap - (long) pcat - 2; /* offset */
   register int err = 0;

   pcat++; /* bump to extension word */
   if (md == E_pcXi)
      if (disp > -0x80 && disp < 0x7f)
      {  *pcat &= 0xff00; /* clear previous offset byte */
         *pcat |= (char) disp;
      }
      else
	 err = CERRddtl;
   else if (md == E_pcOFF)
      if (disp > (long) -0x8000 && disp < (long) 0x7fff)
         *pcat = (CODE) disp;
      else
	 err = CERRddtl;
   else
      err = CERRdmna;
   return(err);
}

int fillB(sz, brat) /* fill in pc relative address, after branch */
int sz;
register CODE *brat;
{  register long disp = (long) cap - (long) brat - 2; /* offset */
   register int err = 0;

   *brat &= 0xff00; /* clear previous offset byte (long branch has problems with this) */
   if (sz == CBYTE)
      if (disp > -0x80 && disp < 0x7f)
         *brat |= (char) disp;
      else
	 err = CERRddtl;
   else if (sz == CWORD)
      if (disp > (long) -0x8000 && disp < (long) 0x7fff)
	 *(++brat) = (CODE) disp; /* bump to word offset first */
      else
	 err = CERRddtl;
   else
      err = CERRszna;
   return(err);
}

int genB(cc, addr) /* Branch to address on condition */
register int cc;
register CODE *addr;
{  register CODE cd = 0x6000 | (cc & 0xf00); /* strip other bits */
   register int err = 0;
   register long disp = (long) addr - (long) cap - 2; /* offset */

   if (cc == cc_F) /* cc_SUB != cc_F => cc_SUB can be encoded */
      err = CERRopna;
   else
      if (disp > -0x80 && disp < 0x7f)
	 err = _gcode((CODE) (cd | (disp & 0xff)));
      else if (disp > (long) -0x8000 && disp < (long) 0x7fff)
      {  err = _gcode(cd);
	 err = _gcode((CODE) disp);
      }
      else
	 err = CERRddtl;
   return(err);
}

int genDB(cc, reg, addr) /* Decrement word reg, Branch on ~cc to a */
register int cc;
register int reg;
register CODE *addr;
{  register CODE cd = 0x50c8 | (cc & 0xf00) | (reg & 7);
   register err = 0;
   register long disp = (long) addr - (long) cap - 2; /* offset */

   if (disp > (long) -0x8000 && disp < (long) 0x8000)
   {  err = _gcode(cd);
      err = _gcode((CODE) disp);
   }
   else
      err = CERRddtl;
   return(err);
}

int genS(cc, dm, dx, dao) /* Set conditional, byte only */
int cc; /* a unary operator with a condition and only one size */
register int dm;
int dx;
long dao;
{  register CODE cd = 050300 | (cc & 0xf00);
   register int err = 0;
   register int pdm = dm & 070; /* partial */

   if (pdm == E_An || dm > E_ABSl)
      err = CERRdmna;
   else
   {  err = _gcode((CODE) (cd | EA(dm, pdm)));
      err = extension(CUNSPEC, dm, dx, dao);
   }
   return(err);
}

int genEXG(mx, my) /* EXchanGe two registers */
register int mx, my; /* mode is (E_An | n) or (E_Dn | n) */
{  register CODE cd = 0140400;
   register int pmx = mx & 070;
   register int pmy = my & 070;
   register int err = 0;

   if (pmx == E_An)
      if (pmy == E_An)
	 err = _gcode((CODE) (cd | 0110 | ((my & 7) << 9) | (mx & 7)));
      else if (pmy == E_Dn)
	 err = _gcode((CODE) (cd | 0210 | ((my & 7) << 9) | (mx & 7)));
      else
	 err = CERRsdi;
   else if (pmx == E_Dn)
      if (pmy == E_Dn)
	 err = _gcode((CODE) (cd | 0100 | ((mx & 7) << 9) | (my & 7)));
      else if (pmy == E_An)
	 err = _gcode((CODE) (cd | 0210 | ((mx & 7) << 9) | (my & 7)));
      else
	 err = CERRsdi;
   else
      err = CERRsmna | CERRsmna;
   return(err);
}

int genMOVEC(sm, dm) /* 68010 superviser only access to Control regs */
register int sm, dm; /* mode is (E_An | n) or (E_Dn | n) or CTL reg */
{  register int err = 0;

   if (E_CTL(sm))
      if (dm < E_In)
	 if ((dm & 070) == E_An && sm == E_USP) /* optimize to MOVE USP */
	    err = _gcode((CODE) (047150 | (dm & 7)));
	 else
	 {  err = _gcode(047172);
	    err = _gcode((CODE) (((dm & 017) << 12) | (sm & 0xfff)));
	 }
      else
	 err = CERRdmna;
   else if (E_CTL(dm))
      if (sm < E_In)
	 if ((sm & 070) == E_An && dm == E_USP) /* optimize to MOVE USP */
	    err = _gcode((CODE) (047140 | (sm & 7)));
	 else
	 {  err = _gcode(047173);
	    err = _gcode((CODE) (((sm & 017) << 12) | (dm & 0xfff)));
	 }
      else
	 err = CERRsmna;
   else
      err = CERRsmna | CERRdmna;
   return(err);
}

/* MOVE uses different size encodings */
static CODE mvsztran[] = { 0x1000, 0x3000, 0x2000 };

/* note that MOVE ea, SR is privileged mode only */
/* and MOVE SR, ea is privileged mode only on the 68010 */
/* also note that MOVEC and MOVE CCR, ea are 68010 ops only */
int genMOVE(sz, sm, sx, svo, dm, dx, dao)
register int sz;
register int sm;
int sx;
long svo;
register int dm;
int dx;
long dao;
{  register int err = 0;
   register int psm = sm & 070;
   register int pdm = dm & 070;

   if (sz < CBYTE || sz > CLONG)
      err = CERRszna;
   else if (E_CTL(sm) || E_CTL(dm))
      err = genMOVEC(sm, dm);
   else if (sm == E_SR) /* do Status Registers */
      err = ((sz > CWORD || pdm == E_An || dm > E_ABSl)
	     ? CERRsmna
	     : (_gcode((CODE) (((sz == CBYTE) ? 041300 : 040300)
				| EA(dm, pdm))),
		extension(sz, dm, dx, dao))); /* watch (super) */
   else if (dm == E_SR)
      err = ((sz > CWORD || psm == E_An || sm > E_IMM)
	     ? CERRdmna
	     : (_gcode((CODE) (((sz == CBYTE) ? 042300 : 043300)
				| EA(sm, psm))),
		extension(sz, sm, sx, svo))); /* watch (super) */
   else if (dm > E_ABSl || (sz == CBYTE && pdm == E_An))
      err = CERRdmna;
   else if (sm > E_IMM || (sz == CBYTE && psm == E_An))
      err = CERRsmna;
   else if (sm == E_IMM && pdm == E_Dn && sz == CLONG && svo < 255)
      err = genMOVEQ(svo, dm); /* optimize */
   else /* general MOVE, or MOVEA */
   {  err = _gcode((CODE) (mvsztran[sz] | EA(sm, psm)
		   | (pdm << 3) | ((dm & 7) << 9)));
      err = extension(sz, sm, sx, svo);
      err = extension(sz, dm, dx, dao);
   }
   return(err);
}

/* if mode is E_Dn or E_An, value/offset is list */
int genMOVEM(sz, sm, sx, svo, dm, dx, dvo)
register int sz, sm;
int sx;
long svo;
register int dm;
int dx;
long dvo;
{  register int err = 0;
   register psm = sm & 070;
   register pdm = dm & 070;

   if (sz < CWORD || sz > CLONG)
      err = CERRszna;
   else if (sm < E_In)
      if (dm < E_In || pdm == E_InINC || dm > E_ABSl)
	 err = CERRdmna;
      else
      {  err = _gcode((CODE) (044200 | ((sz & 2) << 5)
			       | EA(dm, pdm)));
	 err = _gcode((CODE) svo);
	 err = extension(sz, dm, dx, dvo);
      }
   else if (dm < E_In)
      if (psm == E_InDEC || sm > E_pcXi)
	 err = CERRsmna;
      else
      {  err = _gcode((CODE) (046200 | ((sz & 2) << 5)
			       | EA(sm, psm)));
	 err = _gcode((CODE) dvo);
	 err = extension(sz, sm, sx, svo);
      }
   else
      err = CERRsmna | CERRdmna;
   return(err);
}

int genMOVEP(sz, sm, soff, dm, doff) /* move alternate bytes */
register int sz, sm;
long soff;
register int dm;
long doff;
{  register int err = 0;
   register int psm = sm & 070;
   register int pdm = dm & 070;

   if (sz > CLONG || (sz = (sz - 1) << 6) < 0)
      err = CERRszna;
   else if (psm == E_Dn && pdm == E_InOFF)
   {  err = _gcode((CODE) (0610 | (sz & 0100)
			    | ((sm & 7) << 9) | (dm & 7)));
      err = _gcode((CODE) doff);
   }
   else if (pdm == E_Dn && psm == E_InOFF)
   {  err = _gcode((CODE) (0410 | (sz & 0100)
			    | ((dm & 7) << 9) | (sm & 7)));
      err = _gcode((CODE) soff);
   }
   else
      err = CERRsmna | CERRdmna;
   return(err);
}

int genMOVES(sz, sm, sx, soff, dm, dx, doff)
register int sz, sm;
int sx;
long soff;
register int dm;
int dx;
long doff;
{  register CODE cd = 07000 | (sz & 3) << 6;
   register int err = 0;

   if (sz < CBYTE || sz > CLONG)
      err = CERRszna;
   else if (sm < E_In && dm >= E_In && dm < E_pcOFF)
   {  err = _gcode((CODE) (cd | EA(dm, dm & 070)));
      err = _gcode((CODE) ((sm << 12) | 0x800));
      err = extension(sz, dm, dx, doff);
   }
   else if (dm < E_In && sm >= E_In && sm < E_pcOFF)
   {  err = _gcode((CODE) (cd | EA(sm, sm & 070)));
      err = _gcode((CODE) (dm << 12));
      err = extension(sz, sm, sx, soff);
   }
   else
      err = CERRsmna | CERRdmna;
   return(err);
}

int _gMULTI(cd, sz, sm, dm)
register CODE cd;
register int sz;
int sm, dm;
{  register int err = 0;
   register int psm = sm & 070;
   register int pdm = dm & 070;

   if (psm != pdm)
      err = CERRsdi;
   else if ((!(cd & _notBCD) && sz != CBYTE) || sz < CBYTE || sz > CLONG)
      err = CERRszna;
   else if ((cd == _CMP && psm != E_InINC)
	    || (cd != _CMP && psm != E_Dn && psm != E_InDEC))
      err = CERRsmna | CERRdmna;
   else
   {  if (cd & _notBCD)
	 cd |= (sz & 3) << 6;
      if (psm != E_Dn)
	 cd |= 010; /* memory bit */
      err = _gcode((CODE) (cd | 0400 | (sm & 7) | ((dm & 7) << 9)));
   }
   return(err);
}

int _gQUICK(cd, sz, val, dm, dx, dao) /* ADD and SUB only */
register CODE cd;
register int sz;
long val;
register int dm;
int dx;
long dao;
{  register int err = 0;
   register int pdm = dm & 070;

   if (cd == _SUB)
      cd = 050400;
   else /* assume add */
      cd = 050000;
   if (dm >= E_pcOFF || ((pdm == E_An) && sz == CBYTE))
      err = CERRdmna;
   else if (sz < CBYTE || sz > CLONG || (pdm == E_An && sz < CWORD))
      err = CERRszna;
   else /* assume val == 0 => intended val = 8: no size check */
   {  err = _gcode((CODE) (cd | ((val & 7) << 9) | ((sz & 3) << 6)
			    | EA(dm, pdm)));
      err = extension(sz, dm, dx, dao);
   }
   return(err);
}

int _gADDR(cd, sz, sm, sx, svo, reg) /* ADD, CMP, and SUB */
register CODE cd; /* reg is destination (An) */
register int sz;
register int sm;
int sx;
long svo;
int reg;
{  register int err = 0;
   register int psm = sm & 070;

   if (sm > E_IMM)
      err = CERRsmna;
   else if (sz < CWORD || sz > CLONG)
      err = CERRszna;
   else if (cd != _CMP && sm == E_IMM && svo > 0 && svo <= 8)
      err = _gQUICK(cd, sz, svo, reg, 0, 0); /* optimize */
   else
   {  cd |= (~sz & 1) << 8; /* CWORD == 1, CLONG == 2 */
      err = _gcode((CODE) (cd | 0300 | ((reg & 7) << 9) | EA(sm, psm)));
      err = extension(sz, sm, sx, svo);
   }
   return(err);
}

/* translation for immediate: _OR, _SUB, _EOR, _CMP, _AND, _ADD */
static CODE immtran[] = { 0, 02000, 05000, 06000, 01000, 03000 };

int _gIMM(cd, sz, val, dm, dx, dao) /* all binary ops */
register CODE cd;
register int sz;
long val;
register int dm;
int dx;
long dao;
{  register int pdm = dm & 070;
   register int err = 0;

   if (!(cd & _notLOG) && dm == E_SR && sz == CLONG)
	 err = CERRszna | CERRdmna; /* SR is word, CCR is byte */
   else if (dm >= E_pcOFF && !(!(cd & _notLOG) && dm == E_SR))
      err = CERRdmna; /* allow AND, OR, EOR to status reg */
   else if (pdm == E_An)
      if (cd & _notLOG) /* _ADD, _SUB, _CMP */
	 err = _gADDR(cd, sz, E_IMM, 0, val, dm);
      else
	 err = CERRdmna;
   else if ((cd == _ADD || cd == _SUB) && val > 0 && val <= 8)
      err = _gQUICK(cd, sz, val, dm, dx, dao);
   else if (sz < CBYTE || sz > CLONG)
      err = CERRszna;
   else if (cd > _ADD)
      err = CERRopna;
   else /* do it here! */
   {  err = _gcode((CODE) (immtran[(cd >> 12) & 7] | ((sz & 3) << 6)
			    | EA(dm, pdm)));
      err = extension(sz, E_IMM, 0, val); /* immediate operand */
      if (dm != E_SR) /* no ea if dest is status reg */
	 err = extension(sz, dm, dx, dao);
   }
   return(err);
}

int _gBINOP(cd, sz, sm, sx, svo, dm, dx, dao)
register CODE cd;
int sz;
register int sm;
int sx;
long svo;
register int dm;
int dx;
long dao;
{  register int err = 0;
   register int pdm = dm & 070;
   register int psm = sm & 070;

   if (sm == E_IMM) /* vastly different op-code */
      if ((cd == _ADD || cd == _SUB) && svo > 0 && svo <= 8)
	 err = _gQUICK(cd, sz, svo, dm, dx, dao); /* optimize here */
      else
	 err = _gIMM(cd, sz, svo, dm, dx, dao);
   else if (pdm == E_An)
      if (cd & _notLOG)
	 err = _gADDR(cd, sz, sm, sx, svo, dm); /* different op-code */
      else
	 err = CERRdmna;
   else if (dm >= E_pcOFF) /* logic immediate to status already caught */
      err = CERRdmna;
   else if (psm == E_An && (!(cd & _notLOG) || sz == CBYTE))
      err = CERRsmna;
   else if (pdm == E_Dn && cd != _EOR) /* dest ea field can't be Dn */
   {  err = _gcode((CODE) (cd | ((dm & 7) << 9) | (sz & 3) << 6
			    | EA(sm, psm)));
      err = extension(sz, sm, sx, svo);
   }
   else if (psm == E_Dn && cd != _CMP)
   {  if (cd == _EOR) /* CMP and EOR inhabit same code */
	 cd = _CMP;
      err = _gcode((CODE) (cd | 0400 | (sm & 7) << 9 | (sz & 3) << 6
			    | EA(dm, pdm)));
      err = extension(sz, dm, dx, dao);
   }
   else if (psm == pdm && ((psm == E_InDEC && (cd == _ADD || cd == _SUB))
	    || (psm == E_InINC && cd == _CMP)))
      err = _gMULTI(cd, sz, sm, dm); /* anomalous op! */
   else
      err = CERRsdi;
   return(err);
}

int _gSHIFT(op, sz, sm, ct, dm, dx, dao) /* sm is E_IMM or E_Dn|n */
register int op;
int sz;
register int sm;
int ct;
register int dm;
int dx;
long dao;
{  register CODE cd = 0160000 | (op & _sLEFT);
   register int pdm = dm & 070;
   register int err = 0;

   if (pdm == E_Dn)
   {  if ((sm & 070) == E_Dn)
      {  ct = sm; /* put number of register containing count in ct */
	 cd |= 040;
      }
      else if (sm != E_IMM)
	 err = CERRsmna;
      if (!err) /* no range check, assume 0 means 8 if immediate */
	 err = _gcode((CODE) (cd | ((ct & 7) << 9)
			 | ((sz & 3) << 6) | ((op & 3) << 3) | (dm & 7)));
   }
   else if (pdm == E_An || dm > E_ABSl)
      err = CERRdmna;
   else if (sm != E_IMM)
      err = CERRsdi;
   else if (sz != CBYTE)
      err = CERRszna;
   else if (ct != 1) /* this mode shifts one bit at a time */
      err = CERRsdtl;
   else
   {  err = _gcode((CODE) (cd | 0300 | ((op & 3) << 9)
		  | EA(dm, pdm))); /* direction, type, and ea */
      err = extension(sz, dm, dx, dao);
   }
   return(err);
}

int _gBIT(op, sm, bit, dm, dx, dao) /* sm is E_IMM or E_Dn */
register int op, sm;
int bit;
register int dm;
int dx;
long dao;
{  register CODE cd = op & 0300;
   register int pdm = dm & 070;
   register err = 0;

   if (pdm == E_An || (op != _bTST && dm > E_ABSl)
       || (sm == E_IMM && dm == E_IMM) || dm > E_IMM)
      err = CERRdmna;
   else
   {  cd |= EA(dm, pdm);
      if ((sm & 070) == E_Dn)
	 err = _gcode((CODE) (cd | 0400 | ((sm & 7) << 9)));
      else if (sm = E_IMM)
      {  err = _gcode((CODE) (cd | 04000));
	 err = _gcode((CODE) (bit & 0x1f));
      }
      else
	 err = CERRsmna;
      if (!err && pdm != E_Dn)
	 err = extension(CUNSPEC, dm, dx, dao);
   }
   return(err);
}

int _gREGOP(cd, sm, sx, svo, reg) /* MUL, DIV, CHK */
register CODE cd;
register int sm;
int sx;
long svo;
int reg;
{  register int err = 0;
   register int psm = sm & 070;

   if (psm == E_An)
      err = CERRsmna;
   else
   {  err = _gcode((CODE) (cd | ((reg & 7) << 9) | EA(sm, psm)));
      err = extension(CWORD, sm, sx, svo);
   }
   return(err);
}

int _gUNOP(cd, sz, dm, dx, dao) /* CLR, NEG, NEGX, NOT, TST */
register CODE cd;
register int sz, dm;
int dx;
long dao;
{  register int err = 0;
   register int pdm = dm & 070;

   if (pdm == E_An || dm > E_ABSl)
      err = CERRdmna;
   else if (sz < CBYTE || sz > CLONG)
      err = CERRszna;
   else
   {  err = _gcode((CODE) (cd | ((sz & 3) << 6) | EA(dm, pdm)));
      err = extension(sz, dm, dx, dao);
   }
   return(err);
}

int _gEA(cd, dm, dx, dao, reg) /* unary ops with no size, also LEA */
register CODE cd; /* reg should be 0 for JMP, JSR, and PEA */
register int dm;
int dx;
long dao;
int reg;
{  register int err = 0;
   register pdm = dm & 070;

   if ((pdm < E_InOFF && pdm != E_In) || dm >= E_IMM)
      err = CERRdmna;
   else
   {  err = _gcode((CODE) (cd | ((reg & 7) << 9) | EA(dm, pdm)));
      err = extension(CUNSPEC, dm, dx, dao);
   }
   return(err);
}