
/*
   GenPC Elite Macro Assembler, just a TASM killer and the real tool for
   crazy coders. (C)oderight -JEDI- from SECTOR -ONE- 1994/95
   Last revision in date : 12/28/95

   To be compiled with GCC, BORLAND or WATCOM C++

   */

#define REGTO 1
#define VERSION "2.6"
#define MONTH "Feb"
#define YEAR "96"
#define BETA_TEST

#if (REGTO == 1) /* Jedi/Sector One */
#define REGISTERED "enO rotceS/ideJ"
#elif (REGTO == 2) /* Michel Furic */
#define REGISTERED "ciruF lehciM"
#elif (REGTO == 3) /* Quicky */
#define REGISTERED "ykciuQ"
#elif (REGTO == 4) /* Deneb */
#define REGISTERED "beneD"
#elif (REGTO == 5) /* Florent Chichery */
#define REGISTERED "yrehcihC tnerolF"
#elif (REGTO == 6) /* Mon ami bresilien */
#define REGISTERED "neiliserb ima noM"
#elif (REGTO == 7) /* Keops/Equinox */
#define REGISTERED "xoniuqE/spoeK"
#endif

#include <stdlib.h>
#if defined (unix) || defined (__unix__)
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif

#if defined (_POSIX_SOURCE) || defined (__STRICT_ANSI__) && !defined (_BSD_SOURCE) && !defined (__USE_BSD) && !defined (NEED_STRCASE) && !defined (strcasecmp) && !defined (strncasecmp) || !defined (__GNUC__) || !defined (unix) || !defined (__unix__)
#define NEED_STRCASECMP
#define NEED_UNLINK_PROTOTYPE
#endif

#ifdef NEED_UNLINK_PROTOTYPE
#ifndef unlink
int unlink(const char *_path);
#endif
#endif

#ifdef REGISTERED
#define MAX_LABEL 32760
#define IOBUFFER 16380
#define MAX_RELOC 32760
#else
#define MAX_LABEL 16380
#define IOBUFFER 32760
#define MAX_RELOC 16380
#endif

struct lotus {
   char etat;
   long offset;
   char reg1;
   char reg2;
   char factor;
   char r;
} pry1, pry2, pry3;

void eop(void), checkquiet(void);
void soundgarden(void), label(void), bwl(void), fsh(void);
int checkduplicatelabel(void);
char *skipspace(register char *), *nextarg(register char *), *nextcoma(register char *);
void take2(void), put(int), wri(void *, size_t);
void nop(void), end(void), dcb(void), dcw(void), dcl(void), dsb(void), dsw(void), dsl(void);
void trap(void), rts(void), rtsf(void), iret(void), iretd(void), lea(void);
void lock(void), repne(void), repe(void), stop(void), cmc(void), clc(void), stc(void), cld(void), std(void), cli(void), sti(void);
void aaa(void), aad(void), aam(void), aas(void), adc(void), org(void), assume(void), segment(void), even(void), page(void), dpage(void);
void add(void), and(void), arpl(void), bound(void), bsf(void), bsr(void), swap(void);
void bt(void), btc(void), btr(void), bts(void), align(void), alignq(void);
void call(void), callz(void), callf(void), callzf(void), xor(void);
void cbw(void), cwd(void), cdq(void), cwde(void), clts(void), cmp(void), cmps(void), test(void);
void daa(void), das(void), dec(void), div_(void), enter(void), wait_(void), idiv(void);
void imul(void), in(void), inc(void), incbin(void);
void cs(void), ds(void), es(void), fs(void), gs(void), ss(void);
void rept(void), endr(void), set(void), ins(void), into(void), invd(void), wbinvd(void);
void ja(void), jae(void), jb(void), jbe(void), jcxz(void), jecxz(void), je(void);
void jg(void), jge(void), jl(void), jle(void), jno(void), jnp(void), jns(void);
void jne(void), jo(void), jp(void), js(void), jmp(void), jmpf(void), jmpz(void), jmpzf(void);
void seta(void), setae(void), setb(void), setbe(void), sete(void);
void setg(void), setge(void), setl(void), setle(void), setno(void), setnp(void), setns(void);
void setne(void), seto(void), setp(void), sets(void);
void lahf(void), lar(void), lds(void), les(void), lfs(void), lgs(void), lss(void);
void lods(void), leave(void), loop(void), loope(void), loopne(void);
void lgdt(void), lidt(void), lldt(void), lmsw(void), lsl(void), ltr(void), str(void), verr(void);
void sgdt(void), sidt(void), sldt(void), smsw(void), verw(void);
void movs(void), outs(void), mov(void), movsx(void), movzx(void);
void mul(void), neg(void), not(void), or(void), out(void);
void pop(void), popa(void), popf(void), push(void), pusha(void), pushf(void);
void rcl(void), rcr(void), rol(void), ror(void), sahf(void), shl(void), shr(void), sar(void);
void shld(void), shrd(void), xchg(void), xlat(void);
void sub(void), sbb(void), scas(void), stos(void), limite(void), mini(void), overlay(void);
void stack(void), header(void), include(void), macro(void), endm(void), once(void);
void perform(unsigned char, int, char, char, char, unsigned char), limit(void);
void real(void), unreal(void), segsize(void);
void salc(void), icebp(void), umov(void), loadall(void), cmov(void), rdpmc(void), ud(void), ud2(void);
void title(void), bss(void), text(void), use32(void), use16(void), opt(void);
void heading(void), ohnomoreshits(void), int03(void);
long val(char *);
struct lotus getadrs(register char *);
int findreg(char *);
void column(void);

static const struct {const char *nom; void (*col)(void);} neak[] =
{
   {"nop", nop}, {"leave", leave}, {"unlink", leave},
   {"dc.b", dcb}, {"dc.w",dcw}, {"dc.l",dcl}, {"dc", dcw},
   {"ds.b", dsb}, {"ds.w",dsw} ,{"ds.l",dsl},
   {"move", mov}, {"mov", mov}, {"movs", movs}, {"moves", movs},
   {"outs", outs}, {"movsx", movsx}, {"movesx", movsx},
   {"movzx", movzx}, {"movezx", movzx}, {"out", out},
   {"pop", pop}, {"scas", scas}, {"stos", stos},
   {"lgdt", lgdt}, {"lidt", lidt}, {"lldt", lldt}, {"lmsw", lmsw},
   {"trapv", into}, {"into", into}, {"wbinvd", wbinvd}, {"flush", wbinvd}, {"invd", invd},
   {"trap", trap}, {"int", trap}, {"rted", iretd}, {"rtid", iretd}, {"iretd", iretd},
   {"rte", iret}, {"rti", iret}, {"iret", iret}, {"lea", lea},
   {"braf", jmpzf}, {"jmpf", jmpf}, {"bra", jmpz}, {"jmp", jmp},
   {"rtsf", rtsf}, {"retf", rtsf}, {"rts", rts}, {"ret", rts},
   {"lock", lock}, {"rep", repe}, {"repne", repne}, {"repnz", repne},
   {"repeq", repe}, {"repz", repe}, {"repe", repe},
   {"hlt", stop}, {"stop", stop}, {"xor", xor}, {"eor", xor},
   {"cmc", cmc}, {"ngc", cmc}, {"clc", clc}, {"stc", stc},
   {"cld", cld}, {"d+", cld}, {"std", std}, {"d-", std}, {"cli", cli},
   {"intoff", cli}, {"sti", sti}, {"inton", sti},
   {"aaa", aaa}, {"aad", aad}, {"aam", aam}, {"aas", aas},
   {"addx", adc}, {"adc", adc}, {"org", org}, {"assume", assume},
   {"segment", segment}, {"para", segment}, {"page", page}, {"dpage", dpage},
   {"even", even}, {"align.q", alignq}, {"align", align}, {"add", add}, {"and", and}, {"arpl", arpl},
   {"bound", bound}, {"bs+", bsf}, {"bsf", bsf}, {"bs-", bsr}, {"swap", swap}, {"bswap", swap},
   {"btstc", btc}, {"btstn", btc}, {"btc", btc}, {"btstr", btr}, {"btr", btr},
   {"tas", bts}, {"btsts", bts}, {"btst", bt}, {"bts", bts}, {"bt", bt},
   {"jsrf", callzf}, {"callf", callf}, {"jsr", callz}, {"call", call},
   {"bsrf", callzf}, {"bsr", callz}, {"mulu", mul}, {"mul", mul}, {"verr", verr}, {"verw", verw},
   {"exta.q", cdq}, {"ext.q", cdq}, {"cdq", cdq}, {"exta", cbw}, {"ext", cbw},
   {"cbw", cbw}, {"cwde", cwde}, {"cwd", cwd}, {"clts", clts}, {"cmps", cmps}, {"cmp", cmp},
   {"daa", daa}, {"das", das}, {"dec", dec}, {"test", test},
   {"lahf", lahf}, {"lar", lar}, {"lsl", lsl}, {"ltr", ltr}, {"str", str},
   {"lds", lds}, {"les", les}, {"lfs", lfs}, {"lgs", lgs}, {"lss", lss},
   {"divs", idiv}, {"idiv", idiv}, {"divu", div_}, {"div", div_},
   {"link", enter}, {"enter", enter}, {"wait", wait_}, {"fwait", wait_},
   {"muls", imul}, {"imul", imul}, {"incbin", incbin}, {"inc", inc}, {"ins", ins},
   {"cs", cs}, {"ds", ds}, {"es", es}, {"fs", fs}, {"gs", gs}, {"ss", ss},
   {"rept", rept}, {"endr", endr}, {"set", set}, {"in", in},
   {"jnbe", ja}, {"bhi", ja}, {"jae", jae}, {"jnb", jae}, {"bcc", jae},
   {"jnae", jb}, {"bcs", jb}, {"jbe", jbe}, {"jna", jbe}, {"bls", jbe},
   {"jge", jge}, {"jnl", jge}, {"bge", jge}, {"jnc", jae}, {"jno", jno}, {"bvc", jno},
   {"jnge", jl}, {"blt", jl}, {"jle", jle}, {"jng", jle}, {"ble", jle},
   {"jcxz", jcxz}, {"bcxz", jcxz}, {"beq", je}, {"jnle", jg}, {"bgt", jg},
   {"jecxz", jecxz}, {"becxz", jecxz}, {"jcez", jecxz}, {"bcez", jecxz},
   {"jns", jns}, {"bpl", jns}, {"jne", jne}, {"jnz", jne}, {"bne", jne},
   {"jnp", jnp}, {"jpo", jnp}, {"bpo", jnp}, {"bvs", jo},
   {"jpe", jp}, {"bpe", jp}, {"bmi", js},
   {"ja", ja}, {"jb", jb}, {"jc", jb}, {"je", je}, {"jz", je}, {"jg", jg},
   {"jl", jl}, {"jo", jo}, {"jp", jp}, {"js", js},
   {"setbe", seta}, {"shi", seta}, {"setae", setae}, {"setnb", setae}, {"scc", setae},
   {"setae", setb}, {"scs", setb}, {"setbe", setbe}, {"setna", setbe}, {"sls", setbe},
   {"setge", setge}, {"setnl", setge}, {"sge", setge}, {"setnc", setae},
   {"setno", setno}, {"svc", setno},
   {"setnge", setl}, {"slt", setl}, {"setle", setle}, {"setng", setle}, {"sle", setle},
   {"seq", sete}, {"setnle", setg}, {"sgt", setg},
   {"setns", setns}, {"spl", setns}, {"setne", setne}, {"setnz", setne}, {"sne", setne},
   {"setnp", setnp}, {"setpo", setnp}, {"spo", setnp}, {"svs", seto},
   {"setpe", setp}, {"setpe", setp}, {"smi", sets},
   {"seta", seta}, {"setb", setb}, {"setc", setb}, {"sete", sete},
   {"setz", sete}, {"setg", setg},
   {"setl", setl}, {"seto", seto}, {"setp", setp}, {"sets", sets},
   {"loope", loope}, {"loopz", loope}, {"dbeq", loope},
   {"loopne", loopne}, {"loopnz", loopne}, {"dbne", loopne},
   {"lods", lods}, {"loop", loop}, {"dbf", loop}, {"dbra", loop},
   {"neg", neg}, {"not", not}, {"or", or}, {"popa", popa}, {"popf", popf},
   {"push", push}, {"pusha", pusha}, {"pushf", pushf},
   {"roxl", rcl}, {"rcl", rcl}, {"roxr", rcr}, {"rcr", rcr},
   {"rol", rol}, {"ror", ror}, {"sahf", sahf}, {"saf", sahf},
   {"asl", shl}, {"sal", shl}, {"asr", sar}, {"sar", sar}, {"shl", shl}, {"shr", shr},
   {"sub", sub}, {"subx", sbb}, {"sbb", sbb}, {"shld", shld}, {"shrd", shrd},
   {"sgdt", sgdt}, {"sidt", sidt}, {"sldt", sldt}, {"smsw", smsw},
   {"exg", xchg}, {"xchg", xchg}, {"xlat", xlat}, {"xlatb", xlat},
   {"salc", salc}, {"icebp", icebp}, {"int01", icebp}, {"trap01", icebp},
   {"int03", int03}, {"trap03", int03},
   {"umov", umov}, {"umove", umov}, {"loadall", loadall},
   {"cmov", cmov}, {"cmove", cmov}, {"rdpmc", rdpmc}, {"ud", ud}, {"ud2", ud2},
   {"stack", stack}, {"header", heading}, {"exe", heading},
   {"max", limite}, {"limit", limite}, {"min", mini}, {"mini", mini},
   {"overlay", overlay}, {"include", include}, {"macro", macro}, {"once", once},
   {"real", real}, {"realmode", real}, {"flat", unreal}, {"unreal", unreal}, {"unlimit", unreal}, {"segsize", segsize},
   {"endm", endm}, {"bss", bss}, {"section bss", bss}, {"text", text}, {"section text", text}, {"data", text}, {"section data", text},
   {"title", title}, {"use32", use32}, {"use16", use16}, {"opt", opt},
   {NULL, end}
};

static const char *registres[] =
{
   "a", "c", "d", "b",
   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
   "ae", "ce", "de", "be", "spe", "bpe", "sie", "die",
   "es", "cs", "ss", "ds", "fs", "gs",
   "cr0", "cr2", "cr3", "dr0", "dr1", "dr2", "dr3", "dr6", "dr7",
   "tr3", "tr4", "tr5", "tr6", "tr7",
   NULL
};

struct stackent {
   struct stackent *link;
   char *file;
   long pl;
   long pos;
};
struct stackent *upstack = NULL;

#ifdef REGISTERED
struct stackent *uponce = NULL;

struct macroent {
   struct macroent *link;
   char *file;
   char *macro;
   long pl;
   long pos;
};
struct macroent *upmacro = NULL;
#endif

int pass_brief = 2;
int pass_correct = 1;

#define PASS_BRIEF pass_brief
#define PASS_CORRECT pass_correct
#define PASS_LAST 1
#define PASS_FIRST PASS_BRIEF
#define PASS_MAX 3

char *line, *prout, **name, sizer, *pnt, forward = 0;
char *buffer, *bufpnt, *bufend, *accordeon;
FILE *joe, *popol;
int lastlabel = 1, passe, tpasse = 1;
long pl = 0, tpl = 0, rpc = 0, pc = 0, reupeuteumeu = -1, *where, assumer = 0;
long maxsegsize = -1, maxsegcounter = -1;
long orgvalue = 0;
long retimes, repl;
long stk = 0, taille;
long battletech = 0;
long *reloc;
int relocpnt = 0;
char exe = 0, clara = 0;
unsigned short lim = 0xffff, lowlim = 0, ovrlay = 0;
char *sourcefile;
char preprocess = 0, isverbose = 0, isquiet = 0, optimize = 0, nowarning = 0;
char unresolvedlabel = 0, autoalign = 0, isobject = 0, peephole = 0;
long pcwoalign = 0, lastpcwoalign = 0;
int extra_passe = 0, bssflag = 0;
int seg32 = 0;
long polter1, polter2;

enum cputype {
   CALL, C186, C286, C386, C486, C586, C686, CBEST
} cpu = CBEST;

static char *cpunames[] = {
   "8086 or 8088", "80186", "80286", "80386", "80486", "Pentium", "P6", "maximum"
};

#define CPUCHECK(NEEDED) if (cpu < NEEDED) cpusucks(NEEDED)

#ifdef NEED_STRCASECMP
int strcasecmp(const char *s1, const char *s2)
{
   register const unsigned char *p1 = (const unsigned char *) s1;
   register const unsigned char *p2 = (const unsigned char *) s2;
   unsigned char c1, c2;

   if (p1 == p2)
      return 0;
   do {
      c1 = tolower(*p1++);
      c2 = tolower(*p2++);
      if (c1 == '\0')
        break;
   } while (c1 == c2);

   return c1 - c2;
}

int strncasecmp(const char *s1, const char *s2, size_t n)
{
   register const unsigned char *p1 = (const unsigned char *) s1;
   register const unsigned char *p2 = (const unsigned char *) s2;
   unsigned char c1, c2;

   if (p1 == p2 || n == 0)
      return 0;
   do
   {
      c1 = tolower(*p1++);
      c2 = tolower(*p2++);
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
   } while (--n > 0);

   return c1 - c2;
}
#endif

int strtokcasecmp(const char *s, const char *token)
{
   register const unsigned char *p1 = (const unsigned char *) s;
   register const unsigned char *p2 = (const unsigned char *) token;
   unsigned char c1, c2;

   if (p1 == p2)
      return 0;
   for (;;)
   {
      if ((c2 = *p2) == 0)
         return 0;
      p2++;
      if ((c1 = tolower(*p1)) == 0 || c1 != c2)
         return -1;
      p1++;
   }
}

int strfastcasecmp(const char *s1, const char *s2)
{
   register const unsigned char *p1 = (const unsigned char *) s1;
   register const unsigned char *p2 = (const unsigned char *) s2;
   unsigned char c1, c2;

   if (p1 == p2)
      return 0;
   do {
      c1 = tolower(*p1++);
      c2 = *p2++;
      if (c1 == '\0')
        break;
   } while (c1 == c2);

   return c1 - c2;
}

void warning(const char *shakeyourbody)
{
   if (nowarning == 0)
   {
      checkquiet();
      fprintf(stderr, "WARNING : %s at line %ld\n", shakeyourbody, pl);
   }
}

void error(const char *shakeyourbody)
{
   fprintf(stderr, "ERROR : %s at line %ld\n", shakeyourbody, pl);
   exit(EXIT_FAILURE);
}

void checkquiet(void)
{
   static char fanou[13] = "";

   if (strncmp(fanou, sourcefile, 12))
   {
      fprintf(stderr, "\n*** In file [%s] : ***\n", sourcefile);
      strncpy(fanou, sourcefile, 12);
   }
}

void cpusucks(enum cputype required)
{
   fprintf(stderr, "ERROR : You wanted a %s compatibility, but at line %ld, you\n\tused a feature that needs at least a %s processor.\n",
          cpunames[cpu], pl, cpunames[required]);
   exit(EXIT_FAILURE);
}

void optinfo(void)
{
   if (isverbose && tpasse != 2)
   {
      if (lastpcwoalign > pcwoalign)
      {
         printf("%ld bytes saved compared to the previous pass.\n", lastpcwoalign - pcwoalign);
      }
      else if (lastpcwoalign < pcwoalign)
      {
         printf("%ld extra bytes were added to the previous pass due to cross-references.\n", pcwoalign - lastpcwoalign);
      }
   }
}

void eop(void)
{
   if (joe != NULL)
      fclose(joe);
   if (popol != NULL)
   {
      fclose(popol);
   }
   if (sourcefile != NULL)
   {
      fprintf(stderr, "\n( Last processed file was : [%s] )\n", sourcefile);
   }
}

void decrypt(char *encrypted)
{
   char *zarawhite;

   int daphnee = strlen(encrypted);
   zarawhite = encrypted + daphnee;
   do {
      putchar(*--zarawhite);
      daphnee--;
   } while (daphnee != 0);
}

int main(int argc, char **argv)
{
   char *targetname, *popy;

#ifdef REGISTERED
   printf("\n-*-*=)> GenPC v" VERSION "r Elite Assembler by -JEDI- From -SECTOR ONE- " MONTH " " YEAR " <(=*-*-\n\n");
#else
   printf("\n-*-*=)> GenPC v" VERSION " Elite Assembler by -JEDI- From -SECTOR ONE- " MONTH " '" YEAR " <(=*-*-\n\n");
#endif

   passe = PASS_FIRST;

   atexit(eop);

   if (argc < 2)
      goto man;
   do {
      popy = argv[1];
      if (!strcasecmp(popy, "-e") || !strcasecmp(popy, "--preprocess"))
      {
         preprocess = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-nw") || !strcasecmp(popy, "--nowarning"))
      {
         nowarning = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-v") || !strcasecmp(popy, "--verbose"))
      {
         isverbose = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-q") || !strcasecmp(popy, "--quiet"))
      {
         isquiet = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-p") || !strcasecmp(popy, "--peepholes"))
      {
         peephole = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-o") || !strcasecmp(popy, "--optimize"))
      {
         optimize = 1;
         pass_brief = 3;
         pass_correct = 2;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-a") || !strcasecmp(popy, "--autoalign"))
      {
         autoalign = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-c") || !strcasecmp(popy, "--object"))
      {
         isobject = 1;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-86") || !strcasecmp(popy, "-88") ||
               !strcasecmp(popy, "--cpu=88") || !strcasecmp(popy, "--cpu=86"))
      {
         cpu = CALL;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-186") || !strcasecmp(popy, "--cpu=186"))
      {
         cpu = C186;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-286") || !strcasecmp(popy, "--cpu=286"))
      {
         cpu = C286;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-386") || !strcasecmp(popy, "--cpu=386"))
      {
         cpu = C386;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-486") || !strcasecmp(popy, "--cpu=486"))
      {
         cpu = C486;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-586") || !strcasecmp(popy, "--cpu=586") ||
               !strcasecmp(popy, "-pentium") || !strcasecmp(popy, "--cpu=pentium"))
      {
         cpu = C586;
         argv++; argc--;
      }
      else if (!strcasecmp(popy, "-686") || !strcasecmp(popy, "--cpu=686") ||
               !strcasecmp(popy, "-p6") || !strcasecmp(popy, "--cpu=P6"))
      {
         cpu = C686;
         argv++; argc--;
      }
      else
      {
         break;
      }
   } while (argc > 1);

   if (argc == 3)
      targetname = argv[2];
   else if (argc != 2)
   {
   man:
      printf("Usage : GEMA [options] <source.s> [target.obj|target.com|target.exe]\n");

      printf("Options :\n");
      printf("-E, --preprocess : display preprocessed sources\n");
      printf("-v, --verbose    : verbose output\n");
      printf("-q, --quiet      : reduced output\n");
      printf("-o, --optimize   : automatic level 2 optimizations\n");
      printf("-p, --peepholes  : automatic peepholes optimizations\n");
      printf("-nw, --nowarning : disable all warnings\n");
      printf("-a, --autoalign  : enable automatic alignment for each label\n");
      printf("-c, --object     : produce a .OBJ linkable file\n");
      printf("-86, -88, --cpu=86, --cpu=88 : assemble only  8086 opcodes\n");
      printf("-186, --cpu=186              : assemble only 80186 opcodes\n");
      printf("-286, --cpu=286              : assemble only 80286 opcodes\n");
      printf("-386, --cpu=386              : assemble only 80386 opcodes\n");
      printf("-486, --cpu=486              : assemble only 80486 opcodes\n");
      printf("-586, -pentium, --cpu=586, --cpu=pentium  :  80586 opcodes\n");
      printf("-686, -p6, --cpu=686, --cpu=p6            :  80686 opcodes\n");

#ifdef REGISTERED
      printf("\nRegistered to : ");
      decrypt(REGISTERED);
#else
      printf("\nShareware release, please register !");
#endif

#if defined(__DATE__) && defined(__TIME__)
      printf("\nLast revision in date : " __DATE__ ", " __TIME__ "\n");
#endif

      exit(EXIT_SUCCESS);
   }
   else
   {
      if ((targetname = (char *) malloc(strlen(argv[1]) + 5)) == NULL)
      {
         fprintf(stderr, "ERROR : No memory enough for filenames\n");
         exit(EXIT_FAILURE);
      }
      strcpy(targetname, argv[1]);
      if ((popy = strrchr(targetname, '.')) == NULL)
      {
         if (isobject == 0) {
            strcat(targetname, ".exe");
         } else {
            strcpy(targetname, ".obj");
         }
      }
      else
      {
         if (isobject == 0) {
            strcpy(++popy, "exe");
         } else {
            strcpy(++popy, "obj");
         }
      }
   }
   if ((name = (char **) malloc(MAX_LABEL)) == NULL)
   {
      fprintf(stderr, "ERROR : No memory enough for label names\n");
      exit(EXIT_FAILURE);
   }
   if ((where = (long *) malloc(MAX_LABEL * sizeof(long))) == NULL)
   {
      fprintf(stderr, "ERROR : No memory enough for label references\n");
      exit(EXIT_FAILURE);
   }
   if ((reloc = (long *) malloc(MAX_RELOC * sizeof(long))) == NULL)
   {
      fprintf(stderr, "ERROR : No memory enough for relocation table\n");
      exit(EXIT_FAILURE);
   }
   if ((line = (char *) malloc(256)) == NULL)
   {
      fprintf(stderr, "ERROR : No memory enough for inline analyze\n");
      exit(EXIT_FAILURE);
   }
   if ((prout = (char *) malloc(256)) == NULL)
   {
      fprintf(stderr, "ERROR : No memory enough for inline buffering\n");
      exit(EXIT_FAILURE);
   }
   if ((bufpnt = buffer = (char *) malloc(IOBUFFER)) == NULL)
   {
      fprintf(stderr, "ERROR : No memory enough for I/O buffering\n");
      exit(EXIT_FAILURE);
   }
   bufend = buffer + IOBUFFER;
   passe = PASS_FIRST;
 sgeg:
   sourcefile = argv[1];
   if ((joe = fopen(sourcefile, "rt")) == NULL)
   {
      if (*sourcefile == '-') {
         printf("Unrecognized option [%s], assembly aborted.\n", sourcefile);
      } else {
         printf("Sorry, but I can't locate that file\n");
      }
      exit(EXIT_FAILURE);
   }
   if (passe == PASS_LAST)
   {
       if ((popol = fopen(targetname, "wb")) == NULL)
       {
          printf("Sorry, but I can't create the target file\n");
          fclose(joe);
          joe = NULL;
          exit(EXIT_FAILURE);
       }
   }
   *name = "START";
   *where = 0;
   if (passe == PASS_BRIEF)
      printf("-> Assembling : [%s] to [%s]...\n", argv[1], targetname);
 legal:
   while (fgets(line, 255, joe) != NULL)
   {
      pnt = line;
      if (preprocess)
      {
         printf("%s", line);
      }
/*
      else if (isverbose)
      {
         printf("%ld/%ld    \r", tpl, pl);
      }
*/
      pl++;
      tpl++;
      rpc = pc;
      if (*pnt == '\n' || *pnt == '/' || *pnt == '*' || *pnt == '%' || *pnt == ';')
         continue;
      if (*pnt == ' ' || *pnt == '\t')
      {
      enjoy:
         soundgarden();
         continue;
      }
      label();
      goto enjoy;
   }

   if (upstack != NULL)
   {
      struct stackent *savent = upstack;

      fclose(joe);

      if (upstack->link != NULL)
         free(sourcefile);

      sourcefile = upstack->file;
      if ((joe = fopen(sourcefile, "rt")) == NULL)
      {
         fprintf(stderr, "ERROR : Can't reopen [%s] at line %ld\n", sourcefile, pl);
         exit(EXIT_FAILURE);
      }
      fseek(joe, upstack->pos, SEEK_SET);
      pl = upstack->pl;
      upstack = upstack->link;

      free(savent);

/*
      if (!isquiet && isverbose != 0)
      {
         printf("\tBack to file [%s]\n", sourcefile);
      }
*/
      goto legal;
   }
   if (isobject != 0 && exe != 0)
   {
      ohnomoreshits();
   }
   fsh();
   if (popol != NULL)
   {
       fclose(popol);
   }
   if (joe != NULL)
   {
       fclose(joe);
   }
   popol = joe = NULL;
   if (reupeuteumeu >= 0)
   {
      fprintf(stderr, "ERROR : No ENDR follows the last REPT\n");
      exit(EXIT_FAILURE);
   }
   if (--passe)
   {
newturn:
      tpasse++;

      optinfo();
      lastpcwoalign = pcwoalign;
      taille = pc;
      if (passe != PASS_LAST)
      {
         relocpnt = 0;
      }
      rpc = pc = tpl = pl = pcwoalign = 0;
      bssflag = 0;
      assumer = 0;
      seg32 = 0;
      if (!isquiet || isverbose != 0)
      {
         if (forward)
            printf("-> Second pass for forward references...\n");
         else
         {
            if (extra_passe)
            {
               printf("-> Extra pass for crossed peepholes...\n");
               extra_passe++;
            }
            else
            {
               printf("-> New pass for extended warnings and optimizations...\n");
               extra_passe = 1;
            }
         }
      }
      forward = 0;
      goto sgeg;
   }
   else if (lastpcwoalign != pcwoalign)
   {
      if (extra_passe < PASS_MAX) {
         pass_brief = 3;
         pass_correct = 2;
         passe = PASS_LAST;
         goto newturn;
      }
      printf("-> Optimization impossible due to crossed relative lengths - Retrying...\n");
      pass_brief = 3;
      pass_correct = 2;
      passe = PASS_CORRECT;
      optimize = 0;
      goto newturn;
   }
   else if (forward)
   {
      fprintf(stderr, "\nERROR : Crossed references\n");
      exit(EXIT_FAILURE);
   }
   if (!exe && isobject == 0)
   {
      if ((popy = strstr(targetname, ".exe")) != NULL)
      {
         char *ren;

         if ((ren = (char *) malloc(strlen(targetname) + 1)) == NULL)
         {
            fprintf(stderr, "ERROR : No memory enough for renaming [.exe] to [.com]\n");
            exit(EXIT_FAILURE);
         }
         strcpy(ren, targetname);
         strcpy(popy, ".com");
         unlink(targetname);
         if (rename(ren, targetname) != 0)
         {
            fprintf(stderr, "ERROR : Can't rename [%s] to [%s]\n", ren, targetname);
            exit(EXIT_FAILURE);
         }
         printf("Moving [%s] to [%s]...\n", ren, targetname);
      }
   }
   else if (!stk && nowarning == 0)
   {
      fprintf(stderr, "WARNING : No stack\n");
   }
   optinfo();
   if (exe != 0 && relocpnt == 0)
   {
      printf("\n%ld lines assembled in %ld bytes of PC-relative code.\n", tpl, pc);
   }
   else if (exe)
   {
      printf("\n%ld lines assembled in %ld bytes of relocatable code.\n", tpl, pc);
   }
   else
   {
      printf("\n%ld lines assembled in %ld bytes of tiny model code.\n", tpl, ((pc - 0x100) > 0) ? pc - 0x100 : pc);
   }
   if (isverbose)
   {
      printf("The main file [%s] was %ld lines long.\n", sourcefile, pl);
      printf("%d symbols were defined and %ld bytes were used for alignment.\n", lastlabel, pc - pcwoalign);
      printf("There are %d entries in the relocation table.\n", relocpnt);
      printf("%d passes ( %d extra ) were necessary to produce ", tpasse, extra_passe);
      if (optimize)
      {
         printf("automatically optimized");
      }
      else
      {
         printf("raw");
      }
      printf(" code.\n");
   }
   printf("\n-<(* Thank You For Having Done The Right Choice...Keep on Coding or Die ! *)>-\n");

   sourcefile = NULL;
   exit(EXIT_SUCCESS);

   return 0;
}

void ware(void)
{
   if (sizer && passe == PASS_BRIEF)
   {
      warning("Size has no effect");
   }
}

void put(int c)
{
   if (passe == PASS_LAST && !bssflag)
   {
       if (bufpnt == bufend)
       {
          fwrite(buffer, IOBUFFER, 1, popol);
          bufpnt = buffer;
       }
       *bufpnt++ = c;
   }
   pc++;
   pcwoalign++;
   if (maxsegsize < 0) {
      return;
   }
   maxsegcounter--;
   if (maxsegcounter == 0) {
      fprintf(stderr, "ERROR : Too many data in segment (max size was %ld bytes) at line %ld\n", maxsegsize, pl);
      exit(EXIT_FAILURE);
   }
}

void wri(void *c, size_t lune)
{
   if (passe == PASS_LAST && !bssflag)
   {
       if (bufpnt + lune >= bufend)
       {
          fwrite(buffer, bufpnt - buffer, 1, popol);
          bufpnt = buffer;
       }
       memcpy(bufpnt, c, lune);
       bufpnt += lune;
   }
   pc += lune;
   pcwoalign += lune;
   if (maxsegsize < 0) {
      return;
   }
   maxsegcounter -= lune;
   if (maxsegcounter == 0) {
      fprintf(stderr, "ERROR : Too many data in segment (max size was %ld bytes) at line %ld\n", maxsegsize, pl);
      exit(EXIT_FAILURE);
   }
}

void fsh(void)
{
   if (passe == PASS_LAST)
   {
       if (bufpnt != buffer)
       {
          fwrite(buffer, bufpnt - buffer, 1, popol);
          bufpnt = buffer;
       }
   }
}

void hey(struct lotus fleur)
{
   if (seg32 == 0) {
      if (sizer == 'L') {
         put(0x66);
      }
      if ((fleur.reg1 >= 20 && fleur.etat > 8) || fleur.etat == 8) {
         put(0x67);
      }
   } else {
      if (sizer != 'L') {
         put(0x66);
      }
      if (!((fleur.reg1 >= 20 && fleur.etat > 8) || fleur.etat == 8)) {
         put(0x67);
      }
   }
}

#ifdef REGISTERED
int checkmacro(char *zepnt)
{
   register struct macroent *pntmac = upmacro;

   while (pntmac != NULL)
   {
      if (!strtokcasecmp(zepnt, pntmac->macro))
      {

         return 0;
      }
      pntmac = pntmac->link;
   }
   return -1;
}
#endif

void soundgarden(void)
{
   int t = 0;
   char *pnt2;
   const char *tekno;

   pnt = skipspace(pnt);
   if (*pnt == '\n' || *pnt == '\r' || *pnt == 0)
      return;
   for(;;)
   {
      if ((tekno = neak[t].nom) == NULL)
      {
#ifdef REGISTERED
         if (checkmacro(pnt) != 0)
         {
#endif
            fprintf(stderr, "ERROR : Unknown instruction at line %ld :\n\t%s", pl, pnt);
            exit(EXIT_FAILURE);
#ifdef REGISTERED
         }
         break;
#endif
      }
      else if (!strtokcasecmp(pnt, tekno))
      {
         pnt2 = pnt;
         pnt += strlen(tekno);
         if (isalnum(*pnt))
         {
            pnt = pnt2;
            t++;
            continue;
         }
         if (*pnt == '.')
         {
            if ((sizer = toupper(*(++pnt))) == 'L')
            {
               CPUCHECK(C286);
            }
         }
         else
         {
            sizer = 0;
         }
         (*neak[t].col)();
         break;
      }
      t++;
   }
}

void label(void)
{
   char *proutos, zok;
   unsigned int size = 0;
   int thinkabout;
   proutos = prout;
   for (;;)
   {
      zok = *pnt++;
      if (zok == '\n' || zok == ':' || zok == '\t' || zok == ' ')
         break;
      if (isalnum(zok) || zok == '_' || zok == '.' || zok == '!')
      {
         *proutos++ = zok;
         size++;
      }
      else
      {
         error("Invalid label name");
      }
   }
   if (!size)
   {
      error("Label declaration error");
   }
   prout[size] = 0;
   if (autoalign != 0)
   {
      while (pc & 1)
      {
         put(0x90);
         pcwoalign--;
         rpc++;
      }
   }
   if ((thinkabout = checkduplicatelabel()) == -1)
   {
      if ((name[lastlabel] = (char *) malloc(size + 1)) == NULL)
      {
         fprintf(stderr, "ERROR : Oh no ! More memory for labels !\n");
         exit(EXIT_FAILURE);
      }
      where[lastlabel] = rpc;
      strcpy(name[lastlabel++], prout);
      if (lastlabel == MAX_LABEL)
      {
         fprintf(stderr, "ERROR : Too many labels !\n");
         exit(EXIT_FAILURE);
      }
   }
   else if (*prout != '!')
   {
      where[thinkabout] = rpc;
   }
}

int checkduplicatelabel()
{
   int t, u = -1;
   for (t = 0; t < lastlabel; t++)
   {
      if (!strcmp(prout, name[t]))
         break;
   }
   if (t < lastlabel)
   {
      if (passe == PASS_BRIEF && *prout != '.' && *prout != '!')
      {
         fprintf(stderr, "ERROR : Duplicate label/constant variable [%s] at line %ld\n", prout, pl);
         exit(EXIT_FAILURE);
      }
      u = t;
   }
   return u;
}

char *skipspace(register char *remember)
{
   while(*remember == ' ' || *remember == '\t' || *remember == 13)
      remember++;
   return remember;
}

long eval(register char *num)
{
   register char comedie;
   char *sondage, *anum, *onum;
   long total;
   int t, idea = 0;

   anum = num;
 pouf:
   total = 0;
   onum = num;
   comedie = *num++;
   if (comedie == ';')
   {
      error("Expression awaited before the comment");
   }
   else if (isdigit(comedie))
   {
      total = (comedie - '0');
      for(;;)
      {
         comedie = *num++;
         if (isdigit(comedie))
         {
            total *= 10;
            total += (comedie - '0');
         }
         else
            break;
      }
   }
   else if (comedie == '\0' || comedie == 13 || comedie == '\n')
   {
      error("Incomplete subexpression");
   }
   else if (comedie == '$')
   {
      for(;;)
      {
         comedie = *num++;
         if (comedie >= 'A' && comedie <= 'F')
         {
            total <<= 4;
            total |= (comedie - 'A' + 10);
         }
         else if (comedie >= 'a' && comedie <= 'f')
         {
            total <<= 4;
            total |= (comedie - 'a' + 10);
         }
         else if (isdigit(comedie))
         {
            total <<= 4;
            total |= (comedie - '0');
         }
         else
            break;
      }
   }
   else if (comedie == '%')
   {
      for(;;)
      {
         comedie = *num++;
         if (comedie == '0' || comedie == '1')
         {
            total <<= 1;
            total |= (comedie - '0');
         }
         else
            break;
      }
   }
   else if (comedie == '')
   {
      for(;;)
      {
         comedie = *num++;
         if (comedie >= '0' && comedie <='7')
         {
            total <<= 3;
            total |= (comedie - '0');
         }
         else
            break;
      }
   }
   else if (comedie == '*')
   {
      total = rpc;
      num++;
   }
   else if (comedie == '-')
   {
      total = -val(num);
      num = accordeon;
   }
   else if (comedie == ':')
   {
      if (maxsegsize > 0) {
         total = val(num) % maxsegsize;
      } else {
         total = val(num);
      }
      num = accordeon;
   }
   else if (comedie == '@')
   {
      total = val(num);
      if ((total & 15) && passe == PASS_LAST && !idea && nowarning == 0)
      {
         checkquiet();
         fprintf(stderr, "WARNING : @ not applied to a segment address at line %ld\n\t..@%s", pl, num);
      }
      num = accordeon;
      total >>= 4;
   }
   else if (comedie == '\'')
   {
      total = (unsigned char) *num++;
      while (*num != '\'' && *num != '\t' && *num != '\n' && *num != 13)
      {
         total <<= 8;
         total += (unsigned char) *num++;
      }
      if (*num != '\'')
      {
         error("Missing quote");
      }
      num += 2;
   }
   else if (comedie == '~')
   {
      total = ~val(num);
      num = accordeon;
   }
   else if (isalpha(comedie) || comedie == '_' || comedie == '.' || comedie == '!')
   {
      sondage = prout;
      *sondage++ = comedie;
      for(;;)
      {
         comedie = *num++;
         if (!isalnum(comedie) && comedie != '_' && comedie != '.')
            break;
         *sondage++ = comedie;
      }
      *sondage = 0;
      for (t = 0; t < lastlabel; t++)
      {
         if (!strcmp(prout,name[t]))
         {
            total = where[t] - assumer;
            unresolvedlabel = 0;
            break;
         }
      }
      if (t == lastlabel)
      {
         if (passe == PASS_BRIEF)
         {
            forward = 1;
/*          switch (sizer)
            {
               case 'B' :
               case 'S' :
                  total = 0x10;
                  break;
               case 'W' :
                  total = 0x1000;
                  break;
               case 'L' :
               	  total = 0x1000000;
               	  break;
               default : */
                  total = (pc + 0xf) & ~0xf;
/*                do {
                     total++;
                  } while (total & 0xf); */
/*          } */
            unresolvedlabel = 1;
         }
         else
         {
            fprintf(stderr, "ERROR : Undefined label [%s] at line %ld\n", prout, pl);
            exit(EXIT_FAILURE);
         }
      }
   }
   else if (comedie == '[')
   {
      if ((onum = strchr(num, ']')) == NULL)
      {
         error("Final \']\' awaited in expression");
      }
      total = val(num);
      num = skipspace(++onum);
      onum = num;
   }
   else
   {
      error("Undefined expression");
   }
   accordeon = num;
   if (num != onum)
      num--;
   num = skipspace(num);
   comedie = *num;
   if (strchr("=%+-*/|&^<>", comedie) != NULL)
   {
      onum = num;
      *(onum) = '\n';
      num = skipspace(++num);
      switch (idea)
      {
      case 0 :
         if (comedie == '=')
         {
            total = val(anum) == val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 1 :
         if (comedie == '%')
         {
            total = val(anum) % val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 2 :
         if (comedie == '+')
         {
            total = val(anum) + val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 3 :
         if (comedie == '-')
         {
            total = val(anum) - val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 4 :
         if (comedie == '*')
         {
            total = val(anum) * val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 5 :
         if (comedie == '/')
         {
            total = val(anum) / val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 6 :
         if (comedie == '|')
         {
            total = val(anum) | val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 7 :
         if (comedie == '&')
         {
            total = val(anum) & val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 8 :
         if (comedie == '^')
         {
            total = val(anum) ^ val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 9 :
         if (comedie == '<')
         {
            total = val(anum) << val(num);
            *onum = comedie;
            return total;
         }
         break;
      case 10 :
         if (comedie == '>')
         {
            total = val(anum) >> val(num);
            *onum = comedie;
            return total;
         }
      }
      *onum = comedie;
   }
   else
   {
      if (idea != 10)
      {
         idea++;
         num = anum;
      }
      else
         return total;
   }
   goto pouf;
}

long val(char *num)
{
   long fire;
   long oldassumer = assumer;

   if (*num == '\\')
   {
      assumer = 0;
      fire = eval(skipspace(++num));
      fire >>= 4;
      clara = 1;
      assumer = oldassumer;
      return fire;
   }
   clara = 0;

   return eval(num);
}

char *nextarg(register char *doudou)
{
   while (*doudou != ' ' && *doudou != '\t' && *doudou != '\n' && *doudou != 13)
      doudou++;
   if (*doudou == '\n' || *doudou == '\r')
      return NULL;
   while (*doudou == '\t' || *doudou == ' ')
      doudou++;
   if (*doudou == '\n' || *doudou == '\r')
      return NULL;
   if (*doudou == ';') {
      do {
         pnt++;
      } while (*pnt != '\n' && *pnt != '\r' && *pnt != 0);
      return NULL;
   }
   return doudou;
}

char *nextcoma(register char *doudou)
{
   while (*doudou != ',' && *doudou != '\n' && *doudou != 13)
      doudou++;
   if (*doudou == '\n' || *doudou == 13)
      return NULL;
   doudou = skipspace(++doudou);
   if (*doudou == '\n' || *doudou == 13)
      return NULL;
   return doudou;
}

struct lotus getadrs(register char *df)
{
   struct lotus back;
   int t = 0;
   char *df2;

   if (*df == '#')
   {
      df=skipspace(++df);
      back.offset = val(df);
      back.r = clara;
      for(;;)
      {
         if (*df == '\n' || *df == 13 || *df == ',')
            break;
         if (*df++ == '.')
         {
            switch (*df)
            {
            case 'B' :
            case 'b' :
            case 'S' :
            case 's' :
               back.etat = (clara)? 2 : 1;
               return back;
            case 'W' :
            case 'w' :
               back.etat = 2;
               return back;
            case 'L' :
            case 'l' :
               if (clara)
               {
                  error("Can't relocate a long value");
               }
               back.etat = 3;
               return back;
            }
         }
      }
      if (back.offset >= -128 && back.offset <= 255)
         back.etat = (clara)? 2 : 1;
      else if (back.offset >= -32768 && back.offset <= 65535)
         back.etat = 2;
      else
      {
         back.etat = 3;
         if (clara)
         {
            error("Can't relocate a long value");
         }
      }
      return back;
   }
   if ((t = findreg(df)) != -1)
   {
      back.reg1 = t;
      back.etat = 4;
      return back;
   }
   back.etat = 5;
   if (*df == '(')
   {
   dust:
      df2 = df;
      df = skipspace(++df);
      if ((t = findreg(df)) != -1)
      {
         back.reg1 = t;
         back.etat += 4;
         while (*df != ',' && *df != ')' && *df != '\n' && *df != 13) {
            if (!isalnum(*df)) {
               error("Unknown addressing mode");
            }
            df++;
         }
         if (*df == ')')
            return back;
         else if (*df++ != ',')
         {
            error("Missing ')'");
         }
         df = skipspace(df);
         if ((t = findreg(df)) == -1)
         {
            error("Index register missing");
         }
         back.reg2 = t;
         back.etat += 8;
         while (*df != '*' && *df != ')' && *df != '\n' && *df !=13) {
            if (!isalnum(*df)) {
               error("Suspicious garbage with index register");
            }
            df++;
         }
         if (*df == ')')
            return back;
         else if (*df++ != '*')
         {
            error("Missing ')'");
         }
         back.etat += 16;
         switch (val(df = skipspace(df)))
         {
         case 1 :
            back.factor = 0;
            break;
         case 2 :
            back.factor = 1;
            break;
         case 4 :
            back.factor = 2;
            break;
         case 8 :
            back.factor = 3;
            break;
         default :
            error("Suspicious factor");
         }
         return back;
      }
      df = df2;
   }
   back.offset = val(df);
   if (optimize != 0 && back.offset == 0 && unresolvedlabel == 0)
   {
      df = skipspace(++df);
      for (;;)
      {
         if (*df == '\n' || *df == '\r' || *df == 0)
            break;
         if (*df == '(')
         {
           if (isverbose != 0 && passe == PASS_LAST)
           {
              warning("Superflous offset removed");
           }
           back.etat = 5;
           goto dust;
         }
         df++;
      }
   }
   back.r = clara;
   back.etat = 5;
   for(;;)
   {
      if (*df == '\n' || *df == '\r' || *df == '(' || *df == 0)
         break;
      if (*df++ == '.')
      {
         if (*df == 'L' || *df == 'l')
         {
            if (clara)
            {
               error("Can't relocate a long offset");
            }
            back.etat = 8;
            df = skipspace(++df);
            break;
         }
         if (*df == 'W' || *df == 'w')
         {
            back.etat = 7;
            df = skipspace(++df);
            break;
         }
         if (*df == 'B' || *df == 'b' || *df == 'S' || *df =='s')
         {
            back.etat = (clara)? 7 : 6;
            df = skipspace(++df);
            break;
         }
      }
   }
   if (back.etat == 5)
   {
      if (back.offset >= -128 && back.offset <= 127)
         back.etat = 6;
      else if (back.offset >= -32768 && back.offset <= 32767)
         back.etat = 7;
      else
         back.etat = 8;
   }

   if (*df == '(')
      goto dust;
   return back;
}

void nop(void)
{
   ware();
   put(0x90);
}

int findreg(char *tralala)
{
   int t = 0;
   char dynamic;
   char *hoke;
   register const char **regptr = registres;

   hoke = prout;
   for(;;)
   {
      dynamic = *tralala++;
      if (dynamic == '.' || dynamic == '_')
         return -1;
      else if (isalnum(dynamic))
         *hoke++ = dynamic;
      else
         break;
   }
   if (hoke == prout)
      return -1;
   *hoke = 0;
   for (;;)
   {
      if (*regptr == NULL)
      {
         return -1;
      }
      if (!strfastcasecmp(prout, *regptr))
      {
         return t;
      }
      regptr++;
      t++;
   }
}

void take2(void)
{
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("Two arguments are missing");
   }
   pry1 = getadrs(pnt);
   if (!pry1.etat)
   {
      error("Invalid adressing mode");
   }
   while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
      pnt++;
   if (*pnt++ != ',')
   {
      error("Second argument is missing");
   }
   pnt = skipspace(pnt);
   if (pry1.etat >= 13)
   {
      while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
         pnt++;
      if (*pnt++ != ',')
      {
         error("Second argument is missing");
      }
      pnt = skipspace(pnt);
   }
   pry2 = getadrs(pnt);
   if (!pry2.etat)
   {
      error("Invalid adressing mode");
   }
}

void end(void)
{
   printf("GenPC was forced to stop processing\n");
   exit(EXIT_SUCCESS);
}

void dcb(void)
{
   char ginette;

   if ((pnt = nextarg(pnt)) == NULL)
      return;
   do
   {
      if (*pnt == '\"')
      {
         for(;;)
         {
            ginette = *(++pnt);
            if (ginette == '\"' || ginette == 13 || ginette == '\n')
               break;
            put(ginette);
         }
      }
      else
         put((unsigned char) val(pnt));
      if (clara)
      {
         error("Can't relocate a single byte");
      }
   }
   while ((pnt = nextcoma(pnt)) != NULL);
}

void relocate(void)
{
/*
   if (passe != PASS_CORRECT)
   {
      return;
   }
*/
   if (relocpnt == MAX_RELOC)
   {
      fprintf(stderr, "ERROR : Too many entries in relocation table\n");
      exit(EXIT_FAILURE);
   }
   else
   {
      reloc[relocpnt++] = pc;
   }
}

void ccheck(void)
{
   if (clara)
   {
      error("Impossible relocation");
   }
}

void orage(void)
{
   if (clara)
      relocate();
}

void tempete(struct lotus cherie)
{
   if (cherie.r)
      relocate();
}

void dcw(void)
{
   char ginette;
   unsigned int love;

   if ((pnt = nextarg(pnt)) == NULL)
      return;
   do
   {
      if (*pnt == '\"')
      {
         for(;;)
         {
            ginette = *(++pnt);
            if (ginette == '\"' || ginette == 13 || ginette == '\n')
               break;
            put(ginette);
         }
      }
      else
      {
         love = val(pnt);
         orage();
         wri(&love, 2);
      }
   }
   while ((pnt = nextcoma(pnt)) != NULL);
}

void dcl(void)
{
   char ginette;
   unsigned long love;

   if ((pnt = nextarg(pnt)) == NULL)
      return;
   do
   {
      if (*pnt == '\"')
      {
         for(;;)
         {
            ginette = *(++pnt);
            if (ginette == '\"' || ginette == 13 || ginette == '\n')
               break;
            put(ginette);

         }
      }
      else
      {
         love = val(pnt);
         wri(&love, 4);
      }
      if (clara)
      {
         error("Can't relocate a long constant");
      }
   }
   while ((pnt = nextcoma(pnt)) != NULL);
}

void dsb(void)
{
   char ginette;
   long t, tm;

   if ((pnt = nextarg(pnt)) == NULL)
      return;
   do
   {
      if (*pnt == '\"')
      {
         for(;;)
         {
            ginette = *(++pnt);
            if (ginette == '\"' || ginette == 13 || ginette == '\n')
               break;
            put(0);
         }
      }
      else
      {
         tm = val(pnt);
         for (t = 0; t < tm; t++)
            put(0);
      }
   }
   while ((pnt = nextcoma(pnt)) != NULL);
}

void dsw(void)
{
   char ginette;
   long t, tm;
   static char tmp[] = { 0, 0 };

   if ((pnt = nextarg(pnt)) == NULL)
      return;
   do
   {
      if (*pnt == '\"')
      {
         for(;;)
         {
            ginette = *(++pnt);
            if (ginette == '\"' || ginette == 13 || ginette == '\n')
               break;
            put(0);
         }
      }
      else
      {
         tm = val(pnt);
         for (t = 0; t < tm; t++)
            wri(tmp, 2);
      }
   }
   while ((pnt = nextcoma(pnt)) != NULL);
}


void dsl(void)
{
   char ginette;
   long t, tm;
   static char tmp[] = { 0, 0, 0, 0 };

   if ((pnt = nextarg(pnt)) == NULL)
      return;
   do
   {
      if (*pnt == '\"')
      {
         for(;;)
         {
            ginette = *(++pnt);
            if (ginette == '\"' || ginette == 13 || ginette == '\n')
               break;
            put(0);
         }
      }
      else
      {
         tm = val(pnt);
         for (t = 0; t < tm; t++)
            wri(tmp, 4);
      }
   }
   while ((pnt = nextcoma(pnt)) != NULL);
}

void trap(void)
{
   ware();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("incomplete TRAP #");
   }
   if (*pnt == '#')
   {
      pnt++;
      pnt = skipspace(pnt);
   }
   put(0xcd);
   put(val(pnt));
   ccheck();
}

void rts(void)
{
   unsigned int oupla;

   if (sizer == 'L' && seg32 == 0) {
      put(0x66);
   }
   if ((pnt = nextarg(pnt)) == NULL)
   {
      put(0xc3);
      return;
   }
   if ((oupla = val(pnt)) != 0)
   {
      put(0xc2);
      orage();
      wri(&oupla, 2);
   }
}

void rtsf(void)
{
   unsigned int oupla;

   ware();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      put(0xcb);
      return;
   }
   if ((oupla = val(pnt)) != 0)
   {
      put(0xca);
      orage();
      wri(&oupla, 2);
   }
}

void stop(void)
{
   ware();
   put(0xf4);
}

void cmc(void)
{
   ware();
   put(0xf5);
}

void clc(void)
{
   ware();
   put(0xf8);
}

void stc(void)
{
   ware();
   put(0xf9);
}

void cld(void)
{
   ware();
   put(0xfc);
}

void std(void)
{
   ware();
   put(0xfd);
}

void cli(void)
{
   ware();
   put(0xfa);
}

void sti(void)
{
   ware();
   put(0xfb);
}

void aaa(void)
{
   ware();
   put(0x37);
}

void undoc(void)
{
   if (isverbose != 0 && passe == PASS_BRIEF)
   {
      warning("Undocumented opcode");
   }
}

void aaundoc(char op)
{
   long im;

   ware();
   put(op);
   if ((pnt = nextarg(pnt)) == NULL)
   {
      im = 0x0a;
   }
   else
   {
      if (*pnt == ';')
      {
         im = 0x0a;
         goto talali;
      }
      else if (*pnt == '#')
      {
         pnt = skipspace(++pnt);
         if (*pnt == '\n' || *pnt == '\r' || *pnt == 0 || *pnt == ';')
         {
            error("Some undocumented thing is missing after the # symbol");
         }
      }
      im = val(pnt);
      if (im < 0 || im > 255)
      {
         undoc();
         if (passe == PASS_LAST) {
            warning("ASCII base operand reduced to a byte");
         }
         im &= 0xff;
      }
   }
 talali:
   put(im);
}

void aad(void)
{
   aaundoc(0xd5);
}

void aam(void)
{
   aaundoc(0xd4);
}

void aas(void)
{
   ware();
   undoc();
   put(0x3f);
}

void salc(void)
{
   ware();
   undoc();
   put(0xd6);
}

void icebp(void)
{
   CPUCHECK(C386);
   ware();
   undoc();
   put(0xf1);
}

void int03(void)
{
   CPUCHECK(C386);
   ware();
   undoc();
   put(0xf3);
}

void umov(void)
{
   CPUCHECK(C386);
   undoc();
   put(0x0f);
   perform(0x10, 0x10, 0, 0, 0x80, 0);
}

void loadall(void)
{
   CPUCHECK(C386);
   ware();
   undoc();
   put(0x0f);
   put(0x07);
}

void cmov(void)
{
   CPUCHECK(C686);
   undoc();
   put(0x0f);
   perform(0x40, 0x40, 0, 0, 0x80, 0);
}

void rdpmc(void)
{
   CPUCHECK(C686);
   ware();
   undoc();
   put(0x0f);
   put(0x33);
}

void ud(void)
{
   ware();
   undoc();
   put(0x0f);
   put(0x0b);
}

void ud2(void)
{
   ware();
   undoc();
   put(0x0f);
   put(0xb9);
}

void bwl(void)
{
   if (!sizer)
      sizer = 'W';
   else if (sizer == 'S')
      sizer = 'B';
   else if (sizer != 'B' && sizer != 'W' && sizer != 'L')
   {
      error("Invalid size");
   }
}

void lea(void)
{
   take2();
   if (sizer == 'B' || sizer == 'S' || pry2.etat != 4)
   {
      error("LEA deals only with word and long registers");
   }
   if (pry1.etat < 4)
   {
      error("Can't load effective address of an immediate value");
   }
   else if (pry1.etat == 4)
   {
      error("Use MOVE");
   }
   perform(0x8a, 0x8a, 0, 1, 0x80, 0);
}

void adc(void)
{
   perform(0x10, 0x10, 0, 0, 0x80, 0);
}

void add(void)
{
   perform(0x00, 0x00, 0, 0, 0x80, 0);
}

void sub(void)
{
   perform(0x28, 0x28, 0, 0, 0x80, 0);
}

void sbb(void)
{
   perform(0x18, 0x18, 0, 0, 0x80, 0);
}

void perform(unsigned char fuckepita, int trynow, char runaway, char away2,
             char horizon, unsigned char tryit)
{
   unsigned char head, head2 = 0, moving = 0, onup = 0;
   int hole, away = 0;

   if (!away2)
      take2();
   bwl();
   if (pry1.etat == 4)          /* Op1 = Registre */
   {
      if (pry2.etat == 4)       /* Op2 = Registre */
      {
         switch (sizer)
         {
         case 'B' :
            if (seg32 != 0 && !runaway) {
               put(0x66);
            }
            put(fuckepita + 2);
            if (pry1.reg1 >= 12 || pry2.reg1 >= 12)
            {
            fanfare:
               error("Instruction and operands sizes don't fit");
            }
            if (pry1.reg1 >= 4)
               pry1.reg1 -= 4;
            if (pry2.reg1 >= 4)
               pry2.reg1 -= 4;
            head = 0xc0 + (pry2.reg1 << 3) + pry1.reg1 + tryit;
            put(head);

            break;
         case 'W' :
            if (seg32 != 0 && !runaway) {
               put(0x66);
            }
            put(fuckepita + 3);
            if ((pry1.reg1 >= 4 && pry1.reg1 <12) || pry1.reg1 >= 20)
               goto fanfare;
            if ((pry2.reg1 >= 4 && pry2.reg1 <12) || pry2.reg1 >= 20)
               goto fanfare;
            if (pry1.reg1 >= 12)
               pry1.reg1 -= 12;
            if (pry2.reg1 >= 12)
               pry2.reg1 -= 12;
            head = 0xc0 + (pry2.reg1 << 3) + pry1.reg1 + tryit;
            put(head);

            break;
         default :
            if (seg32 == 0 && !runaway) {
               put(0x66);
            }
            put(fuckepita + 3);
            if ((pry1.reg1 >= 4 && pry1.reg1 <16) || pry1.reg1 >= 28)
               goto fanfare;
            if ((pry2.reg1 >= 4 && pry2.reg1 <16) || pry2.reg1 >= 28)
               goto fanfare;
            if (pry1.reg1 >= 20)
               pry1.reg1 -= 20;
            else if (pry1.reg1 >= 16)
               pry1.reg1 -= 12;
            if (pry2.reg1 >= 20)
               pry2.reg1 -= 20;
            else if (pry2.reg1 >= 16)
               pry2.reg1 -= 12;
            head = 0xc0 + (pry2.reg1 << 3) + pry1.reg1 + tryit;
            put(head);
         }
         return;
      }
      else if (pry2.etat > 5)   /* Op1 = Registre, Op2 = Mem */
      {
      degoute:
         switch (sizer)
         {
         case 'L' :
            if ((pry1.reg1 >= 4 && pry1.reg1 < 20) || pry1.reg1 >=28)
               goto fanfare;
            if (pry1.reg1 >= 20)
               pry1.reg1 -= 20;
            away = 1;
            if (seg32 == 0 && !onup && !runaway) {
               put(0x66);
            }
            goto tocard;
         case 'W' :
            if ((pry1.reg1 >= 4 && pry1.reg1 < 12) || pry1.reg1 >=20)
               goto fanfare;
            if (pry1.reg1 >= 12)
               pry1.reg1 -= 12;
            away = 1;
            if (seg32 != 0 && !onup && !runaway) {
               put(0x66);
            }
            goto tocard;
         case 'B' :
            away = 0;
            if (seg32 != 0 && !onup && !runaway) {
               put(0x66);
            }
            if (pry1.reg1 >= 12)
               goto fanfare;
            if (pry1.reg1 >= 4)
               pry1.reg1 -= 4;
         tocard:
            head = (pry1.reg1 << 3) + tryit;
            if (pry2.etat < 8)  /* Op2 = Absolu.w */
            {
               if (!onup) {
                  if (seg32 != 0 && !runaway) {
                     put(0x67);
                  }
                  put(fuckepita + away);
               }
               put(head + 6);
               hole = pry2.offset;
               tempete(pry2);
               wri(&hole, 2);
               break;
            }
            if (pry2.etat == 8) /* Op2 = Absolu.l */
            {
               CPUCHECK(C286);
               if (!onup)
               {
                  if (seg32 == 0 && !runaway) {
                     put(0x67);
                  }
                  put(fuckepita + away);
               }
               put(head + 5);
               wri(&pry2.offset, 4);

               break;
            }
         lackers:
            if (pry2.etat == 9) /* (Reg) */
            {
               if (pry2.reg1 < 4)
                  pry2.reg1 += 12;
               if (pry2.reg1 == 18 || pry2.reg1 == 19 || pry2.reg1 == 15)
               {
                  if (!onup)
                  {
                     if (seg32 != 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  switch (pry2.reg1)
                  {
                  case 18 :
                     head += 4;
                     break;
                  case 19 :
                     head += 5;
                     break;
                  case 15 :
                     head += 7;
                     break;
                  }
                  put(head);
                  break;
               }
               if (pry2.reg1 == 17)
               {
                  if (!onup)
                  {
                     if (seg32 != 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  if (head < 0x40)
                  {
                     put(0x40 + head + 6);
                     put(0x00);

                  }
                  else
                  {
                     head += 6;
                     put(head);
                  }
                  break;
               }
               if (pry2.reg1 >= 20 && pry2.reg1 <= 27)
               {
                  if (!onup)
                  {
                     if (seg32 == 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);

                  }
                  if (pry2.reg1 == 24)
                  {
/*
                     if (head < 0x40)
                     {
*/
                        put(head + 4);
                        put(0x24);
/*
                     }
                     else
                     {
                        head += 4;
                        put(head);
                     }
*/
                     break;
                  }
                  else if (pry2.reg1 == 25)
                  {
                     if (head < 0x40)
                     {
                        put(0x40 + head + 5);
                        put(0x00);

                     }
                     else
                     {
                        head += 5;
                        put(head);

                     }
                     break;
                  }
                  head += (pry2.reg1 - 20);
                  put(head);

                  break;
               }
               else
               culture:
               error("Unknown adressing mode");
            }
            else if (pry2.etat == 17) /* (Reg,Reg) */
            {
            bouillon:
/*
               if (pry2.reg1 == 16 || pry2.reg1 == 17
                   || pry2.reg1 == 24 || pry2.reg1 == 25)
               {
		  char saveit = pry2.reg1;

                  pry2.reg1 = pry2.reg2;
                  pry2.reg2 = saveit;
               }
*/
               if (pry2.reg1 == 17 || pry2.reg1 == 25)
	       {
                  if (moving == 0)
                  {
		     moving = 1;
	             pry2.offset = 0;
                     if (hole == 1)
                        head += 0x40;
                     else
                        head += 0x80;
	          }
	       }
               if (pry2.reg1 < 4)
                  pry2.reg1 += 12;
               if (pry2.reg2 < 4)
                  pry2.reg2 += 12;
               if ((pry2.reg1 == 15 && pry2.reg2 == 18) || (pry2.reg1 == 18 && pry2.reg2 == 15))
               {
                  if (!onup) {
                     if (seg32 != 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  put(head);

                  break;
               }
               else if ((pry2.reg1 == 15 && pry2.reg2 == 19) || (pry2.reg1 == 19 && pry2.reg2 == 15))
               {
                  if (!onup) {
                     if (seg32 != 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  head++;
                  put(head);

                  break;
               }
               else if ((pry2.reg1 == 17 && pry2.reg2 == 18) || (pry2.reg1 == 18 || pry2.reg2 == 17))
               {
                  if (!onup) {
                     if (seg32 != 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  head += 2;
                  put(head);

                  break;
               }
               else if ((pry2.reg1 == 17 && pry2.reg2 == 19) || (pry2.reg1 == 19 || pry2.reg2 == 17))
               {
                  if (!onup) {
                     if (seg32 != 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  head += 3;
                  put(head);

                  break;
               }
               else if (pry2.reg1 >= 20 && pry2.reg1 < 28 && pry2.reg2 >= 20 && pry2.reg2 < 28)
               {
                  if (!onup)
                  {
                     if (seg32 == 0 && !runaway) {
                        put(0x67);
                     }
                     put(fuckepita + away);
                  }
                  head += 4;
                  put(head);
                  head2 += ((pry2.reg2 - 20) << 3) + pry2.reg1 - 20;
                  put(head2);

                  break;
               }
               else
                  goto culture;
            }
            else if (pry2.etat == 33) /* (Reg,Reg*Coef) */
            {
               head2 = pry2.factor << 6;
               goto bouillon;
            }
            else if ((hole = ((pry2.etat - 5) & 3)) != 0) /* Offset */
            {
               if (hole == 2)
                  hole++;
               else if (passe == PASS_LAST && pry2.reg1 < 20 && hole == 3)
               {
                  error("Offset out of range");
               }
               if (hole == 1)
                  head += 0x40;
               else
                  head += 0x80;
               moving = 1;
               pry2.etat = ((pry2.etat - 5) & ~3) + 5;

               goto lackers;
            } else {
               goto culture;
            }
         }
         if (moving)
         {
            if (hole == 1)
            {
               put(pry2.offset);
            }
            else if (pry2.reg1 >=20 && pry2.reg1 < 28)
            {
               wri(&pry2.offset, 4);
            }
            else
            {
               wri(&pry2.offset, 2);
            }
         }
         if (onup)
         {
            if (onup == 1)
               put(pry1.offset);
            else if (onup == 2)
            {
               hole = pry1.offset;
               tempete(pry1);
               wri(&hole, 2);
            }
            else
            {
               wri(&pry1.offset, 4);

            }
         }
         return;
      }
      else
      {
         error("Can't assign immediate values");
      }
   }
   else if (pry1.etat < 4 && pry2.etat == 4) /* #,Reg */
   {
      switch (sizer)
      {
      case 'L' :
         if ((pry2.reg1 >= 4 && pry2.reg1 < 20) || pry2.reg1 >=28)
            goto fanfare;
         if (pry2.reg1 >= 20)
            pry2.reg1 -= 20;
         away = 3;
         if (seg32 == 0 && !runaway) {
            put(0x66);
         }
         goto petard;
      case 'W' :
         if ((pry2.reg1 >= 4 && pry2.reg1 < 12) || pry2.reg1 >=20 || pry1.etat == 3)
            goto fanfare;
         if (pry2.reg1 >= 12)
            pry2.reg1 -= 12;
         away = 3;
         if (seg32 != 0 && !runaway) {
            put(0x66);
         }
         goto petard;
      case 'B' :
         away = 0;
         if (seg32 != 0 && !runaway) {
            put(0x66);
         }
         if (pry2.reg1 >= 12 || pry1.etat != 1)
            goto fanfare;
         if (pry2.reg1 >= 4)
            pry2.reg1 -= 4;
      }
   petard:
      head = pry2.reg1;
      if (pry1.etat == 1 && pry1.offset >= -128 && pry1.offset <= 127)
      {
         if (pry2.reg1 || sizer == 'L')
         {
            put(horizon + away);
            head += 0xc0 + fuckepita;
            put(head);
         }
         else
            goto unreality;
         put(pry1.offset);
      }
      else
      {
         if (pry2.reg1)
         {
            put(horizon + away - 2);
            head += 0xc0 + fuckepita;
            put(head);
         }
         else
         {
         unreality:
            if (away == 3)
               away =1;
            put(fuckepita + 4 + away);
         }
         if (pry1.etat == 3 || sizer == 'L')
            wri(&pry1.offset, 4);
         else if (pry1.etat == 2 || sizer == 'W')
         {
            hole = pry1.offset;
            tempete(pry1);
            wri(&hole, 2);
         }
         else
            put(pry1.offset);
      }
   }
   else if (pry1.etat > 5 && pry2.etat == 4) /* Mem,Reg */
   {
      struct lotus donald;

      donald = pry1;
      pry1 = pry2;
      pry2 = donald;
      fuckepita += 2;
      goto degoute;
   }
   else if (pry1.etat < 4 && pry2.etat > 5) /* #,Mem */
   {
      tryit = trynow;
      if (pry2.etat < 8)
         pry2.reg1 = 0;
      else if (pry2.etat == 8)
         pry2.reg1 = 21;
      if (sizer == 'B' && pry1.etat == 1)
      {
         if (seg32 != 0 && !runaway) {
            put(0x66);
         }
         if (seg32 == 0 && pry2.reg1 > 20 && !runaway) {
            put(0x67);
         } else if (seg32 != 0 && pry2.reg1 <= 20 && !runaway) {
            put(0x67);
         }
         pry1.etat = 4;
         pry1.reg1 = 0;
         onup = 1;
         put(horizon);

         goto degoute;
      }
      else if (sizer == 'W' && pry1.etat == 2)
      {
         if (seg32 != 0 && !runaway) {
            put(0x66);
         }
         if (seg32 == 0 && pry2.reg1 > 20 && !runaway) {
            put(0x67);
         } else if (seg32 != 0 && pry2.reg1 <=20 && !runaway) {
            put(0x67);
         }
         pry1.etat = 4;
         pry1.reg1 = 0;
         onup = 2;
         put(horizon + 1);

         goto degoute;
      }
      else if (sizer == 'W' && pry1.etat == 1)
      {
         if (seg32 != 0 && !runaway) {
            put(0x66);
         }
         if (seg32 == 0 && pry2.reg1 > 20 && !runaway) {
            put(0x67);
         } else if (seg32 != 0 && pry2.reg1 <= 20 && !runaway) {
            put(0x67);
         }
         pry1.etat = 4;
         pry1.reg1 = 0;
         onup = 1;
         put(horizon + 3);

         goto degoute;
      }
      else if (sizer == 'L' && pry1.etat == 1)
      {
         if (seg32 == 0 && !runaway) {
            put(0x66);
         }
         if (seg32 == 0 && pry2.reg1 > 20 && !runaway) {
            put(0x67);
         } else if (seg32 != 0 && pry2.reg1 <=20 && !runaway) {
            put(0x67);
         }
         pry1.etat = 4;
         pry1.reg1 = 0;
         onup = 1;
         put(horizon + 3);

         goto degoute;
      }
      else if (sizer == 'L')
      {
         if (seg32 == 0 && !runaway) {
            put(0x66);
         }
         if (seg32 == 0 && pry2.reg1 > 20 && !runaway) {
            put(0x67);
         } else if (seg32 != 0 && pry2.reg1 <= 20 && !runaway) {
            put(0x67);
         }
         pry1.etat = 4;
         pry1.reg1 = 0;
         onup = 4;
         put(horizon + 1);

         goto degoute;
      }
      else
      {
         error("Size mismatch with constant");
      }
   }
   else
   {
      error("Unknown assignement");
   }
}

void org(void)
{
   ware();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("ORG needs one argument");
   }
   orgvalue = pcwoalign = pc = val(pnt);
   ccheck();
}

void opt(void)
{
   char zekar, newcar;

   ware();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("OPT needs one argument");
   }
   zekar = tolower(*pnt++);
   newcar = *pnt;
   if (newcar != '+' && newcar != '-') {
      error("'+' or '-' awaited to enable/disable an option");
   }
   switch(zekar) {
      case 'v' :
         isverbose = (newcar == '+') ? 1 : 0;
         break;
      case 'o' :
         optimize = (newcar == '+') ? 1 : 0;
         break;
      case 'q' :
         isquiet = (newcar == '+') ? 1 : 0;
         break;
      case 'w' :
         nowarning = (newcar == '-') ? 1 : 0;
         break;
      case 'a' :
         autoalign = (newcar == '+') ? 1 : 0;
         break;
      default :
         warning("Unrecognized option");
   }
}

void title(void)
{

}

void assume(void)
{
   ware();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("ASSUME needs one argument");
   }
   assumer = 0;
   assumer = val(pnt);
   ccheck();
   if ((assumer & 15) != 0 && passe == PASS_LAST)
   {
      warning("Assuming a non segment-aligned value");
   }
}

void segment(void)
{
   ware();
   maxsegcounter = maxsegsize;
   while (pc & 15)
   {
      put(0x90);
      pcwoalign--;
   }
   column();
}

void page(void)
{
   ware();
   maxsegcounter = maxsegsize;
   while(pc & 0xff)
   {
      put(0x90);
      pcwoalign--;
   }
   column();
}

void dpage(void)
{
   ware();
   maxsegcounter = maxsegsize;
   while(pc & 0x1ff)
   {
      put(0x90);
      pcwoalign--;
   }
   column();
}

void even(void)
{
   ware();
   if (pc & 1)
   {
      put(0x90);
      pcwoalign--;
   }
}

void align(void)
{
   if (sizer == 'B' || sizer == 'S')
   {
      warning("Directive has no effect");
   }
   else
   {
      bwl();
      if (sizer == 'W')
      {
         if (pc & 1)
         {
            put(0x90);
            pcwoalign--;
         }
      }
      else
      {
         while(pc & 3)
         {
            put(0x90);
            pcwoalign--;
         }
      }
   }
}

void alignq(void)
{
   if (sizer)
   {
      error("Ambigous directive");
   }
   while(pc & 7)
   {
      put(0x90);
      pcwoalign--;
   }
}

void and(void)
{
   perform(0x20, 0x20, 0, 0, 0x80, 0);
}

void xor(void)
{
   perform(0x30, 0x30, 0, 0, 0x80, 0);
}

void arpl(void)
{
   CPUCHECK(C286);
   limit();
   perform(0x60, 0x60, 0, 0, 0x80, 0);
}

void limit(void)
{
   char *toc;

   toc = pnt;
   take2();
   bwl();
   pnt = toc;
   if (pry2.etat != 4 || pry1.etat < 4 || sizer == 'B')
   {
      error("Impossible adressing mode");
   }
}

void limit2(void)
{
   char *toc;

   toc = pnt;
   take2();
   bwl();
   pnt = toc;
   if (pry2.etat != 4 || pry1.etat <= 4 || sizer == 'B')
   {
      error("Impossible adressing mode");
   }
}

void bound(void)
{
   CPUCHECK(C186);
   limit2();
   perform(0x5F, 0x5F, 0, 0, 0x80, 0);
}

void bsf(void)
{
   CPUCHECK(C386);
   limit();
   if ((pry1.etat > 5 && (pry1.reg1 >= 4 && pry1.reg1 < 12)) || pry1.etat == 1)
   {
   snake:
      error("Incoherent sizes");
   }
   if (sizer == 'W')
   {
      if (pry1.etat == 3 || (pry1.etat > 5 && pry1.reg1 >= 20))
         goto snake;
      if (seg32 != 0) {
         put(0x66);
         put(0x67);
      }
      put(0x0f);
      perform(0xb9, 0xb9, 0, 0, 0x80, 0);
   }
   else
   {
      if (pry1.etat == 2 || (pry1.etat > 5 && pry1.reg1 < 20 && pry1.reg1 >= 4))
         goto snake;
      if (seg32 == 0) {
         put(0x66);
         put(0x67);
      }
      put(0x0f);
      perform(0xb9, 0xb9, 1, 0, 0x80, 0);
   }
}

void bsr(void)
{
   CPUCHECK(C386);
   limit();
   if ((pry1.etat > 5 && (pry1.reg1 >= 4 && pry1.reg1 < 12)) || pry1.etat == 1)
   {
   snake:
      error("Incoherent sizes");
   }
   if (sizer == 'W')
   {
      if (pry1.etat == 3 || (pry1.etat > 5 && pry1.reg1 >= 20))
         goto snake;
      if (seg32 != 0) {
         put(0x66);
         put(0x67);
      }
      put(0x0f);
      perform(0xBA, 0xBA, 0, 0, 0x80, 0);
   }
   else
   {
      if (pry1.etat == 2 || (pry1.etat > 5 && pry1.reg1 < 20 && pry1.reg1 >= 4))
         goto snake;
      if (seg32 == 0) {
         put(0x66);
         put(0x67);
      }
      put(0x0f);
      perform(0xBA, 0xBA, 1, 0, 0x80, 0);
   }
}

void take1(void)
{
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("One argument is missing");
   }
   pry1 = getadrs(pnt);
}

void swap(void)
{
   CPUCHECK(C486);
   take1();
   ware();
   if (pry1.etat != 4)
   {
      error("Invalid adressing mode");
   }
   if ((pry1.reg1 >= 4 && pry1.reg1 < 20) || (pry1.reg1 >= 28))
   {
      error("SWAP can only work on 32 bits registers");
   }
   if (pry1.reg1 >= 20)
      pry1.reg1 -= 20;
   if (seg32 == 0) {
      put(0x66);
   }
   put(0x0f);
   put(0xc8 + pry1.reg1);
}

void bits(unsigned char mediatic)
{
   char *toc;

   CPUCHECK(C386);
   toc = pnt;
   take2();
   pnt = toc;
   bwl();
   if (pry1.etat == 1)
   {
      if (pry2.etat == 4)       /* #b,reg.w */
      {
         if (pry2.reg1 >= 12 && pry2.reg1 < 20)
            pry2.reg1 -= 12;
         else if (pry2.reg1 > 4)
         {
            error("Only a word register can be used");
         }
         put(0x0f);
         put(0xba);
         put(0xe0 + pry2.reg1);
         put(pry1.offset);
      }
      else if (pry2.etat < 5)
         goto bang;
      else                      /* #b,mem */
      {
         if (sizer == 'B')
         {
            error("Only .W and .L fit to <B..> <#b>,<mem>");
         }
         hey(pry2);
         put(0x0f);
         perform(0x20 + mediatic, 0x20 + mediatic, 1, 1, 0xb7, 0);
      }
   }
   else if (pry1.etat == 4)
   {
      if (pry2.etat == 4)       /* reg,reg */
      {
         if (pry1.reg1 >= 12 && pry1.reg1 < 20)
            pry1.reg1 -= 12;
         else if (pry1.reg1 > 4)
         {
         thisismydream:
            error("Only a word register can be used");
         }
         if (pry2.reg1 >= 12 && pry2.reg1 < 20)
            pry2.reg1 -= 12;
         else if (pry2.reg1 > 4)
            goto thisismydream;
         put(0x0f);
         put(0xa3);
         put(0xc0 + (pry1.reg1 << 3) + pry2.reg1);
      }
      else if (pry2.etat < 5)
         goto bang;
      else
      {
         if (sizer == 'B')
         {
            error("Only .W and .L fit to <B..> <reg>,<mem>");
         }
         hey(pry2);
         put(0x0f);
         perform(0xa2 + mediatic, 0xa2 + mediatic, 1, 0, 0x80, 0);
      }
   }
   else
   {
   bang:
      error("unknown <B..> adressing mode");
   }
}

void bt(void)
{
   bits(0);
}

void btc(void)
{
   bits(0x18);
}

void btr(void)
{
   bits(0x10);
}

void bts(void)
{
   bits(0x8);
}

void colle(char uhu, char yo, char helicoptere)
{
   long relative;
   signed short rel2;

   if (!helicoptere)
   {
      take1();
      bwl();
   }
   if (sizer == 'B' || sizer == 'S')
   {
      error("Byte jump is impossible");
   }
   if (pry1.etat < 4 || (uhu && pry1.etat > 5 && pry1.etat < 9))
   {
      relative = pry1.offset - rpc - 3;
      rel2 = (signed short) relative;
      if (sizer == 'L')
      {
         if (seg32 == 0) {
            put(0x67);
         } else {
            relative++;
         }
         put(0xe8);
         relative -= 3;
         wri(&relative, 4);
      }
      else if (rel2 != relative && passe == PASS_LAST)
      {
         error("Jump too far, use JSR.L/JSRF");
      }
      else
      {
         if (seg32 != 0) {
            rel2--;
            put(0x67);
         }
         put(0xe8);
         wri(&rel2, 2);
      }
   }
   else if (pry1.etat == 4)
   {
      if (pry1.reg1 >= 20 && pry1.reg1 < 28)
      {
         sizer = 'L';
         pry1.reg1 -= 20;
      }
      else if ((pry1.reg1 >= 4 && pry1.reg1 < 12) || pry1.reg1 >= 20)
      {
         error("Only word/long registers can fit with JSR/CALL");
      }
      else if (pry1.reg1 >= 12)
      {
         if (sizer == 'W')
            pry1.reg1 -= 12;
         else
         {
            error("Incoherent instruction and register sizes");
         }
      }
      if (sizer == 'L') {
         if (seg32 == 0) {
            put(0x66);
         }
      } else if (seg32 != 0) {
         put(0x66);
      }
      put(0xff);
      put((yo == 0xd0) ? 0xd0 + pry1.reg1 : 0xe0 + pry1.reg1);
   }
   else
   {
      pry2.etat = 4;
      if (sizer == 'L')
         pry2.reg1 = 23;
      else
         pry2.reg1 = 14;
      if (pry1.etat == 8 || (pry1.etat >= 9 && pry1.reg1 >= 20)) {
         if (seg32 == 0) {
            put(0x67);
         }
      } else if (seg32 != 0) {
         put(0x67);
      }
      perform(0xfc, 0xfc, 1, 1, 0x80, (yo == 0xd0) ? 0 : 0x10);
   }
}

void call(void)
{
   colle(0, 0xd0, 0);
}

void callz(void)
{
   colle(1, 0xd0, 0);
}

void collef(char uhu, char stylo)
{
   unsigned short youpla;

   if (uhu)
      take1();
   else
      take2();
   bwl();
   if (sizer == 'B')
   {
      error("Byte values can't fit to far jumps");
   }
   if (uhu)
   {
      pry2.offset = pry1.offset & 0xf;
      pry1.offset >>= 4;
      if (sizer == 'L')
      {
         pry1.etat = 7;
         pry2.etat = 8;
      }
      else if (pry1.offset == (unsigned short) pry1.offset)
      {
         pry1.etat = pry2.etat = 7;
         pry1.r = 1;
      }
      else
      {
         error("Jump too far for a 16 bit segment");
      }
   }
   if (pry1.etat == 6 || pry1.etat == 7)
   {
      if (sizer == 'L' && pry2.etat >= 6 && pry2.etat <= 8)
      {
	 if (seg32 == 0) {
            put(0x66);
         }
         put(stylo);
         wri(&pry2.offset, 4);
         goto jerk;
      }
      else if (pry2.etat == 6 || pry2.etat == 7)
      {
         if (seg32 != 0) {
            put(0x66);
         }
         put(stylo);
         youpla = (unsigned short) pry2.offset;
         tempete(pry2);
         wri(&youpla, 2);
      jerk:
         youpla = (unsigned short) pry1.offset;
         tempete(pry1);
         wri(&youpla, 2);
      }
      else
      {
         error("Incorrect index to far jump");
      }
   }
   else
   {
      error("Incorrect base to far jump");
   }
}

void callf(void)
{
   collef(0, 0x9a);
}

void callzf(void)
{
   collef(1, 0x9a);
}

void cbw(void)
{
   CPUCHECK(C386);
   bwl();
   if (sizer == 'W') {
      if (seg32 != 0) {
         put(0x66);
      }
      put(0x98);
   }
   else if (sizer == 'L')
   {
      if (seg32 == 0) {
         put(0x66);
      }
      put(0x98);
   }
   else
   {
      error("Can't extend to a byte");
   }
}

void cwd(void)
{
   CPUCHECK(C386);
   ware();
   put(0x99);
}

void cwde(void)
{
   CPUCHECK(C386);
   ware();
   if (seg32 == 0) {
      put(0x66);
   }
   put(0x98);
}

void cdq(void)
{
   CPUCHECK(C386);
   if (sizer && passe == PASS_BRIEF)
   {
      warning("Conversion forced from LONG to QUAD");
   }
   if (seg32 == 0) {
      put(0x66);
   }
   put(0x99);
}

void clts(void)
{
   CPUCHECK(C286);
   ware();
   put(0x0f);
   put(0x06);
}

void cmp(void)
{
   perform(0x38, 0x38, 0, 0, 0x80, 0);
}

void test(void)
{
   take2();
   bwl();
   if (pry1.etat < 4)
   {
      if (sizer == 'B')
      {
         if (pry1.etat != 1)
         {
            if (passe == PASS_LAST)
            {
               warning("Constant too large for a byte");
            }
            pry1.offset &= 0xff;
            pry1.etat = 1;
         }
      }
      else if (sizer == 'W')
      {
         if (pry1.etat == 3)
         {
            if (passe == PASS_LAST)
            {
               warning("Constant too large for a word");
            }
            pry1.offset &= 0xffff;
         }
         pry1.etat = 2;
      }
      else
         pry1.etat = 3;
      if (pry2.etat == 4 && (pry2.reg1 == 0 || pry2.reg1 == 4
                             || pry2.reg1 == 12 || pry2.reg1 == 20))
         perform(0xa4, 0xa4, 0, 1, 0xf6, 0);
      else
         perform(0x00, 0x00, 0, 1, 0xf6, 0);
   }
   else
      perform(0x82, 0x82, 0, 1, 0x80, 0);
}

void macadam(char assez)
{
   bwl();
   if (seg32 == 0) {
      if (sizer == 'L')
      {
         CPUCHECK(C286);
         put(0x66);
      }
   } else {
      if (sizer != 'L')
      {
         put(0x66);
      }
   }
   put((sizer == 'B') ? assez : assez + 1);
}

void cmps(void)
{
   macadam(0xa6);
}

void daa(void)
{
   ware();
   put(0x27);
}

void das(void)
{
   ware();
   put(0x2f);
}

void decom(unsigned char banjo)
{
   take1();
   bwl();
   if (pry1.etat == 4)
   {
      if (sizer == 'B')
      {
         if (pry1.reg1 >= 4 && pry1.reg1 < 12)
            pry1.reg1 -= 4;
         else if (pry1.reg1 >= 4)
         {
         demakeup:
            error("Incoherent instruction and register");
         }
         if (seg32 != 0) {
            put(0x66);
         }
         put(0xfe);
         put(0xc0 + banjo + pry1.reg1);
      }
      else if (sizer == 'W')
      {
         if (pry1.reg1 >= 12 && pry1.reg1 < 20)
            pry1.reg1 -= 12;
         else if (pry1.reg1 >= 4)
            goto demakeup;
         if (seg32 != 0) {
            put(0x66);
         }
         put(0x40 + banjo + pry1.reg1);
      }
      else
      {
         if (pry1.reg1 >= 20 && pry1.reg1 < 28)
            pry1.reg1 -= 20;
         else if (pry1.reg1 >= 4)
            goto demakeup;
         if (seg32 == 0) {
            put(0x66);
         }
         put(0x40 + banjo + pry1.reg1);
      }
   }
   else if (pry1.etat < 4)
   {
      error("Can't decrement an immediate value");
   }
   else if (pry1.etat == 8)
   {
      error("Can't manage a 32-bits address");
   }
   else
   {
      pry2.etat = 4;
      pry2.reg1 = 0;
      hey(pry1);
      perform(0xfc, 0xfc, 1, 1, 0x80, banjo);
   }
}

void dec(void)
{
   decom(8);
}

void divide(signed char mobylette)
{
   take1();
   bwl();
   if (pry1.etat == 4)
   {
      if (sizer == 'B')
      {
         if (pry1.reg1 >= 4 && pry1.reg1 < 12)
            pry1.reg1 -= 4;
         else if (pry1.reg1 >= 4)
         {
         demakeup:
            error("Incoherent instruction and register");
         }
	 if (seg32 != 0) {
	    put(0x66);
         }
         put(0xf6);
         put(0xf0 + pry1.reg1 + mobylette);
      }
      else if (sizer == 'W')
      {
         if (pry1.reg1 >= 12 && pry1.reg1 < 20)
            pry1.reg1 -= 12;
         else if (pry1.reg1 >= 4)
            goto demakeup;
         if (seg32 != 0) {
            put(0x66);
         }
         put(0xf7);
         put(0xf0 + pry1.reg1 + mobylette);
      }
      else
      {
         if (pry1.reg1 >= 20 && pry1.reg1 < 28)
            pry1.reg1 -= 20;
         else if (pry1.reg1 >= 4)
            goto demakeup;
         if (seg32 == 0) {
            put(0x66);
         }
         put(0xf7);
         put(0xf0 + pry1.reg1 + mobylette);
      }
   }
   else if (pry1.etat < 4)
   {
      error("Can't modify an immediate value");
   }
   else if (pry1.etat == 8)
   {
      error("Can't manage a 32-bits address");
   }
   else
   {
      pry2.etat = 4;
      pry2.reg1 = 0;
      hey(pry1);
      perform(0xf4, 0xf4, 1, 1, 0x80, 0x30 + mobylette);
   }
}

void div_(void)
{
   divide(0);
}

void enter(void)
{
   unsigned short chatte;

   CPUCHECK(C186);
   take2();
   ware();
   if (pry1.etat == 1 || pry1.etat == 2 || pry1.etat == 6 || pry1.etat == 7)
   {
      if (pry2.etat == 1 || pry2.etat == 6)
      {
         put(0xc8);
         chatte = pry1.offset;
         tempete(pry1);
         wri(&chatte, 2);
         put(pry2.offset);
      }
      else
      {
         error("Immediate byte expected as second argument");
      }
   }
   else
   {
      error("Immediate word expected as first argument");
   }
}

void wait_(void)
{
   ware();
   put(0x9b);
}

void idiv(void)
{
   divide(8);
}

void imul(void)
{
   char *tuviens;
   signed short toudou;

   tuviens = pnt;
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("Missing arguments");
   }
   pry1 = getadrs(pnt);
   bwl();
   if (!pry1.etat)
   {
      error("Invalid adressing mode");
   }
   while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
      pnt++;
   if (*pnt++ != ',')
   {
   ami:
      pnt = tuviens;
      divide(-8);
      return;
   }
   pnt = skipspace(pnt);
   if (pry1.etat >= 13)
   {
      while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
         pnt++;
      if (*pnt++ != ',')
         goto ami;
      pnt = skipspace(pnt);
   }
   pry2 = getadrs(pnt);
   if (!pry2.etat)
   {
      error("Invalid adressing mode");
   }
   while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
      pnt++;
   if (*pnt++ != ',')
   {
   delicate:
      if (pry2.etat != 4)
      {
         error("Register awaited as second argument");
      }
      if (sizer == 'B')
      {
         error("Multiplication of byte registers not allowed");
      }
      if (pry1.etat == 4)
      {
         if (sizer == 'W')
         {
            if (pry1.reg1 >= 12 && pry1.reg1 < 20)
               pry1.reg1 -= 12;
            else if (pry1.reg1 >= 4)
            {
               error("Word register awaited as first argument");
            }
            if (pry2.reg1 >= 12 && pry2.reg1 < 20)
               pry2.reg1 -= 12;
            else if (pry2.reg1 >= 4)
            {
               error("Word register awaited as second argument");
            }
            if (seg32 != 0) {
               put(0x66);
            }
            put(0x0f);
            put(0xaf);
            put(0xc0 + (pry2.reg1 << 3) + pry1.reg1);
         }
         else
         {
            if (pry1.reg1 >= 20 && pry1.reg1 < 28)
               pry1.reg1 -= 20;
            else if (pry1.reg1 >= 4)
            {
               error("Long register awaited as first argument");
            }
            if (pry2.reg1 >= 20 && pry2.reg1 < 28)
               pry2.reg1 -= 20;
            else if (pry2.reg1 >= 4)
            {
               error("Long register awaited as second argument");
            }
	    if (seg32 == 0) {
               put(0x66);
            }
            put(0x0f);
            put(0xaf);
            put(0xc0 + (pry2.reg1 << 3) + pry1.reg1);
         }
      }
      else if (pry1.etat > 5)
      {
         if (pry1.etat == 8)
         {
            error("Direct 32-bits addresses can't be used");
         }
         hey(pry1);
         put(0x0f);
         perform(0xac, 0xac, 1, 1, 0x80, 0);
      }
      else
      {
         pry3 = pry2;
         goto loulou;
      }
      return;
   }
   pnt = skipspace(pnt);
   if (pry1.etat >= 13)
   {
      while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
         pnt++;
      if (*pnt++ != ',')
         goto delicate;
      pnt = skipspace(pnt);
   }
   pry3 = getadrs(pnt);
 loulou:
   if (pry1.etat == 1 || pry1.etat == 2 || (pry1.etat == 3 && sizer == 'L'))
   {
      if (pry3.etat != 4)
      {
         error("Register awaited as third argument");
      }
      if (sizer == 'B')
      {
         error("Multiplication of byte registers not allowed");
      }
      if (pry2.etat == 4)
      {
         if (sizer == 'L')
         {
            if (pry2.reg1 >= 20 && pry2.reg1 < 28)
               pry2.reg1 -= 20;
            else if (pry2.reg1 >= 4)
            {
               error("Long register awaited as second argument");
            }
            if (pry3.reg1 >= 20 && pry3.reg1 < 28)
               pry3.reg1 -= 20;
            else if (pry3.reg1 >= 4)
            {
               error("Long register awaited as third argument");
            }
            if (seg32 == 0) {
               put(0x66);
            }
         }
         else
         {
            if (pry2.reg1 >= 12 && pry2.reg1 < 20)
               pry2.reg1 -= 12;
            else if (pry2.reg1 >= 4)
            {
               error("Word register awaited as second argument");
            }
            if (pry3.reg1 >= 12 && pry3.reg1 < 20)
               pry3.reg1 -= 12;
            else if (pry3.reg1 >= 4)
            {
               error("Word register awaited as third argument");
            }
            if (seg32 != 0) {
               put(0x66);
            }
         }
         if (pry1.etat == 1)
         {
            put(0x6b);
            put(0xc0 + pry2.reg1 + (pry3.reg1 << 3));
            put(pry1.offset);
         }
         else
         {
            if (sizer == 'L')
            {
               put(0x69);
               put(0xc0 + pry2.reg1 + (pry3.reg1 << 3));
               wri(&pry1.offset, 4);
            }
            else
            {
               if (pry1.etat == 3 && passe == PASS_LAST)
               {
                  error("Immediate too large");
               }
               toudou = (signed short) pry1.offset;
               put(0x69);
               put(0xc0 + pry2.reg1 + (pry3.reg1 << 3));
               tempete(pry2);
               wri(&toudou, 2);
            }
         }
      }
      else
      {
         error("MULS <#>,<mem>,<reg> not implemented yet");
      }
   }
   else
   {
      error("Correct constant awaited as first argument");
   }
}

void in(void)
{
   bwl();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("One or two arguments are missing");
   }
   pry1 = getadrs(pnt);
   if (pry1.etat == 7 && pry1.offset <= 255)
      pry1.etat = 6;
   if (pry1.etat != 6 && pry1.etat != 1
       && !(pry1.etat == 4 && (pry1.reg1 == 2 || pry1.reg1 == 14)))
   {
      error("[First] parameter must be D or #<byte>");
   }
   while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
      pnt++;
   if (*pnt++ != ',')
      goto cjwilson;
   pnt = skipspace(pnt);
   if (pry1.etat >= 13)
   {
      while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
         pnt++;
      if (*pnt++ != ',')
         goto cjwilson;
      pnt = skipspace(pnt);
   }
   pry2 = getadrs(pnt);
   if (!(pry2.etat == 4 && (pry2.reg1 == 0 || (pry2.reg1 == 4 && sizer == 'B')
                            || (pry2.reg1 == 12 && sizer == 'W') || (pry2.reg1 == 20 && sizer == 'L'))))
   {
      error("Second parameter must be A or nothing");
   }
 cjwilson:
   if (sizer == 'L') {
      if (seg32 == 0) {
         put(0x66);
      }
   } else if (seg32 != 0) {
      put(0x66);
   }
   if (pry1.etat == 4)
      put((sizer == 'B') ? 0xec : 0xed);
   else
   {
      put((sizer == 'B') ? 0xe4 : 0xe5);
      put(pry1.offset);
   }
}

void out(void)
{
   bwl();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("One or two arguments are missing");
   }
   pry1 = getadrs(pnt);
   if (pry1.etat == 7 && pry1.offset <= 255)
      pry1.etat = 6;
   if (pry1.etat != 6 && pry1.etat != 1
       && !(pry1.etat == 4 && (pry1.reg1 == 2 || pry1.reg1 == 14)))
   {
      if (!(pry1.etat == 4 && (pry1.reg1 == 0 || (pry1.reg1 == 4 && sizer == 'B')
                               || (pry1.reg1 == 12 && sizer == 'W') || (pry1.reg1 == 20 && sizer == 'L'))))
      {
         error("Source parameter must be A or nothing");
      }
      while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
         pnt++;
      if (*pnt++ != ',')
         goto cjwilson;
      pnt = skipspace(pnt);
      if (pry1.etat >= 13)
      {
         while(*pnt != ',' && *pnt != '\n' && *pnt != 13)
            pnt++;
         if (*pnt++ != ',')
            goto cjwilson;
         pnt = skipspace(pnt);
      }
      pry1 = getadrs(pnt);
      if (pry1.etat == 7 && pry1.offset <= 255)
         pry1.etat = 6;
      if (pry1.etat != 6 && pry1.etat != 1
          && !(pry1.etat == 4 && (pry1.reg1 == 2 || pry1.reg1 == 14)))
      {
      cjwilson:
         error("Port number or D expected as target");
      }
   }
   if (sizer == 'L') {
      if (seg32 == 0) {
         put(0x66);
      }
   } else if (seg32 != 0) {
      put(0x66);
   }
   if (pry1.etat == 4)
      put((sizer == 'B') ? 0xee : 0xef);
   else
   {
      put((sizer == 'B') ? 0xe6 : 0xe7);
      put(pry1.offset);
   }
}

void inc(void)
{
   decom(0);
}

void incbin(void)
{
   char *proutos;
   FILE *facteur;
   size_t crash;

   proutos = prout;
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("A file name is missing");
   }
   if (*pnt == '\'' || *pnt == '\"')
   {
      pnt = skipspace(++pnt);
      if (*pnt == 13 || *pnt == '\n')
      {
         error("A file name is missing after the \"");
      }
   }
   while (*pnt != 13 && *pnt != '\n' && *pnt != '\t'
          && *pnt != '\'' && *pnt != '\"')
      *proutos++ = *pnt++;
   *proutos = 0;
   if ((facteur = fopen(prout, "rb")) == NULL)
   {
      fprintf(stderr, "ERROR : Can't open [%s] at line %ld\n", prout , pl);
      exit(EXIT_FAILURE);
   }
   fsh();
   while ((crash = fread(buffer, 1, IOBUFFER, facteur)) != 0)
   {
      wri(buffer, crash);
   }
   fclose(facteur);
}

void yop(char youplaboum)
{
   ware();
   put(youplaboum);
   if (*(pnt = skipspace(pnt)) == ':')
   {
      rpc++;
      pnt++;
      soundgarden();
   }
}

void lock(void)
{
   yop(0xf0);
}

void repne(void)
{
   yop(0xf2);
}

void repe(void)
{
   yop(0xf3);
}

void cs(void)
{
   yop(0x2e);
}

void ds(void)
{
   yop(0x3e);
}

void es(void)
{
   yop(0x26);
}

void fs(void)
{
   yop(0x64);
}

void gs(void)
{
   yop(0x65);
}

void ss(void)
{
   yop(0x36);
}

void rept(void)
{
   if (reupeuteumeu >= 0)
   {
      error("Can't imbricate REPT...ENDR structures");
   }
   take1();
   if (pry1.etat < 4 || pry1.etat == 6 || pry1.etat == 7 || pry1.etat == 8)
   {
      if ((retimes = pry1.offset) <= 0)
      {
         error("Can't repeat a negative (or 0) time");
      }
      else if (retimes == 1 && passe == PASS_BRIEF)
      {
         warning("Superflous REPT...ENDR");
      }
      reupeuteumeu = ftell(joe);
      repl = pl;
   }
   else
   {
      error("Constant expected with a REPT");
   }
}

void endr(void)
{
   if (--retimes)
   {
      fseek(joe, reupeuteumeu, SEEK_SET);
      pl = repl;
   }
   else
      reupeuteumeu = -1;
}

void include(void)
{
   register char *proutos;
   char zok;
   register struct stackent *ent;

   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("INCLUDE needs a file name");
   }
   if (*pnt == '\"')
   {
      pnt++;
      if ((proutos = strchr(pnt, '\"')) == NULL)
      {
         error("Missing double quotes");
      }
      *proutos = 0;
   }
   else if (*pnt == '\'')
   {
      pnt++;
      if ((proutos = strchr(pnt, '\'')) == NULL)
      {
         error("Missing closing quote");
      }
      *proutos = 0;
   }
   proutos = pnt;
   do
   {
      zok = *proutos++;
   }
   while (zok != '\n' && zok != 0 && zok != 13 && zok != '\t');
   *--proutos = 0;

   if (upstack != NULL)
   {
      ent = upstack;
      do
      {
         if (!strcasecmp(ent->file, pnt))
         {
            error("Circular include references");
         }
      }
      while ((ent = ent->link) != NULL);
   }
   if (!isquiet)
   {
      printf("\tIncluding nested file : [%s]\n", pnt);
   }
   if ((ent = (struct stackent *) malloc(sizeof(struct stackent))) == NULL)
   {
      fprintf(stderr, "ERROR : Oh no ! More memory for dynamic stack\n");
      exit(EXIT_FAILURE);
   }
   ent->link = upstack;
   ent->file = sourcefile;
   ent->pl = pl;
   ent->pos = ftell(joe);
   upstack = ent;
   fclose(joe);
   joe = NULL;
   if ((sourcefile = (char *) malloc(strlen(pnt) + 1)) == NULL)
   {
      fprintf(stderr, "ERROR : Outta memory to stack file names\n");
      exit(EXIT_FAILURE);
   }
   strcpy(sourcefile, pnt);
   if ((joe = fopen(sourcefile, "rt")) == NULL)
   {
      fprintf(stderr, "ERROR : Can't include [%s] at line %ld\n", sourcefile, pl);
      exit(EXIT_FAILURE);
   }
   pl = 0;
}

void macro(void)
{
#ifndef REGISTERED

   error("Macros are only available in the registered release");

#else

   register char *onemoretime = line;
   char c;
   register struct macroent *ent;
   char *damacro, *damacropnt;

   for (;;)
   {
      c = *onemoretime;
      if (c == '\t' || c == ' ' || c == ':')
         break;
      onemoretime++;
   }
   *onemoretime++ = 0;
   onemoretime = skipspace(onemoretime);
   if (strtokcasecmp(onemoretime, "macro"))
   {
      warning("Suspicious garbage before MACRO");
   }
   for (;;)
   {
      if (*onemoretime == 0 || *onemoretime == '\n' || *onemoretime == '\r')
      {
         error("Parse error in macro standing");
      }
      if (!strtokcasecmp(onemoretime, "macro"))
         break;
      onemoretime++;
   }
   if ((ent = (struct macroent *) malloc(sizeof(struct macroent))) == NULL)
   {
      warning("No more memory for macros");
      return;
   }
   pnt = line;
   if ((damacro = (char *) malloc(strlen(pnt) + 1)) == NULL)
   {
      warning("Can't store macro name");
      return;
   }
   damacropnt = damacro;
   do {
      *damacropnt++ = c = tolower(*pnt++);
   } while (c != 0);
   ent->link = upmacro;
   ent->file = sourcefile;
   ent->macro = damacro;
   ent->pl = pl + 1;
   ent->pos = ftell(joe);
   upmacro = ent;

#endif
}

void endm(void)
{
#ifdef REGISTERED

#endif
}

void once(void)
{
#ifndef REGISTERED

   warning("Register GEMA to enjoy the ONCE directive");

#else

   register struct stackent *scan = uponce;
   int found = 0;
   char *source2;

   while (scan != NULL)
   {
      if (!strcasecmp(scan->file, sourcefile))
      {
         if (scan->pl == tpasse)
         {
            found = 1;
            break;
         }
         else
         {
            scan->pl = tpasse;
         }
      }
      scan = scan->link;
   }
   if (found)
   {
      fseek(joe, 0, SEEK_END);
      if (isverbose && passe == PASS_BRIEF)
      {
         printf("- Skipping [%s] due to an ONCE directive -\n", sourcefile);
      }
      return;
   }
   if (passe != PASS_BRIEF)
   {
      return;
   }
   if ((scan = (struct stackent *) malloc(sizeof *scan)) == NULL)
   {
      error("No more memory for ONCE pragma");
   }
   if ((source2 = (char *) malloc(strlen(sourcefile) + 1)) == NULL)
   {
      error("Need more memory for ONCE pragma");
   }
   strcpy(source2, sourcefile);
   scan->file = source2;
   scan->pl = tpasse;
   scan->link = uponce;
   uponce = scan;

#endif
}

void set(void)
{
   char *proutos, zok;
   unsigned int size = 0;
   int thinkabout;
   long matou;

   CPUCHECK(C386);
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("SET needs one argument");
   }
   matou = val(pnt);
   ccheck();
   pnt = line;
   proutos = prout;
   for (;;)
   {
      zok = *pnt++;
      if (zok == '\n' || zok == ':' || zok == '\t' || zok == ' ' || zok == 13)
         break;
      if (isalnum(zok) || zok == '_' || zok == '.' || zok == '!')
      {
         *proutos++ = zok;
         size++;
      }
      else
      {
         error("Invalid variable name");
      }
   }
   if (!size)
   {
      error("Variable declaration error");
   }
   prout[size] = 0;
   if ((thinkabout = checkduplicatelabel()) == -1)
   {
      error("SET error");
   }
   else
      where[thinkabout] = matou;
}

void ins(void)
{
   CPUCHECK(C186);
   macadam(0x6c);
}

void into(void)
{
   ware();
   put(0xce);
}

void invd(void)
{
   CPUCHECK(C486);
   ware();
   put(0x0f);
   put(0x08);
}

void iret(void)
{
   if (sizer == 'L') {
      if (seg32 == 0) {
         put(0x66);
      }
   } else if (seg32 != 0) {
      put(0x66);
   }
   else if (sizer == 'B' || sizer == 'S')
   {
      error("Byte return is impossible");
   }
   put(0xcf);
}

void iretd(void)
{
   CPUCHECK(C386);
   ware();
   if (seg32 == 0) {
      put(0x66);
   }
   put(0xcf);
}

void j(char rio)
{
   long relative;
   short rel2;

   take1();
   bwl();
   if (pry1.etat != 1 && pry1.etat != 2 && pry1.etat != 3
       && pry1.etat != 6 && pry1.etat != 7 && pry1.etat != 8)
   {
      error("Pointer expected");
   }
   relative = pry1.offset - rpc;
   if (sizer == 'B')
   {
hun:
      relative -= 2;
      if (relative > 127 || relative < -128)
      {
         if (passe == PASS_LAST)
         {
            error("Jump too far for a byte, try .W");
         }
         else
         {
            relative = 0;
         }
      }
      if (seg32 != 0) {
         put(0x67);
         relative--;
      }
      put(rio);
      put(relative);
   }
   else if (sizer == 'W')
   {
      if (optimize != 0 && unresolvedlabel == 0)
      {
         if (relative <= 0x7a && relative >= -0x7a)
         {
            if (isverbose && passe == PASS_LAST)
            {
               warning("Conditional jump was made short");
            }
            sizer = 'B';
            goto hun;
         }
      }
      relative -= 4;
      rel2 = (signed short) relative;
      if (relative < -0x7ff0L || relative > 0x7ff0L)
      {
         if (passe == PASS_LAST)
         {
            error("Jump too far for a word, try .L");
         }
         else
         {
            relative = 0;
         }
      }
      if (seg32 != 0) {
         put(0x67);
         rel2--;
      }
      put(0x0f);
      put(rio + 0x10);
      wri(&rel2, 2);
   }
   else
   {
      relative -= 4;
      if (seg32 == 0) {
         put(0x67);
         relative--;
      }
      put(0x0f);
      put(rio + 0x10);
      wri(&relative, 4);
   }
}

void ja(void)
{
   j(0x77);
}

void jae(void)
{
   j(0x73);
}

void jb(void)
{
   j(0x72);
}

void jbe(void)
{
   j(0x76);
}

void bizaroide(char trouakar)
{
   long relative;

   take1();
   if (pry1.etat != 1 && pry1.etat != 2 && pry1.etat != 3
       && pry1.etat != 6 && pry1.etat != 7 && pry1.etat != 8)
   {
      error("8-bits pointer expected");
   }
   if (sizer == 'W' || sizer == 'L')
   {
      error("BCXZ and BCEZ can only address a 8-bits offset");
   }
   relative = pry1.offset - rpc - 2 - trouakar;
   if (passe == PASS_LAST && (relative > 127 || relative < -128))
   {
      error("Jump out of byte range");
   }
   if (trouakar) {
      if (seg32 == 0) {
         put(0x67);
      }
   } else if (seg32 != 0) {
      put(0x67);
   }
   put(0xe3);
   put(relative);
}

void jcxz(void)
{
   bizaroide(0);
}

void jecxz(void)
{
   bizaroide(1);
}

void je(void)
{
   j(0x74);
}

void jg(void)
{
   j(0x7f);
}

void jge(void)
{
   j(0x7d);
}

void jl(void)
{
   j(0x7c);
}

void jle(void)
{
   j(0x7e);
}

void jno(void)
{
   j(0x71);
}

void jnp(void)
{
   j(0x7b);
}

void jns(void)
{
   j(0x79);
}

void jne(void)
{
   j(0x75);
}

void jo(void)
{
   j(0x70);
}

void jp(void)
{
   j(0x7a);
}

void js(void)
{
   j(0x78);
}

void s(char rio)
{
   take1();
   if ((sizer == 'W' || sizer == 'L') && passe == PASS_BRIEF)
   {
      warning("Size forced to BYTE at line");
   }
   sizer = 'B';
   if (pry1.etat < 4)
   {
      error("Register or byte pointer expected");
   }
   hey(pry1);
   pry2.etat = 4;
   pry2.reg1 = 0;
   put(0x0f);
   rio += 0x1e;
   perform(rio, rio, 1, 1, 0x80, 0);
}

void seta(void)
{
   s(0x77);
}

void setae(void)
{
   s(0x73);
}

void setb(void)
{
   s(0x72);
}

void setbe(void)
{
   s(0x76);
}

void sete(void)
{
   s(0x74);
}

void setg(void)
{
   s(0x7f);
}

void setge(void)
{
   s(0x7d);
}

void setl(void)
{
   s(0x7c);
}

void setle(void)
{
   s(0x7e);
}

void setno(void)
{
   s(0x71);
}

void setnp(void)
{
   s(0x7b);
}

void setns(void)
{
   s(0x79);
}

void setne(void)
{
   s(0x75);
}

void seto(void)
{
   s(0x70);
}

void setp(void)
{
   s(0x7a);
}

void sets(void)
{
   s(0x78);
}

void jump(char uhu)
{
   long relative;
   signed short rel2;

   take1();
   bwl();
   if (pry1.etat < 4 || (uhu && pry1.etat > 5 && pry1.etat < 9))
   {
      relative = pry1.offset - rpc;
      if (sizer == 'B')
      {
nutsycat:
         relative -= 2;
         if (seg32 != 0) {
            relative--;
         }
         if (passe == PASS_LAST && (relative > 0x7a || relative < -0x7a))
         {
            error("Byte jump out of range, try .W");
         }
         if (relative == 0 && optimize != 0 && unresolvedlabel == 0)
         {
            if (isverbose && passe == PASS_LAST)
            {
               warning("Dummy jump replaced by nops");
            }
            put(0x90);
            put(0x90);

            return;
         }
         if (seg32 != 0) {
            put(0x67);
         }
         put(0xeb);
         put(relative);
      }
      else if (sizer == 'W')
      {
         if (optimize != 0 && unresolvedlabel == 0)
         {
            if (relative <= 0x7a && relative >= -0x7a) /* $fd */
            {
               if (isverbose && passe == PASS_LAST)
               {
                  warning("Jump was made short");
               }
               sizer = 'B';
               goto nutsycat;
            }
         }
         relative -= 3;
         if (seg32 != 0) {
            relative--;
         }
         rel2 = (signed short) relative;
         if (passe == PASS_LAST && relative != rel2)
         {
            error("Word jump out of range, try .L");
         }
         if (seg32 != 0) {
            put(0x67);
         }
         put(0xe9);
         wri(&rel2, 2);
      }
      else
      {
         relative -= 5;

         if (seg32 == 0) {
            put(0x67);
            relative--;
         }
         put(0xe9);
         wri(&relative, 4);
      }
   }
   else
   {
      colle(uhu, 0xc0, 1);
   }
}

void jmp(void)
{
   jump(0);
}

void jmpz(void)
{
   jump(1);
}

void jmpf(void)
{
   collef(0, 0xea);
}

void jmpzf(void)
{
   collef(1, 0xea);
}

void lahf(void)
{
   put(0x9f);
}

void leave(void)
{
   CPUCHECK(C186);
   put(0xc9);
}

void lods(void)
{
   macadam(0xac);
}

void movs(void)
{
   macadam(0xa4);
}

void scas(void)
{
   macadam(0xae);
}

void outs(void)
{
   CPUCHECK(C186);
   macadam(0x6e);
}

void stos(void)
{
   macadam(0xaa);
}

void loupe(char pabo)
{
   long relative;

   take1();
   ware();
   if (pry1.etat < 4 || pry1.etat == 6 || pry1.etat == 7 || pry1.etat == 8)
   {
      relative = pry1.offset - rpc - 2;
      if ((relative > 127 || relative < -128) && passe == PASS_LAST)
      {
         error("Loop too far");
      }
      put(pabo);
      put(relative);
   }
   else
   {
      error("Short pointer expected");
   }
}

void loop(void)
{
   loupe(0xe2);
}

void loope(void)
{
   loupe(0xe1);
}

void loopne(void)
{
   loupe(0xe0);
}

void wbinvd(void)
{
   CPUCHECK(C486);
   ware();
   put(0x0f);
   put(0x09);
}

void gro(char sac)
{
   char *vroum;

   CPUCHECK(C286);
   vroum = pnt;
   take2();
   bwl();
   if (sizer == 'B' || pry2.etat != 4)
   {
      error("Word or long register expected");
   }
   if (pry1.etat < 4)
   {
      error("Can't load from a constant");
   }
   pnt = vroum;
   hey(pry1);
   put(0x0f);
   perform(sac, sac, 1, 1, 0x80, 0);
}

void lar(void)
{
   gro(-1);
}

void lsl(void)
{
   gro(0);
}

void lds(void)
{
   limit2();
   perform(0xc2, 0xc2, 0, 0, 0x80, 0);
}

void les(void)
{
   limit2();
   perform(0xc1, 0xc1, 0, 0, 0x80, 0);
}

void lfs(void)
{
   CPUCHECK(C386);
   limit2();
   hey(pry1);
   put(0x0f);
   perform(0xb1, 0xb1, 1, 1, 0x80, 0);
}

void lgs(void)
{
   CPUCHECK(C386);
   limit2();
   hey(pry1);
   put(0x0f);
   perform(0xb2, 0xb2, 1, 1, 0x80, 0);
}

void lss(void)
{
   CPUCHECK(C386);
   limit2();
   hey(pry1);
   put(0x0f);
   perform(0xaf, 0xaf, 1, 1, 0x80, 0);
}

void lt(char c)
{
   CPUCHECK(C286);
   take1();
   ware();
   sizer = 'W';
   if (pry1.etat < 5)
   {
      error("64-bits pointer expected");
   }
   hey(pry1);
   pry2.etat = 4;
   pry2.reg1 = 0;
   put(0x0f);
   perform(-2, -2, 1, 1, 0x80, c);
}

void lgdt(void)
{
   lt(0x10);
}

void lidt(void)
{
   lt(0x18);
}

void sgdt(void)
{
   lt(0x00);
}

void sidt(void)
{
   lt(0x08);
}

void ohoho(char tchac, char poum)
{
   CPUCHECK(C286);
   take1();
   ware();
   sizer = 'W';
   if (pry1.etat < 4)
   {
      error("16-bits pointer or register expected");
   }
   hey(pry1);
   pry2.etat = 4;
   pry2.reg1 = 0;
   put(0x0f);
   perform(tchac, tchac, 1, 1, 0x80, poum);
}

void lldt(void)
{
   ohoho(-3, 0x10);
}

void sldt(void)
{
   ohoho(-3, 0x00);
}

void lmsw(void)
{
   ohoho(-2, 0x30);
}

void smsw(void)
{
   ohoho(-2, 0x20);
}

void ltr(void)
{
   ohoho(-3, 0x18);
}

void verr(void)
{
   ohoho(-3, 0x20);
}

void verw(void)
{
   ohoho(-3, 0x28);
}

void str(void)
{
   ohoho(-3, 0x08);
}

void mov(void)
{
   signed short purelove;
   struct lotus coca;
   int lendemain;

   take2();
   bwl();
   if (pry1.etat < 4)
   {
      if (sizer == 'B')
      {
         if (pry1.etat != 1)
         {
            if (passe == PASS_LAST)
            {
               warning("Constant too large for a byte");
            }
            pry1.etat = 1;
            pry1.offset &= 0xff;
         }
      }
      else if (sizer == 'W')
      {
         if (pry1.etat == 3)
         {
            if (passe == PASS_LAST)
            {
               warning("Constant too large for a word");
            }
            pry1.offset &= 0xffff;
         }
         pry1.etat = 2;
      }
      else
         pry1.etat = 3;
      if (pry2.etat == 4)
      {
         switch (sizer)
         {
         case 'B' :
            if (pry2.reg1 >= 4 && pry2.reg1 < 12)
               pry2.reg1 -= 4;
            else if (pry2.reg1 >= 4)
            {
               error("Byte register expected");
            }
            if (seg32 != 0) {
               put(0x66);
            }
            put(0xb0 + pry2.reg1);
            put(pry1.offset);
            break;
         case 'W' :
            if (pry2.reg1 >= 12 && pry2.reg1 < 20)
               pry2.reg1 -= 12;
            else if (pry2.reg1 >= 4)
            {
               error("Word register expected");
            }
            if (seg32 != 0) {
               put(0x66);
            }
            put(0xb8 + pry2.reg1);
            purelove = (signed short) pry1.offset;
            tempete(pry1);
            wri(&purelove, 2);
            break;
         default :
            if (pry2.reg1 >= 20 && pry2.reg1 < 28)
               pry2.reg1 -= 20;
            else if (pry2.reg1 >= 4)
            {
               error("Long register expected");
            }
            if (seg32 == 0) {
               put(0x66);
            }
            put(0xb8 + pry2.reg1);
            wri(&pry1.offset, 4);
         }
      }
      else
         perform(0x00, 0x00, 0, 1, 0xc6, 0);
   }
   else if (pry1.etat == 4 &&
      (pry1.reg1 == 0 || pry1.reg1 == 4 || pry1.reg1 == 12 || pry1.reg1 == 20)
      && pry2.etat >= 6 && pry2.etat <= 8) /* a?,$xxx */
   {
      switch (sizer) {
         case 'B' :
            if (seg32 != 0) {
               put(0x66);
            }
	    if (pry2.etat == 8) {
               if (seg32 == 0) {
                  put(0x67);
               }
	    } else if (seg32 != 0) {
	       put(0x67);
	    }
            put(0xa2);
            if (pry2.etat == 8) {
               wri(&pry2.offset, 4);
            } else {
               wri(&pry2.offset, 2);
            }

            break;
	 case 'W' :
	    if (seg32 != 0) {
	       put(0x66);
	    }
telephone:
	    if (pry2.etat == 8) {
	       if (seg32 == 0) {
	          put(0x67);
	       }
	    } else if (seg32 != 0) {
	       put(0x67);
	    }
	    put(0xa3);
	    if (pry2.etat == 8) {
	       wri(&pry2.offset, 4);
	    } else {
   	       wri(&pry2.offset, 2);
   	    }

	    break;
	 default :
	    if (seg32 == 0) {
	       put(0x66);
	    }
            goto telephone;
      }
   }
   else if (pry2.etat == 4 &&
      (pry2.reg1 == 0 || pry2.reg1 == 4 || pry2.reg1 == 12 || pry2.reg1 == 20)
      && pry1.etat >= 6 && pry1.etat <= 8) /* $xxx,a? */
   {
      switch (sizer) {
         case 'B' :
            if (seg32 != 0) {
               put(0x66);
            }
	    if (pry1.etat == 8) {
               if (seg32 == 0) {
                  put(0x67);
               }
	    } else if (seg32 != 0) {
	       put(0x67);
	    }
            put(0xa0);
            if (pry1.etat == 8) {
               wri(&pry1.offset, 4);
            } else {
               wri(&pry1.offset, 2);
            }

            break;
	 case 'W' :
	    if (seg32 != 0) {
	       put(0x66);
	    }
telephone2:
	    if (pry1.etat == 8) {
	       if (seg32 == 0) {
	          put(0x67);
	       }
	    } else if (seg32 != 0) {
	       put(0x67);
	    }
	    put(0xa1);
	    if (pry1.etat == 8) {
	       wri(&pry1.offset, 4);
	    } else {
   	       wri(&pry1.offset, 2);
   	    }

	    break;
	 default :
	    if (seg32 == 0) {
	       put(0x66);
	    }
            goto telephone2;
      }
   }
   else if (pry1.reg1 >=28 && pry1.reg1 < 34 && pry1.etat == 4)
   {
      if (sizer != 'W')
      {
         error("With a segment register, use MOV[E][.W]");
      }
      pry1.reg1 -= 28;
      if (pry2.etat == 4)
      {
         if (pry2.reg1 >= 12 && pry2.reg1 < 20)
            pry2.reg1 -= 12;
         else if (pry2.reg1 >= 4)
         {
            error("Word register expected with a segment");
         }
	 if (seg32 != 0) {
	    put(0x66);
	 }
         put(0x8c);
         put(0xc0 + pry2.reg1 + (pry1.reg1 << 3));
      }
      else
      {
         pry1.reg1 += 12;
         perform(0x8b, 0x8b, 0, 1, 0x80, 0);
      }
   }
   else if (pry2.reg1 >=28 && pry2.reg1 < 34 && pry2.etat == 4)
   {
      if (sizer != 'W')
      {
         error("With a segment register, use MOV[E][.W]");
      }
      pry2.reg1 -= 28;
      if (pry1.etat == 4)
      {
         if (pry1.reg1 >= 12 && pry1.reg1 < 20)
            pry1.reg1 -= 12;
         else if (pry1.reg1 >= 4)
         {
            error("Word register expected with a segment");
         }
         if (seg32 != 0) {
            put(0x66);
         }
         put(0x8e);
         put(0xc0 + pry1.reg1 + (pry2.reg1 << 3));
      }
      else
      {
         pry2.reg1 += 12;
         perform(0x8b, 0x8b, 0, 1, 0x80, 0);
      }
   }
   else if (pry2.etat == 4 && pry2.reg1 >= 34)
   {
      coca = pry1;
      pry1 = pry2;
      pry2 = coca;
      lendemain = 2;
      goto toujours;
   }
   else if (pry1.etat == 4 && pry1.reg1 >= 34)
   {
      lendemain = 0;
   toujours:
      CPUCHECK(C286);
      if (sizer != 'L')
      {
         error("Use MOV[E].L with a control register");
      }
      if (pry2.etat != 4)
      {
         error("Register expected");
      }
      if (pry2.reg1 >= 20 && pry2.reg1 < 28)
         pry2.reg1 -= 20;
      else if (pry2.reg1 >= 4)
      {
         error("32-bits register expected");
      }
      put(0x0f);
      if (pry1.reg1 < 37)
      {
         put(0x20 + lendemain);
         switch (pry1.reg1)
         {
         case 34 :
            put(0xc0 + pry2.reg1);
            break;
         case 35 :
            put(0xd0 + pry2.reg1);
            break;
         default :
            put(0xd8 + pry2.reg1);
         }
      }
      else if (pry1.reg1 < 43)
      {
         put(0x21 + lendemain);
         switch (pry1.reg1)
         {
         case 37 :
         case 38 :
         case 39 :
         case 40 :
            put(0xc0 + pry2.reg1 + ((pry1.reg1 - 37) << 3));
            break;
         default :
            put(0xc0 + pry2.reg1 + ((pry1.reg1 - 35) << 3));
         }
      }
      else
      {
         put(0x24 + lendemain);
         put(0xd8 + pry2.reg1 + ((pry1.reg1 - 43) << 3));
      }
   }
   else
   {
      perform(0x88, 0x88, 0, 1, 0x80, 0);
   }
}

void movx(char tsoin)
{
   CPUCHECK(C386);
   limit();
   if (sizer == 'W')
   {
      if (pry1.etat == 4)
      {
         if (pry1.reg1 >= 4 && pry1.reg1 < 12)
            pry1.reg1 += 8;
         else if (pry1.reg1 >= 4)
         {
            error("First argument must be a byte register");
         }
      }
   }
   else
   {
      if (pry1.etat == 4)
      {
         if (pry1.reg1 >= 4 && pry1.reg1 < 12)
            pry1.reg1 += 16;
         else if (pry1.reg1 >= 12 && pry1.reg1 < 20)
         {
            pry1.reg1 += 8;
            tsoin++;
         }
         else if (pry1.reg1 >= 4)
         {
            error("First argument must be a byte or word register");
         }
      }
   }
   hey(pry1);
   put(0x0f);
   perform(tsoin, tsoin, 1, 1, 0x80, 0);
}

void movsx(void)
{
   movx(0xbb);
}

void movzx(void)
{
   movx(0xb3);
}

void mol(char iowa)
{
   take1();
   bwl();
   if (pry1.etat < 4)
   {
      error("Can't deal with immediate values");
   }
   pry2.etat = 4;
   pry2.reg1 = 0;
   perform(0xf4, 0xf4, 0, 1, 0x80, iowa);
}

void mul(void)
{
   mol(0x20);
}

void neg(void)
{
   mol(0x18);
}

void not(void)
{
   mol(0x10);
}

void or(void)
{
   perform(0x08, 0x08, 0, 0, 0x80, 0);
}

void pop(void)
{
   take1();
   bwl();
   if (sizer == 'B')
   {
      error("Can't work on bytes");
   }
   if (pry1.etat < 4)
   {
      error("Can't POP a constant");
   }
   else if (pry1.etat == 4)
   {
      if (sizer == 'W')
      {
         if (pry1.reg1 >= 28 && pry1.reg1 < 34)
         {
            switch(pry1.reg1)
            {
            case 28 :
               put(0x07);
               break;
            case 29 :
               error("Can't POP CS");
            case 30 :
               put(0x17);
               break;
            case 31 :
               put(0x1f);
               break;
            case 32 :
               put(0x0f);
               put(0xa1);
               break;
            default :
               put(0x0f);
               put(0xa9);
            }
            return;
         }
         if (pry1.reg1 >= 12 && pry1.reg1 < 20)
            pry1.reg1 -= 12;
         else if (pry1.reg1 >= 4)
         {
         wakeup:
            error("Incorrect register size");
         }
         if (seg32 != 0) {
            put(0x66);
         }
      }
      else
      {
         if (pry1.reg1 >= 20 && pry1.reg1 < 28)
            pry1.reg1 -= 20;
         else if (pry1.reg1 >= 4)
            goto wakeup;
	 if (seg32 == 0) {
            put(0x66);
         }
      }
      put(0x58 + pry1.reg1);
   }
   else
   {
      pry2.etat = 4;
      pry2.reg1 = 0;
      perform(0x8c, 0x8c, 0, 1, 0x80, 0);
   }
}

void popa(void)
{
   if (sizer == 'B' || sizer == 'S')
   {
      error("Can't pop 8-bits parts");
   }
   else if (sizer == 'L') {
      CPUCHECK(C386);
      if (seg32 == 0) {
         put(0x66);
      }
   } else {
      CPUCHECK(C386);
   }
   put(0x61);
}

void popf(void)
{
   if (sizer == 'B' || sizer == 'S')
   {
      error("FLAG is a 16 or 32 bits register");
   }
   else if (sizer == 'L') {
      CPUCHECK(C386);
      if (seg32 == 0) {
         put(0x66);
      }
   }
   put(0x9d);
}

void push(void)
{
   take1();
   bwl();
   if (pry1.etat < 4)
   {
      if (sizer == 'B')
      {
         if (seg32 != 0) {
            put(0x66);
         }
         put(0x6a);
         if (pry1.offset > 255 && passe == PASS_LAST)
         {
            warning("Pushed immediate too large for a byte");
         }
         put(pry1.offset);
      }
      else if (sizer == 'W')
      {
         if (seg32 != 0) {
            put(0x66);
         }
         put(0x68);
         if (pry1.offset > 65535 && passe == PASS_LAST)
         {
            warning("Pushed immediate too large for a word");
         }
         wri(&pry1.offset, 2);
      }
      else if (passe == PASS_LAST)
      {
         if (seg32 == 0) {
            put(0x66);
         }
         put(0x68);
         wri(&pry1.offset, 4);
      }
      return;
   }
   if (sizer == 'B')
   {
      error("Can't work on bytes");
   }
   else if (pry1.etat == 4)
   {
      if (sizer == 'W')
      {
         if (pry1.reg1 >= 28 && pry1.reg1 < 34)
         {
            switch(pry1.reg1)
            {
            case 28 :
               put(0x06);
               break;
            case 29 :
               put(0x0e);
               break;
            case 30 :
               put(0x16);
               break;
            case 31 :
               put(0x1e);
               break;
            case 32 :
               put(0x0f);
               put(0xa0);
               break;
            default :
               put(0x0f);
               put(0xa8);
            }
            return;
         }
         if (pry1.reg1 >= 12 && pry1.reg1 < 20)
            pry1.reg1 -= 12;
         else if (pry1.reg1 >= 4)
         {
         wakeup:
            error("Incorrect register size");
         }
         if (seg32 != 0) {
            put(0x66);
         }
      }
      else
      {
         if (pry1.reg1 >= 20 && pry1.reg1 < 28)
            pry1.reg1 -= 20;
         else if (pry1.reg1 >= 4)
            goto wakeup;
         if (seg32 == 0) {
            put(0x66);
         }
      }
      put(0x50 + pry1.reg1);
   }
   else
   {
      pry2.etat = 4;
      pry2.reg1 = 0;
      perform(0xfc, 0xfc, 0, 1, 0x80, 0x30);
   }
}

void pusha(void)
{
   if (sizer == 'B' || sizer == 'S')
   {
      error("Can't push 8-bits parts");
   }
   else if (sizer == 'L') {
      CPUCHECK(C386);
      if (seg32 == 0) {
         put(0x66);
      }
   } else {
      CPUCHECK(C186);
   }
   put(0x60);
}

void pushf(void)
{
   if (sizer == 'B' || sizer == 'S')
   {
      error("FLAG is a 16 or 32 bits register");
   }
   else if (sizer == 'L') {
      CPUCHECK(C386);
      if (seg32 == 0) {
         put(0x66);
      }
   }
   put(0x9c);
}

void stayfresh(char kinky)
{
   take2();
   bwl();
   if (pry2.etat == 4)
   {
      if (sizer == 'B')
      {
         if (pry2.reg1 >= 4 && pry2.reg1 < 12)
            pry2.reg1 -= 4;
         else if (pry2.reg1 >= 4)
         {
            error("Byte register expected");
         }
      }
      else if (sizer == 'W')
      {
         if (pry2.reg1 >= 12 && pry2.reg1 < 20)
            pry2.reg1 -= 12;
         else if (pry2.reg1 >= 4)
         {
            error("Word register expected");
         }
      }
      else
      {
         if (pry2.reg1 >=20 && pry2.reg1 < 28)
            pry2.reg1 -= 20;
         else if (pry2.reg1 >= 4)
         {
            error("Long register expected");
         }
      }
      if (pry1.etat == 4)
      {
         if (pry1.reg1 == 1 || pry1.reg1 == 5)
         {
            macadam(0xd2);
            put(0xc0 + pry2.reg1 + kinky);
         }
         else
         {
            error("Only CL would work as counter");
         }
      }
      else if (pry1.etat != 1)
      {
         error("Byte constant or C expected as count index");
      }
      else if (pry1.offset == 1)
      {
         macadam(0xd0);
         put(0xc0 + pry2.reg1 + kinky);
      }
      else
      {
         macadam(0xc0);
         put(0xc0 + pry2.reg1 + kinky);
         put(pry1.offset);
      }
   }
   else if (pry2.etat < 4)
   {
      error("Can't modify a constant");
   }
   else
   {
      if (pry1.etat == 4)
      {
         if (pry1.reg1 == 1 || pry1.reg1 == 5)
         {
            pry1.etat = 4;
            pry1.reg1 = 0;
            perform(0xd2, 0xd2, 0, 1, 0x80, kinky);
         }
         else
         {
            error("Only CL would work as counter");
         }
      }
      else if (pry1.etat != 1)
      {
         error("Byte constant or C expected as count index");
      }
      else if (pry1.offset == 1)
      {
         pry1.etat = 4;
         pry1.reg1 = 0;
         perform(0xd0, 0xd0, 0, 1, 0x80, kinky);
      }
      else
         perform(kinky, kinky, 0, 1, (sizer == 'B') ? 0xc0 : 0xbe, kinky);
   }
}

void rol(void)
{
   stayfresh(0x00);
}

void ror(void)
{
   stayfresh(0x08);
}

void rcl(void)
{
   stayfresh(0x10);
}

void rcr(void)
{
   stayfresh(0x18);
}

void shl(void)
{
   stayfresh(0x20);
}

void shr(void)
{
   stayfresh(0x28);
}

void sar(void)
{
   stayfresh(0x38);
}

void sahf(void)
{
   ware();
   put(0x9e);
}

void shiftd(char addon)
{
   struct lotus coca;
   char auphset = 0;

   CPUCHECK(C386);
   bwl();
   if (sizer == 'B')
   {
      error("SHLD/SHRD can't deal with byte registers");
   }
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("Syntax is SHLD/SHRD [CL|#] <source> <target>");
   }
   coca = getadrs(pnt);
   if (coca.etat == 2 || coca.etat == 3)
   {
      warning("Constant converted to an unsigned 8-bit type");
      auphset = (unsigned char) coca.offset;
   }
   else if (coca.etat == 1)
   {
      auphset = coca.offset;
   }
   else if (coca.etat == 4)
   {
      if (coca.reg1 == 5)
      {
         coca.reg1 = 1;
      }
      else if (coca.reg1 != 1)
      {
         error("Shift register must be CL");
      }
   }
   else
   {
      error("Syntax is SHLD/SHRD [CL|#] <source> <target>");
   }
   if ((pnt = nextcoma(pnt)) == NULL)
   {
      error("SHLD/SHRD need three arguments");
   }
   pnt = skipspace(pnt);
   pry2 = getadrs(pnt);
   if (pry2.etat != 4)
   {
      error("Register awaited as source value");
   }
   if (pry2.reg1 >= 12 && pry2.reg1 < 20)
   {
      if (sizer != 'W')
      {
         error("Incoherent instruction (L) and source (W) sizes");
      }
      pry2.reg1 -= 12;
   }
   else if (pry2.reg1 >= 20 && pry2.reg1 < 28)
   {
      if (sizer != 'L')
      {
         error("Incoherent instruction (W) and source (L) sizes");
      }
      pry2.reg1 -= 20;
   }
   else if (pry2.reg1 >= 4)
   {
      error("Second argument (source) must be a register");
   }
   if ((pnt = nextcoma(pnt)) == NULL)
   {
      error("Third argument (target) awaited with SHLD/SHRD");
   }
   pnt = skipspace(pnt);
   pry1 = getadrs(pnt);
   if (pry1.etat < 4)
   {
      error("Last argument is the target one, not an immediate");
   }
   hey(pry1);
   put(0x0f);
   if (coca.etat == 4)
   {
      perform(addon + 1, addon + 1, 1, 1, 0x80, 0);
   }
   else
   {
      perform(addon, addon, 1, 1, 0x80, 0);
      put(auphset);
   }
}

void shld(void)
{
   shiftd(0xa1);
}

void shrd(void)
{
   shiftd(0xa9);
}

void xchg(void)
{
   struct lotus vain;

   take2();
   if (pry1.etat < 4)
   {
      error("Can't swap a constant");
   }
   else if (pry1.etat == 4)
   {
      vain = pry1;
      pry1 = pry2;
      pry2 = vain;
   }
   perform(0x84, 0x84, 0, 1, 0x80, 0);
}

void xlat(void)
{
   ware();
   put(0xd7);
}

void stack(void)
{
   if (stk && passe == PASS_BRIEF)
   {
      error("Redefinition of STACK");
   }
   stk = rpc;
}

void header(void)
{
   long savepcwoalign = pcwoalign;

   ware();
   if (passe == PASS_LAST)
   {
      long kedal = 0, total;
      short kala;
      long th = 0;
      char *pub = " Assembled with GEMA "; /* 21+1 */
      char *csa;
      int pouf;

      th = (relocpnt << 2) + 50;
      while(th & 0x0f)
      {
         th++;
      }
      put(0x4d);
      put(0x5a);
      total = taille + th;
      kala = total & 0x1ff;
      wri(&kala, 2);
      if (kala)
      {
         kala = (total >> 9) + 1;
      }
      else
      {
         kala = total >> 9;
      }
      wri(&kala, 2);
      wri(&relocpnt, 2);
      kala = th >> 4;
      wri(&kala, 2);
      wri(&lowlim, 2);
      wri(&lim, 2);
      kala = (stk & ~0xffff) >> 4;
      wri(&kala, 2);
      kala = stk & 0xffff;
      wri(&kala, 2);
      wri(&kedal, 2);
      kala = rpc & 0xffff;
      wri(&kala, 2);
      kala = (rpc & ~0xffff) >> 4;
      wri(&kala, 2);
      put(50);
      put(0);
      wri(&ovrlay, 2);
      for (csa = pub; csa < pub + 22; csa += 2)
      {
         wri(csa, 2);
      }
      for (pouf = 0; pouf < relocpnt; pouf++)
      {
         kala = reloc[pouf] & 0xffff;
         wri(&kala, 2);
         kala = (reloc[pouf] & ~0xffff) >> 4;
         wri(&kala, 2);
      }
      while(pc & 0x0f)
      {
         put(0);
      }
      pc = rpc;
      relocpnt = 0;
   }
   exe = 1;
   pcwoalign = savepcwoalign;
}

void limite(void)
{
   ware();
   if (lim != 0xffff && passe == PASS_BRIEF)
   {
      error("Max size redefinition");
   }
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("LIMIT needs one argument");
   }
   lim = val(pnt);
   ccheck();
}

void mini(void)
{
   ware();
   if (lowlim && passe == PASS_BRIEF)
   {
      error("Min size redefinition");
   }
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("MINI needs one argument");
   }
   lowlim = val(pnt);
   ccheck();
}

void overlay(void)
{
   ware();
   if (ovrlay && passe == PASS_BRIEF)
   {
      error("Redefinition of overlay ID");
   }
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("OVERLAY needs one argument");
   }
   ovrlay = val(pnt);
   ccheck();
}

void column(void)
{
   if (*(pnt = skipspace(pnt)) == ':')
   {
      pnt++;
      soundgarden();
   }
}

void real(void)
{
   ware();
   maxsegsize = maxsegcounter = 65536;
   ccheck();
   column();
}

void unreal(void)
{
   ware();
   maxsegsize = maxsegcounter = -1;
   ccheck();
   column();
}

void segsize(void)
{
   ware();
   if ((pnt = nextarg(pnt)) == NULL)
   {
      error("SEGSIZE expects a segment size");
   }
   maxsegsize = maxsegcounter = val(pnt);
   if (maxsegsize < 0 && nowarning == 0) {
      checkquiet();
      fprintf(stderr, "WARNING : Negative segment size at line %ld - No more check for that segment\n", pl);
      maxsegsize = -1;
   } else if (maxsegsize == 0 && nowarning == 0) {
      checkquiet();
      fprintf(stderr, "WARNING : Null segment size at line %ld - No more limit in that segment\n", pl);
      maxsegsize = -1;
   } else if (maxsegsize == 1 && nowarning == 0) {
      checkquiet();
      fprintf(stderr, "WARNING : Declaring a single-byte segment at line %ld\n", pl);
   }
   ccheck();
   column();
}

void bss(void)
{
   bssflag = 1;
}

void text(void)
{
   bssflag = 0;
}

void use32(void)
{
   CPUCHECK(C386);
   seg32 = 1;
}

void use16(void)
{
   seg32 = 0;
}

void objheader(void)
{
   long savepcwoalign = pcwoalign;
   size_t sfnl = strlen(sourcefile);
   long taillework = battletech + 4;
   long taillework2 = battletech;

   ware();
   if (passe == PASS_LAST)
   {

/* $80 - Title */

      put(0x80);
      put(sfnl + 2); put(0);
      put(sfnl);
      wri(sourcefile, sfnl);
      put(0);

/* $96 - LNames */

      put(0x96);
      put(2); put(0);
      put(0);
      put(0);

/* $88 - Comment */

      put(0x88);
      put(3); put(0);
      put(0x40); put(0xa1);
      put(0);

/* $96 - LNames */

      put(0x96);
      put(12); put(0);
      put(5); put(0x5f); put(0x54); put(0x45); put(0x58);
      put(0x54); put(0x04); put(0x43); put(0x4f); put(0x44); put(0x45);
      put(0);

/* $98 - Segment */

      put(0x98);
      put(7); put(0);
      put(0xa9);

/* Bizness' size */

      fsh();

      polter1 = ftell(popol);

      put(taillework2 & 0xff);
      put(taillework2 / 256);
      put(2); put(3); put(1);
      put(0);

/* $96 - LNames */

      put(0x96);
      put(12); put(0);
      put(5); put(0x5f); put(0x44); put(0x41);
      put(0x54); put(0x41); put(4); put(0x44); put(0x41);
      put(0x54); put(0x41);
      put(0);

/* $98 - Segment */

      put(0x98);
      put(7); put(0);
      put(0xa9); put(0); put(0); put(4); put(5); put(1);
      put(0);

/* $96 - Putain encore un LNames de daube */

      put(0x96);
      put(6); put(0);
      put(4); put(0x46); put(0x4c); put(0x41); put(0x54);
      put(0);

/* $9a - ? */

      put(0x9a);
      put(2); put(0);
      put(6);
      put(0);

/* $96 - LNames */

      put(0x96);
      put(8); put(0);
      put(6); put(0x44); put(0x47); put(0x52); put(0x4f); put(0x55);
      put(0x50);
      put(0);

/* $9a - ? */

      put(0x9a);
      put(4); put(0);
      put(7); put(0xff); put(2);
      put(0);

/* $88 - ? */

      put(0x88);
      put(4); put(0);
      put(0x40); put(0xa2); put(1);
      put(0);

/* $a0 - Enfin le segment de code */

      put(0xa0);
/* Len! */
      fsh();

      polter2 = ftell(popol);

      put(taillework & 0xff);
      put(taillework / 256);
      put(1);
      put(orgvalue & 0xff);
      put(orgvalue / 256);
   }
   battletech = pc;
   pcwoalign = savepcwoalign;
   exe = 1;
}

void ohnomoreshits(void)
{
   long pwmal;
   long taillework;
   long taillework2;
   long savepcwoalign = pcwoalign;

/* printf("Real len = [%ld] Expected len = [%ld]\n",
      pc - battletech,
      taille); */

   battletech = pc - battletech;
   taillework = battletech + 4;
   taillework2 = battletech;

   if (passe != PASS_LAST) {
      pcwoalign = savepcwoalign;
      return;
   }

   put(0);

   put(0x8a);
   put(2); put(0);
   put(0);
   put(0);
   fsh();

   pwmal = ftell(popol);

   fseek(popol, polter1, SEEK_SET);
   fputc(taillework2 & 0xff, popol);
   fputc(taillework2 / 256, popol);

   fseek(popol, polter2, SEEK_SET);
   fputc(taillework & 0xff, popol);
   fputc(taillework / 256, popol);

   fseek(popol, pwmal, SEEK_SET);

   pcwoalign = savepcwoalign;
}

void heading(void)
{
   if (isobject != 0) {
      objheader();
   } else {
      header();
   }
}
