[comp.sys.handhelds] Saturn assembly language debugger

apm279l@vaxc.cc.monash.edu.au (11/28/90)

The following is my "sim1" package. It is for debugging your saturn code
before entry to your 28/48. I use the SASS assembler, so I've only run
SASS-format code through it. It is possible there are a few bugs lurking
around, so don't automatically assume a problem results from something in your
code. Carry is set/cleared according to my understanding of what happens
on the calculator (and correspondence with Alonzo). HOWEVER: it is possible
some other instructions alter the carry, or that my understanding is wrong.
At one stage, it was thought that gosubs alterred carry, I have been told
that this is not the case, and gosubs in this code don't alter carry.

I'm sorry I don't have time to make this code cope with more general cases,
but I don't yet. It will work for almost all your code though, and I've
found it quite easy to patch it's output C source to allow for some other
cases anyway. For example, you can make up a C routine to simulate the
effect of a jump to a part of your code which accesses RAM, if you know
what a typical call might do.

For more info, see the comments at the start of sim1.c

Installation:

There are 3 files in this package: SIM1.C, SIM1.H, LABELS.H
I've not tar'd them as they are not too long, and this makes it easier to
unpack on any machine.
All you need to do is compile sim1.c, and run it. You are prompted for
the input file (similar to the source you might feed into SASS), and
an output file. You are then asked if you wish to step through your
programme. If you answer in the affirmative, the output c source will
include calls to a debugging module, and running it will be like running
your code through a debugger.

Cheers, and enjoy,

Peter      apm279l@vaxc.cc.monash.edu.au



                                       _      __
                                 ,/^._/ ^\   {  \-.
                           ,-/~^/         `-/~     \.
                          (    THE 48 ??!!           }
              ___       /  {     A MERE ABACUS     ,/
          ,//| \ \    /     ~ ~^\  MENTION IT NOT! |
        ,// =|H  \*\             \,-+/^\           }
      ,// = =|  P  \ \                  `-.     _,/
    ,// = = =|\      \ \                   ~v/'~
  ,// = = = =|  \  2   \ \
 // = = = = =|    \  8   \ \
||= = = = = =|\     \  S | |
||= = = = = =|= \     \  | |
||= = = = = =|= = \     \| |
||= = = = = =|= = = \    | /
||= = = = = =|= = = = \  ||
||= = = = = =|= = = = = \||
||= = = = = =|= = = = = =||
||= = = = = =|= = = = = =||
||= = = = =,/ \ = = = = =||
||= = = =,/     \ = = = =||
||= = =,/         \ = = =||
||= =,/             \ = =||
||=,/                 \ =||
\|/                     \||





------------------------ %% BEGINNING OF SIM1.C %% ----------------------------


/*  SIM1.C: A SATURN TO C CONVERTER... copyright (1990) by Peter Hawkins

This programme is hereby placed in the public domain. Not to be sold in
whole or part for financial gain. No liability will be accepted by the
author. Do not remove this copyright notice.

Parts of it are not-too-well written, and it produces messy code, but
I don't really care!

Peter Hawkins: apm279l@vaxc.cc.monash.edu.au

Suggestions/comments/additions welcome.
Flames to: bush@whitehouse.gov


This version:
                 Long is assumed to be four-byte, so all registers are 2-longs.
                 a,b,c,d,d1,d0,st and p are all 64 bit, but only the relevant
                 nybbles are used.
                 The return-to-RPL address, stack pointer, d and b are
                 used, but are initially set to arbitrary values. A jump to
                 RPL is detected. Other jumps to memory are processed by the
                 routine in labels.h (this allows you to add a table of
                 "known" addresses of ROM subroutines.)
                 The routine will warn you if you jump to RPL without restoring
                 D,B D1 or D0. If you write to memory, this *is not* done,
                 instead, a message is displayed to say what was written and
                 where. Similarly, You are prompted for memory contents when
                 you read from memory *unless* the routine in labels.h detects
                 a read from a "known" location (eg stack).

                 The commands sethex and setdec are not implemented yet - all
                 operations are in HEX at this stage. If someone extends this
                 send me a copy. I'd also like copies of any other extensions
                 including additions to the labels.h file. I don't have time to
                 do this stuff myself.

                 The hardware status registors are not implemented, nor is IN
                 or OUT; opcodes which use them are ignored.

                 The opcodes used are Alonzo's improved set, with one
                 additional command: "show_re[gisters]" which causes the
                 contents of all registers to be printed whenever the programme
                 reaches that point.

                 If you select the "printout" mode at the prompt, the source
                 code will behave like a (crudish) debugger. You can step
                 through the "pseudo opcodes" one at a time, or several at a
                 time, alter register contents, and the registors are displayed
                 after each step.

                 You've got some self-modifying code? bad luck; won't work
                 sorry - this is a crude debugger - I don't think it's worth
                 allowing for every eventuality at this stage.

                 You may want to add to labels.h. Also, the screen functions
                 are set up for a VT100, if you use another sort of terminal,
                 just change the escape sequences (first routines in sim1.h)

*/

#include <stdio.h>
#include <string.h>

FILE            *infd, *outfd;
int             inptr = 0,min,max,i,digit,bufptr,dotpos,ret_count=0,print_mode=0;
char            ch,field[4],r1[19],r2[4],buffer[50],label[20];

getbuff()
{
  char ch1;

  bufptr = 0;
  buffer[bufptr] = 0; /* in case blank line or comment only */
  dotpos = 0;
  while ( (!feof(infd)) && ((ch1=fgetc(infd)) != 10))
  {
    if (ch1 == 59)
    {
      while (fgetc(infd) != 10);
      if (bufptr) break;
    }
    else
    {
      if ((ch1 > 31) || (ch1 == 9)) buffer[bufptr++] = ch1;
      if (ch1 == '.') dotpos = bufptr;
      if( ch1 == ':' )
      {
        fprintf(outfd,"\n");
        buffer[bufptr] = 0;
        fprintf(outfd,"%s\n",buffer);
        if (print_mode) fprintf(outfd,"printf(%c%s\\n%c);\n",34,buffer,34);
        bufptr = 0;
        dotpos = 0;
      }
    }
  }
  while ((bufptr > 0)&&(buffer[bufptr-1] < 33)) bufptr--; /*strip trailing junk */
  buffer[bufptr] = 0; /* terminate string */
  bufptr = 0;
}

char gtchar() /* finds & returns to next non-junk char, or end of string */
{
  char ch1;
  ch1 = 1;
  while ( (ch1 != 0) && ((ch1=buffer[bufptr++]) < 33 ));
  return ch1;
}

int get_token()
{
#define num_3_tokens 18
    static char token_table3[num_3_tokens][3] =
              { "pop","clr","inc","dec","add","sub","and","rln","rrn",
                "srn","srb","sln","neg","not","nop","brz","ret","or." };

#define num_4_tokens 19
    static char token_table4[num_4_tokens][4] =
              { "move","swap","push","clrb","setb","call","jump","breq",
                "brne","brgt","brlt","brge","brle","brbc","brbs","brcc",
                "brcs","brnz","retz"};

#define num_5_tokens 11
    static char token_table5[num_5_tokens][5] =
              { "reteq","retne","retgt","retlt","retge","retle","retbc",
                "retbs","retcc","retcs","retnz"};

#define num_7_tokens 3
    static char token_table7[num_7_tokens][7] =
              { "retsetc","retclrc","show_re"};

    int pos1,token,i;

    pos1 = bufptr;

    if (dotpos)
    {
      bufptr = dotpos;
      for (i = 0; i < 4; ++i) field[i] = 0;
      field[0]=buffer[bufptr++];
      if ((buffer[bufptr] > 31) && (field[0] < 58) && (buffer[bufptr] < 58)) field[1] = buffer[bufptr++];
      else if (((field[0] == 'w') && (buffer[bufptr] == 'p')) ||
               ((field[0] == 'x') && (buffer[bufptr] == 's')))
           field[1] = buffer[bufptr++];
      else if (field[0] == 'p')
      {
        i = 1;
        while (buffer[bufptr] > 31) field[i++] = buffer[bufptr++];
      }
    }
    else strcpy(field,"def");

    token = -1;
    for (i = 0; i < num_7_tokens; ++i)
      { if (!strncmp(&buffer[pos1],&token_table7[i][0],7)) token =i+num_5_tokens+num_4_tokens+num_3_tokens; }
    if (token >= 0)
    {
      if (!dotpos) bufptr += 7;
      return (token);
    }
    
    for (i = 0; i < num_5_tokens; ++i)
      { if (!strncmp(&buffer[pos1],&token_table5[i][0],5)) token =i+num_4_tokens+num_3_tokens; }
    if (token >= 0)
    {
      if (!dotpos) bufptr += 5;
      return (token);
    }
    
    for (i = 0; i < num_4_tokens; ++i)
      { if (!strncmp(&buffer[pos1],&token_table4[i][0],4)) token = i+num_3_tokens; }
    if (token >= 0)
    {
      if (!dotpos) bufptr += 4;
      return (token);
    }
    
    token = 99;
    for (i = 0; i < num_3_tokens; ++i)
      { if (!strncmp(&buffer[pos1],&token_table3[i][0],3)) token = i; }
    if (!dotpos) bufptr += 3;
    return (token);
}


main()
{                        
    char            filenm[20],pr_ans;
    int             tokn;

    printf("Input file name> ");
    scanf("%s",filenm);

    if(!(infd = fopen(filenm,"r")))
    {
        printf("error opening %s as input\n",filenm);
        exit(0);
    }
    printf("Output file name> ");
    scanf("%s",filenm);
    outfd = fdopen(creat(filenm,0),"w");
    printf("Do you want %s to step through? n/y:",filenm);
    scanf("%s",&pr_ans);
    if (pr_ans == 'y' || pr_ans == 'Y') print_mode=1;

    fprintf(outfd,"#include %csim1.h%c\n\nmain()\n{\n\n#include%clabels.h%c\nset_pmasks();\n\ncls();\n\n",34,34,34,34);

    while (!feof(infd))
    {
      getbuff();
      if (gtchar())
      {
        bufptr--;
        if (print_mode) fprintf(outfd,"getstep(%c%s%c);\n",34,buffer,34);
        switch (tokn = get_token())
        {
        case 0: {fprintf(outfd,"pop();"); break;}
        case 1: {getr1(); fprintf(outfd,"clr(mask_%s,%s);",field,r1); break;}
        case 2: {getr1(); fprintf(outfd,"inc(mask_%s,%s);",field,r1); break;}
        case 3: {getr1(); fprintf(outfd,"dec(mask_%s,%s);",field,r1); break;}
        case 4: {getr1r2(); fprintf(outfd,"add(mask_%s,%s,%s);",field,r1,r2); break;}
        case 5: {getr1r2(); fprintf(outfd,"sub(mask_%s,%s,%s);",field,r1,r2); break;}
        case 6: {getr1r2(); fprintf(outfd,"and(mask_%s,%s,%s);",field,r1,r2); break;}
        case 7: {getr1(); fprintf(outfd,"rln(mask_%s,%s);",field,r1); break;}
        case 8: {getr1(); fprintf(outfd,"rrn(mask_%s,%s);",field,r1); break;}
        case 9: {getr1(); fprintf(outfd,"srn(mask_%s,%s);",field,r1); break;}
        case 10: {getr1(); fprintf(outfd,"srb(mask_%s,%s);",field,r1); break;}
        case 11: {getr1(); fprintf(outfd,"sln(mask_%s,%s);",field,r1); break;}
        case 12: {getr1(); fprintf(outfd,"neg(mask_%s,%s);",field,r1); break;}
        case 13: {getr1(); fprintf(outfd,"not(mask_%s,%s);",field,r1); break;}
        case 14: break;
        case 15: {getr1(); getlbl(); fprintf(outfd,"if (!(%s[0] & mask_%s[0]) || (!(%s[1] & mask_%s[1]))) {carry=1; goto %s;} else carry=0;\n",r1,field,r1,field,label); break;}
        case 16: {fprintf(outfd,"goto goreturn;"); break;}
        case 17: {getr1r2(); fprintf(outfd,"or(mask_%s,%s,%s);",field,r1,r2); break;}
        case 18:
          {
            getr1r2();
            if (!strcmp(r2,"pc")) fprintf(outfd,"return_flag=0;tmp[1]=%s[1]&mask_a[1]; goto jump_mem;",r1);
            else
            {
              if (r1[0] == '@') fprintf(outfd,"input(%c%s%c,mask_%s,%s,%s);",34,field,34,field,&r1[1],r2);
              else if (r2[0] == '@') fprintf(outfd,"output(%c%s%c,mask_%s,%s,%s);",34,field,34,field,r1,&r2[1]);
              else fprintf(outfd,"move(mask_%s,%s,%s);",field,r1,r2);
            }
            break;
          }
        case 19:
          {
            getr1r2();
            if (r1[0] == '@')
            {
              fprintf(outfd,"input(%c%s%c,mask_%s,%s,tmp); ",34,field,34,field,&r1[1]);
              strcpy(r1,"tmp");
            }
            if (r2[0] == '@')
            {
              fprintf(outfd,"input(%c%s%c,mask_%s,tmp,%s); ",34,field,34,field,&r2[1]);
              strcpy(r2,"tmp");
            }
            fprintf(outfd,"swap(mask_%s,%s,%s);",field,r1,r2);
            break;
          }
        case 20: {fprintf(outfd,"push();"); break;}
        case 21: {getr1r2(); fprintf(outfd,"%s[1]=%s[1]&(~(1L<<(%s[1]&mask_1[1])));",r2,r2,r1); break;}
        case 22: {getr1r2(); fprintf(outfd,"%s[1]=%s[1]|(1L<<(%s[1]&mask_1[1]));",r2,r2,r1); break;}
        case 23: {getlbl(); fprintf(outfd,"stack[stkptr--] = 0X%05X; goto %s; ret_%05X:",ret_count,label,ret_count); ret_count++; break;}
        case 24: {getlbl(); fprintf(outfd,"goto %s;",label); break;}
        case 25: {getr1r2(); getlbl(); branch("==",label); break;}
        case 26: {getr1r2(); getlbl(); branch("!=",label); break;}
        case 27: {getr1r2(); getlbl(); branch("> ",label); break;}
        case 28: {getr1r2(); getlbl(); branch("< ",label); break;}
        case 29: {getr1r2(); getlbl(); branch(">=",label); break;}
        case 30: {getr1r2(); getlbl(); branch("<=",label); break;}
        case 31: {getr1r2(); getlbl(); fprintf(outfd,"if ((~%s[1])&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto %s;} else carry=0;",r2,r1,label); break;}
        case 32: {getr1r2(); getlbl(); fprintf(outfd,"if(%s[1]&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto %s;} else carry=0;",r2,r1,label); break;}
        case 33: {getlbl(); fprintf(outfd,"if (!carry) goto %s;",label); break;}
        case 34: {getlbl(); fprintf(outfd,"if (carry) goto %s;",label); break;}
        case 35: {getr1(); getlbl(); fprintf(outfd,"if ((%s[0]&mask_%s[0])||(%s[1]&mask_%s[1])) {carry=1; goto %s;} else carry=0;",r1,field,r1,field,label); break;}
        case 36: {getr1(); fprintf(outfd,"if (!(%s[0] & mask_%s[0]) || !(%s[1] & mask_%s[1]))) {carry=1; goto %s;} else carry=0;",r1,field,r1,field); break;}
        case 37: {getr1r2(); branch("==","goreturn"); break;}
        case 38: {getr1r2(); branch("!=","goreturn"); break;}
        case 39: {getr1r2(); branch("> ","goreturn"); break;}
        case 40: {getr1r2(); branch("< ","goreturn"); break;}
        case 41: {getr1r2(); branch(">=","goreturn"); break;}
        case 42: {getr1r2(); branch("<=","goreturn"); break;}
        case 43: {getr1r2(); fprintf(outfd,"if ((~%s[1])&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto goreturn;} else carry=0;",r2,r1); break;}
        case 44: {getr1r2(); fprintf(outfd,"if (%s[1]&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto goreturn;} else carry=0;",r2,r1); break;}
        case 45: {fprintf(outfd,"if (!carry) goto goreturn;"); break;}
        case 46: {fprintf(outfd,"if (carry) goto goreturn;"); break;}
        case 47: {getr1(); fprintf(outfd,"if ((%s[0] & mask_%s[0])||(%s[1] & mask_%s[1])) {carry=1; goto goreturn;} else carry=0;",r1,field,r1,field); break;}
        case 48: {fprintf(outfd,"carry=1; goto goreturn;"); break;}
        case 49: {fprintf(outfd,"carry=0; goto goreturn;"); break;}
        case 50: {fprintf(outfd,"printf(%c\\n%c); show_regs();",34,34); break;}
        default: fprintf(outfd,"printf(%cUnknown operation: %s\\n%c);",34,buffer,34);
        }
      if (!print_mode) fprintf(outfd,"%c/* %s */\n",9,buffer);
      }
    }

    if (ret_count)
    {
      fprintf(outfd,"\n\ngoreturn: switch(stack[++stkptr] & mask_a[1])\n  {\n");
      for (i = 0;i < ret_count; ++i) fprintf(outfd,"    case 0X%05X: goto ret_%05X;\n",i,i);
      fprintf(outfd,"    case 0xfffff: {printf(%cERROR: you've pushed/popped return stack\\n%c); exit(0);}\n",34,34);
      fprintf(outfd,"  }\n\n");
    }
  
    fprintf(outfd,"}\n");
    fflush(outfd);
    fclose(outfd);
    fclose(infd);
}

getr1()
{
 int j;
 char ch1;

 for (j = 0; j < 4; j++) r1[j] = 0;
 ch1=gtchar();
 for (j = 0; ((ch1 != ',') && (j < 3)); j++) {r1[j] = ch1; ch1=gtchar();}
}

getr1r2()
{
  int j,k;
  char ch1;

  for (j = 0; j < 19; j++) r1[j] = 0;
  for (j = 0; j < 4 ; j++) r2[j] = 0;
  ch1=gtchar();
  for (j = 0; ch1 != ','; j++) {r1[j] = ch1; ch1=gtchar();}

  if (r1[0] < 58) /* constant (not register) */
  {
    if ( (r1[0] == '$') || (r1[0] == '#') ) fprintf(outfd,"constmp(mask_%s,0x%sL); ",field,&r1[1]);
    else fprintf(outfd,"constmp(mask_%s,%sL); ",field,r1);
    strcpy(r1,"tmp");
    r1[3] = 0;
  }

  ch1=gtchar();
  for (j = 0; ((ch1 > 0) && (ch1 != ',') && (j < 3)); j++) {r2[j] = ch1; ch1=gtchar();}
}

getlbl()
{
  int lblptr;
  char ch1;
  if ((ch1 = gtchar()) == 64)
  {
    strcpy(label,"_at_");
    lblptr = 4;
  }
  else
  {
    lblptr = 0;
    bufptr--;
  }
  strcpy(&label[lblptr],&buffer[bufptr]);
}


branch( char *condit, char *lbl)
{
  if (!strcmp(condit,"=="))
  {
    fprintf(outfd,"if (((%s[0]&mask_%s[0])%s(%s[0]&mask_%s[0]))&&",r1,field,condit,r2,field);
    fprintf(outfd,"((%s[1]&mask_%s[1])%s(%s[1]&mask_%s[1]))) ",r1,field,condit,r2,field);
  }
  else if (!strcmp(condit,"!="))
  {
    fprintf(outfd,"if (((%s[0]&mask_%s[0])%s(%s[0]&mask_%s[0]))||",r1,field,condit,r2,field);
    fprintf(outfd,"((%s[1]&mask_%s[1])%s(%s[1]&mask_%s[1]))) ",r1,field,condit,r2,field);
  }
  else if ((!strcmp(condit,">="))||(!strcmp(condit,"<=")))
  { /* ruddy heck!! what a test!! any better ideas???? */
    fprintf(outfd,"if ((((mask_%s[0]) && ((%s[0]&mask_%s[0])%1s(%s[0]&mask_%s[0])))||",field,r1,field,condit,r2,field);
    fprintf(outfd,"((!mask_%s[0]) && ((%s[1]&mask_%s[1])%1s(%s[1]&mask_%s[1])))) ",field,r1,field,condit,r2,field);
    fprintf(outfd,"|| (((%s[0]&mask_%s[0])==(%s[0]&mask_%s[0]))&&",r1,field,r2,field);
    fprintf(outfd,"((%s[1]&mask_%s[1])==(%s[1]&mask_%s[1])))) ",r1,field,r2,field);
  }
  else
  {
    fprintf(outfd,"if (((mask_%s[0]) && ((%s[0]&mask_%s[0])%s(%s[0]&mask_%s[0])))||",field,r1,field,condit,r2,field);
    fprintf(outfd,"((!mask_%s[0]) && ((%s[1]&mask_%s[1])%s(%s[1]&mask_%s[1])))) ",field,r1,field,condit,r2,field);
  }
  fprintf(outfd,"{carry=1; goto %s;} else carry=0;",lbl);
}


-------------------------- %% END OF SIM1.C %% --------------------------------

------------------------ %% BEGINNING OF SIM1.H %% ----------------------------

#include <stdio>
#include <string.h>
#include <stdlib>

#define STRTYP 0x02a2c
#define REATYP 0x02933
#define IMCTYP 0x02c96
#define ALGTYP 0x02ab8
#define PRGTYP 0x02d9d
#define NAMTYP 0x02e48
#define LOCTYP 0x02e67
#define BINTYP 0x02a4e


#define d0_init  0x000e9e52 /* any number, hopefully not required */
#define d1_init  0x000e9e54 /* top of display_stack */
#define st_init  0x00000000
#define b_init   0x76768576
#define d_init   0x29004976

/*now define contents of "known" locations (ie @d0, @d1...) */
#define RPL      0x000e9e53      /* address of next RPL ins */
#define ST0      (d1_init+0x100) /* pointer to stack level 0 */
#define ST1      (ST0 + 0x100)
#define ST2      (ST1 + 0x100)
#define ST3      (ST2 + 0x100)
#define ST4      (ST3 + 0x100)

/* now a few aliases */
#define mask_pa mask_p10
#define mask_pb mask_p11
#define mask_pc mask_p12
#define mask_pd mask_p13
#define mask_pe mask_p14
#define mask_pf mask_p15

typedef unsigned long reg_t[2];

reg_t tmp;
reg_t a,b={0,b_init},c,d={0,d_init};
reg_t r0,r1,r2,r3,r4;
reg_t d0={0,d0_init},d1={0,d1_init},pc={0,0},st={0,st_init},p={0,0};
unsigned char  carry=0,stkptr=6,return_flag;
unsigned long  stack[7]={0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};

/* ------------------------------------------------------------------------- */
/*                      Screen functions for vt100                           */

cls() /* clear screen */
{
  printf("%c[2J",27);
}

ebl() /* erase bottom line */
{
  bos();
  printf("%c[2K",27);
}

tos() /* curser to top of screen */
{
  printf("%c[H",27);
}

bos() /* curser to bottom of screen */
{
  printf("%c[23;0H",27);
}

bold() /* bold text */
{
  printf("%c[1m",27);
}

norm() /* normal text */
{
  printf("%c[0m",27);
}

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


reg_t mask_1  = {0x00000000, 0x0000000f};
reg_t mask_2  = {0x00000000, 0x000000ff};
reg_t mask_3  = {0x00000000, 0x00000fff};
reg_t mask_4  = {0x00000000, 0x0000ffff};
reg_t mask_5  = {0x00000000, 0x000fffff};
reg_t mask_6  = {0x00000000, 0x00ffffff};
reg_t mask_7  = {0x00000000, 0x0fffffff};
reg_t mask_8  = {0x00000000, 0xffffffff};
reg_t mask_9  = {0x0000000f, 0xffffffff};
reg_t mask_10 = {0x000000ff, 0xffffffff};
reg_t mask_11 = {0x00000fff, 0xffffffff};
reg_t mask_12 = {0x0000ffff, 0xffffffff};
reg_t mask_13 = {0x000fffff, 0xffffffff};
reg_t mask_14 = {0x00ffffff, 0xffffffff};
reg_t mask_15 = {0x0fffffff, 0xffffffff};
reg_t mask_16 = {0xffffffff, 0xffffffff};
reg_t mask_w  = {0xffffffff, 0xffffffff};
reg_t mask_a  = {0x00000000, 0x000fffff};
reg_t mask_x  = {0x00000000, 0x00000fff};
reg_t mask_s  = {0xf0000000, 0x00000000};
reg_t mask_m  = {0x0fffffff, 0xfffff000};
reg_t mask_b  = {0x00000000, 0x000000ff};
reg_t mask_xs = {0x00000000, 0x00000f00};
reg_t mask_def= {0x00000000, 0x000fffff}; /* default - non .a defaults should be OK */
reg_t mask_p,mask_wp,mask_p1,mask_p2,mask_p3,mask_p4,mask_p5,mask_p6;
reg_t mask_p7,mask_p8,mask_p9,mask_p10,mask_p11,mask_p12,mask_p13;
reg_t mask_p14,mask_p15,mask_p16;

set_pmasks()
{
  short int i;
  p[1] &= mask_1[1];
  p[0] = 0;
  if (p[1] < 8)
  {
    mask_p[0]  = 0x00000000;
    mask_p[1] = 0x0000000f;
    mask_wp[0] = 0x00000000;
    mask_wp[1] = 0x0000000f;
    for (i = 0; i < p[1]; ++i)
    {
      mask_p[1] == (mask_p[1] << (4*i));
      mask_wp[1] |= mask_p[1];
    }
  }
  else
  {
    mask_p[0]  = 0x0000000f;
    mask_p[1]  = 0x00000000;
    mask_wp[0] = 0x0000000f;
    mask_wp[1] = 0x00000000;
    for (i = 0; i < p[1]-8; ++i)
    {
      mask_p[0] == (mask_p[0] << (4*i));
      mask_wp[0] |= mask_p[0];
    }
  }
  mask_n(mask_p1,1);
  mask_n(mask_p2,2);
  mask_n(mask_p3,3);
  mask_n(mask_p4,4);
  mask_n(mask_p5,5);
  mask_n(mask_p6,6);
  mask_n(mask_p7,7);
  mask_n(mask_p8,8);
  mask_n(mask_p9,9);
  mask_n(mask_p10,10);
  mask_n(mask_p11,11);
  mask_n(mask_p12,12);
  mask_n(mask_p13,13);
  mask_n(mask_p14,14);
  mask_n(mask_p15,15);
  mask_n(mask_p16,16);
}

mask_n(reg,n)
reg_t reg;
int n;
{
  reg_t tmp1;
  int i;

  reg[0] = 0;
  reg[1] = 0;
  if (p[1] < 8) 
  {
    for (i = p[1]; (i < 8)&&(i<(n+p[1])); ++i) reg[1] |= (0xf << (4*i));
    if (i < (n+p[1])) {for (i = 0; (i < 8)&&(i<(n+p[1]-8)); ++i) reg[0] |= (0xf<< (4*i));}
  }  
  else
  {
    for (i = p[1]; (i < 8)&&(i<(n+p[1])); ++i) reg[0] |= (0xf << (4*i));
  }
}


move(  mask, reg1, reg2)
reg_t  mask, reg1, reg2;
{
  short int i;
  if (&reg1[0]==&pc[0]) printf("Ignoring <move pc,register> instruction...\n");
  else
  {
    if ((&mask[0]==&mask_def[0]) && 
       (  (&reg1[0]==&r0[0])||(&reg2[0]==&r0[0])
        ||(&reg1[0]==&r1[0])||(&reg2[0]==&r1[0])
        ||(&reg1[0]==&r2[0])||(&reg2[0]==&r2[0])
        ||(&reg1[0]==&r3[0])||(&reg2[0]==&r3[0])
        ||(&reg1[0]==&r4[0])||(&reg2[0]==&r4[0]) )) {mask[0]=mask_w[0]; mask[1]=mask_w[1];}
      
    for (i = 0; i < 2; ++i) reg2[i] = (reg2[i] & (~mask[i])) | (reg1[i] & mask[i]);
    if (&reg2[0]==&p[0]) set_pmasks();
  }
}

swap(  mask, reg1, reg2)
reg_t  mask, reg1, reg2;
{
  short int i;
  reg_t tmp1;
  if ((&mask[0]==&mask_def[0]) && 
     (  (&reg1[0]==&r0[0])||(&reg2[0]==&r0[0])
      ||(&reg1[0]==&r1[0])||(&reg2[0]==&r1[0])
      ||(&reg1[0]==&r2[0])||(&reg2[0]==&r2[0])
      ||(&reg1[0]==&r3[0])||(&reg2[0]==&r3[0])
      ||(&reg1[0]==&r4[0])||(&reg2[0]==&r4[0]) )) {mask[0]=mask_w[0]; mask[1]=mask_w[1];}
  for (i = 0; i < 2; ++i)
  {
    tmp1[i] = (reg2[i] & (~mask[i])) | (reg1[i] & mask[i]);
    reg1[i] = (reg1[i] & (~mask[i])) | (reg2[i] & mask[i]);
    reg2[i] = tmp1[i];
  }
  if (&reg2[0]==&p[0]) set_pmasks();
}

push()
{
  stack[stkptr--] = c[0] & mask_a[0];
}

pop()
{
  c[0] = ((c[0] & (~mask_a[0])) | (stack[stkptr++] & mask_a[0]));
}

clr(   mask, reg1)
reg_t  mask, reg1;
{
  short int i;
  for (i = 0; i < 2; i++) reg1[i] &= (~mask[i]);
}

and(   mask, reg1, reg2)
reg_t  mask, reg1, reg2;
{
  short int i;
  for (i = 0; i < 2; i++) reg2[i] = ((reg2[i] & (~mask[i])) | (reg2[i] & mask[i] & reg1[i]));
}

or(    mask, reg1, reg2)
reg_t  mask, reg1, reg2;
{
  short int i;
  for (i = 0; i < 2; i++) reg2[i] = ((reg2[i] & (~mask[i])) | ((reg2[i] |reg1[i]) & mask[i]));
}

inc(   mask, reg1)
reg_t  mask, reg1;
{
  reg_t tmp1;
  tmp1[0] = 0;
  tmp1[1] = 1;
  while (tmp1[1] && (!(tmp1[1] & mask[1]))) (tmp1[1] << 4);
  if (!tmp1[1])
  {
    tmp1[0] = 1;
    while (tmp1[0] && (!(tmp1[0] & mask[0]))) (tmp1[0] << 4);
  }
  add(mask,tmp1,reg1);
}

dec(   mask, reg1)
reg_t  mask, reg1;
{
  reg_t tmp1;
  tmp1[0] = 0;
  tmp1[1] = 1;
  while (tmp1[1] && (!(tmp1[1] & mask[1]))) (tmp1[1] << 4);
  if (!tmp1[1])
  {
    tmp1[0] = 1;
    while (tmp1[0] && (!(tmp1[0] & mask[0]))) (tmp1[0] << 4);
  }
  sub(mask,tmp1,reg1);
}


add(   mask, reg1, reg2)
reg_t  mask, reg1, reg2;
{
  unsigned long t;
  reg2[1] += (reg1[1] & mask[1]);
  if ( (((reg2[1] >> 4) + (reg1[1] & mask[1])) >> 4) & 0xf0000000 )
  {
    t = reg2[0];
    reg2[0] += ( (reg1[0]+1) & mask[0] );
    carry = (t+((reg1[0]+1) & mask[0]) != reg2[0]);
  }
  else
  {
    t = reg2[0];
    reg2[0] += ( reg1[0] & mask[0] );
    carry = (t+(reg1[0] & mask[0]) != reg2[0]);
  }
  if (&reg2[0]==&p[0]) set_pmasks();
}


sub(   mask, reg1, reg2)
reg_t  mask, reg1, reg2;
{
  unsigned long t;
  reg2[1] -= (reg1[1] & mask[1]);
  if ((reg2[1] & mask[1]) < (reg1[1] & mask[1]))
  {
    t = reg2[0];
    reg2[0] -= ( (reg1[0]+1) & mask[0] );
    carry = (t-((reg1[0]+1) & mask[0]) != reg2[0]);
  }
  else
  {
    t = reg2[0];
    reg2[0] -= ( reg1[0] & mask[0] );
    carry = (t-(reg1[0] & mask[0]) != reg2[0]);
  }
  if (&reg2[0]==&p[0]) set_pmasks();
}

not(   mask, reg1)
reg_t  mask, reg1;
{
  carry = 0;
  reg1[0] = (reg1[0] & (~mask[0])) | ((~reg1[0]) & mask[0]);
  reg1[1] = (reg1[1] & (~mask[1])) | ((~reg1[1]) & mask[1]);
}

neg(   mask, reg1)
reg_t  mask, reg1;
{
  not(mask,reg1);
  dec(mask,reg1);
}

rrn(   mask, reg1)
reg_t  mask, reg1;
{
  long i,store;
  if (mask[1])
  {
    for (i=0xfL; (!(mask[1] & i)); i = i << 4);
    store = reg1[1] & i;
  }
  else
  {
    for (i=0xfL; (!(mask[0] & i)); i = i < 4);
    store = reg1[0] & i;
  }
  while (store > 0xfL) store = store >> 4;

  srn(mask,reg1);
  if (store)
  {
    if (mask[0])
    {
      for (i=0xf0000000L; (!(mask[0] & i)); i = i >> 4);
      while (!(store & i)) store = store << 4;
      reg1[0] |= store;
    }
    else
    {
      for (i=0xf0000000L; (!(mask[1] & i)); i = i >> 4);
      while (!(store & i)) store = store << 4;
      reg1[1] |= store;
    }
  }
}

rln(   mask, reg1)
reg_t  mask, reg1;
{
  long i,store;
  if (mask[0])
  {
    for (i=0xf0000000L; (!(mask[0] & i)); i = i >> 4);
    store = reg1[0] & i;
  }
  else
  {
    for (i=0xf0000000L; (!(mask[1] & i)); i = i >> 4);
    store = reg1[1] & i;
  }
  while (store > 0xfL) store = store >> 4;

  sln(mask,reg1);
  if (store)
  {
    if (mask[1])
    {
      for (i=0xfL; (!(mask[1] & i)); i = i << 4);
      while (!(store & i)) store = store << 4;
      reg1[1] |= store;
    }
    else
    {
      for (i=0xfL; (!(mask[0] & i)); i = i << 4);
      while (!(store & i)) store = store << 4;
      reg1[0] |= store;
    }
  }
}

srn(   mask, reg1)
reg_t  mask, reg1;
{
  reg_t tmp1;
  tmp1[1] = (((reg1[1] & mask[1]) >> 4L)|((reg1[0] & 0xfL) << 28L)) & mask[1];
  tmp1[0] =   (reg1[0] & mask[0]) >> 4L;
  reg1[0] = (reg1[0] & (~mask[0])) | (tmp1[0] & mask[0]);
  reg1[1] = (reg1[1] & (~mask[1])) | (tmp1[1] & mask[1]);
}

srb(   mask, reg1)
reg_t  mask, reg1;
{
  reg_t tmp1;
  tmp1[1] = (((reg1[1] & mask[1]) >> 1L)|((reg1[0] & 0x1L) << 31L)) & mask[1];
  tmp1[0] =   (reg1[0] & mask[0]) >> 1L;
  reg1[0] = (reg1[0] & (~mask[0])) | (tmp1[0] & mask[0]);
  reg1[1] = (reg1[1] & (~mask[1])) | (tmp1[1] & mask[1]);
}

sln(   mask, reg1)
reg_t  mask, reg1;
{
  reg_t tmp1;
  tmp1[1] =  ((reg1[1] & mask[1]) << 4L) & mask[1];
  tmp1[0] = (((reg1[0] & mask[0]) << 4L)|((reg1[1] & 0xf0000000L) >> 28L)) & mask[0];
  reg1[0] = (reg1[0] & (~mask[0])) | (tmp1[0] & mask[0]);
  reg1[1] = (reg1[1] & (~mask[1])) | (tmp1[1] & mask[1]);
}


constmp(mask, cons)
reg_t mask;
long cons;
{
  short int i;
  i = 0;
  while ((1 << i) && !((1 << i) & mask[1])) i += 4;
  if (!(1 << (i-8))) while ((1 << (i-8)) && !((1 << (i-8)) & mask[0])) i += 4;
  tmp[1] = (mask[1] & ( cons <<   i   ));
  tmp[0] = (mask[0] & ( cons >> (8-i) ));
}

show_regs()
{
  int i;
  char strng1[17],strng2[17];
  printf("-------------------------------------------------------------------------------\n");
  printf("| a=%08X%08X b=%08X%08X c=%08X%08X d=%08X%08X |\n",a[0],a[1],b[0],b[1],c[0],c[1],d[0],d[1]);
  printf("| d0 = %05X,     d1 = %05X,      status = %04X,      p = %1X,     carry %s |\n",d0[1]&mask_a[1],d1[1]&mask_a[1],st[1]&mask_4[1],p[1],(carry) ? "set  " :"clear");
  printf("-------------------------------------------------------------------------------\n");
}

input(fld, mask, reg1, reg2)
reg_t mask, reg1, reg2;
char fld[3];
{
  char instr[17],str1[9],str2[17];
  int i;

  if((mask[0]==mask_a[0]) && (mask[1]==mask_a[1])) /* getting an address? */
  {
    switch (reg1[1]&mask_a[1]) /* is it known? */
    {
      case d0_init:         {reg2[1]=(reg2[1] & (~mask[1]))      | (RPL & mask[1]); return; break; }
      case d1_init:         {reg2[1]=(reg2[1] & (~mask[1]))      | (ST0 & mask[1]); return; break; }
      case (5 +d1_init):    {reg2[1]=(reg2[1] & (~mask[1])) | (ST1 &mask[1]); return; break; }
      case (10+d1_init):    {reg2[1]=(reg2[1] & (~mask[1])) | (ST2 & mask[1]); return; break; }
      case (15+d1_init):    {reg2[1]=(reg2[1] & (~mask[1])) | (ST3 & mask[1]); return; break; }
      case (20+d1_init):    {reg2[1]=(reg2[1] & (~mask[1])) | (ST4 & mask[1]); return; break; }
      case ST0:             {intype(mask,reg2,1); return; break;}
      case ST1:             {intype(mask,reg2,1); return; break;}
      case ST2:             {intype(mask,reg2,2); return; break;}
      case ST3:             {intype(mask,reg2,3); return; break;}
      case ST4:             {intype(mask,reg2,4); return; break;}
      case (ST0+5):         {printf("Input from Stack[0]+5: "); break;}
      case (ST0+10):        {printf("Input from Stack[0]+10: "); break;}
      case (ST1+5):         {printf("Input from Stack[1]+5: "); break;}
      case (ST1+10):        {printf("Input from Stack[1]+10: "); break;}
      case (ST2+5):         {printf("Input from Stack[2]+5: "); break;}
      case (ST2+10):        {printf("Input from Stack[2]+10: "); break;}
      case (ST3+5):         {printf("Input from Stack[3]+5: "); break;}
      case (ST3+10):        {printf("Input from Stack[3]+10: "); break;}
      case (ST4+5):         {printf("Input from Stack[4]+5: "); break;}
      case (ST4+10):        {printf("Input from Stack[4]+10: "); break;}
    }
  }

  for (i = 0; i < 16; ++i) instr[i] = 48;
  instr[17] = 0;
  for (i = 0; i < 8 && !( (1<<(4*i)) & mask[1]); ++i);
  if (i == 8) for (i = 8;i < 16 & !( (1<<((4*i)-32)) & mask[0]); ++i);
  
  printf("Input [%3s] field (in hex) stored at %05X: ",fld,(reg1[1] & mask_a[1]) );
  scanf("%s",str2);
  printf("\n");
  strncpy(&instr[16-i-strlen(str2)],str2,strlen(str2));
  strncpy(str1,instr,8);
  str1[8]=0;
  reg2[0] = (reg2[0] & (~mask[0])) | (strtoul(str1,NULL,16) & mask[0]);
  reg2[1] = (reg2[1] & (~mask[1])) | (strtoul(&instr[8],NULL,16) & mask[1]);
}

output(fld, mask, reg1, reg2)
reg_t mask, reg1, reg2;
char fld[3];
{
  if (mask[0] && mask[1]) printf("[%s] field of @[%05X] <= %x%0x\n",fld,reg2[1]&mask_a[1],reg1[0]&mask[0],reg1[1]&mask[1]);
  else if (mask[0] && !mask[1]) printf("[%s] field of @[%05X] <= %x\n",fld,reg2[1]&mask_a[1],reg1[0]&mask[0]);
  else printf("[%s] field of @[%05X] is now %x\n",fld,reg2[1]&mask_a[1],reg1[1]&mask[1]);
}


intype(mask,reg2,lvl)
reg_t mask, reg2;
int lvl;
{
  int i;

  printf("Input type of object in level %d of display:\n\n	(0)	String\n	(1)	Real\n	(2)	Inline machine code\n	(3)	Algebraic obj\n	(4)	Programme\n	(5)	Global Name\n	(6)	Local Name\n	(7)	Binary Integer\n",lvl);

  scanf("%d",&i);
  switch (i)
  {
    case 0: {reg2[1]=(reg2[1] & (~mask[1])) | (STRTYP & mask[1]); break;}
    case 1: {reg2[1]=(reg2[1] & (~mask[1])) | (REATYP & mask[1]); break;}
    case 2: {reg2[1]=(reg2[1] & (~mask[1])) | (IMCTYP & mask[1]); break;}
    case 3: {reg2[1]=(reg2[1] & (~mask[1])) | (ALGTYP & mask[1]); break;}
    case 4: {reg2[1]=(reg2[1] & (~mask[1])) | (PRGTYP & mask[1]); break;}
    case 5: {reg2[1]=(reg2[1] & (~mask[1])) | (NAMTYP & mask[1]); break;}
    case 6: {reg2[1]=(reg2[1] & (~mask[1])) | (LOCTYP & mask[1]); break;}
    case 7: {reg2[1]=(reg2[1] & (~mask[1])) | (BINTYP & mask[1]); break;}
    default: printf("error, unknown type\n");
  }
  printf("\n");
}

getstep(char *cmd)
{
  char cnt[5];
  static int step_count=1;

  printf ("%s\n",cmd);
  if (!(--step_count))
  {
    tos();
    bold();
    show_regs();
    bos();
    printf("\n%c%c%c clr,set,qui,n-steps: ",9,9,9);
    norm();
    scanf("%s",cnt);
    while ((!strcmp(cnt,"clr"))||(!strcmp(cnt,"set")))
    {
      if(!strcmp(cnt,"clr"))
      {
        cls();
        bos();
        printf ("%s",cmd);
        printf ("\n");  /* for some reason, I need to do it this way on my term */
      }
      else
      {
        bold();
        printf("Enter name of register (a,b,c,d,d0,d1,st,p,car): ");
        norm();
        scanf("%s",cnt);
        ebl();
        if (!strcmp(cnt,"car"))
        {
          bold();
          printf("Set/Clear? (s/c)");
          norm();
          scanf("%c",cnt);
          if (cnt[0]==115) carry=1; else carry=0;
        }
        else if (!strcmp(cnt,"p"))
        {
          bold();
          printf("Enter HEX value (1 nybble): ");
          norm();
          scanf("%1x",&p[1]);
          set_pmasks();
        }
        else if (!strcmp(cnt,"st"))
        {
          bold();
          printf("Enter HEX value (4 nybbles): ");
          norm();
          scanf("%4x",&st[1]);
        }
        else if (!strcmp(cnt,"d0"))
        {
          bold();
          printf("Enter new value (in HEX) (5 nybbles): ");
          norm();
          scanf("%5x",&d0[1]);
        }
        else if (!strcmp(cnt,"d1"))
        {
          bold();
          printf("Enter new value (in HEX) (5 nybbles): ");
          norm();
          scanf("%5x",&d1[1]);
        }
        else if (!strcmp(cnt,"a"))
        {
          bold();
          printf("Enter new value (in HEX) (16 nyb incl leading 0s): ");
          norm();
          scanf("%16x",&a[0],&a[1]);
        }
        else if (!strcmp(cnt,"b"))
        {
          bold();
          printf("Enter new value (in HEX) (16 nyb incl leading 0s): ");
          norm();
          scanf("%16x",&b[0],&b[1]);
        }
        else if (!strcmp(cnt,"c"))
        {
          bold();
          printf("Enter new value (in HEX) (16 nyb incl leading 0s): ");
          norm();
          scanf("%16x",&c[0],&c[1]);
        }
        else if (!strcmp(cnt,"d"))
        {
          bold();
          printf("Enter new value (in HEX) (16 nybs incl leading 0s): ");
          norm();
          scanf("%16x",&d[0],&d[1]);
        }
        else printf("Illegal register name - ignored");
        printf("\n");
      }
      tos();
      bold();
      show_regs();
      bos();
      printf("\n%c%c%c clr,set,qui,n-steps: ",9,9,9);
      norm();
      scanf("%s",cnt);
    }
    if (!strcmp(cnt,"qui"))
    {
      cls();
      tos();
      exit(0);
    }
    ebl();
    step_count=strtol(cnt,NULL,10);
    if (!step_count) step_count = 1;
  }
}


-------------------------- %% END OF SIM1.H %% --------------------------------

---------------------- %% BEGINNING OF LABELS.H %% ----------------------------

cls();
bos();
goto start_prg;

jmp_at_a: tmp[1] = a[1];
    return_flag = 0;
    goto jump_mem;

jmp_at_c: tmp[1] = c[1];
    return_flag = 0;
    goto jump_mem;

jump_mem:

  switch (tmp[1]&mask_a[1])
  {
    case RPL:
      {
        printf("programme returned to RPL\n");
        if (p) printf("%%%WARNING%%% you have not set p to 0,%c\n",7);
        if (b[1] != b_init) printf("%%%WARNING%%% you have not restored b,%c\n",7);
        if (d0[1] != d0_init + 5) printf("%%%WARNING%%% you have not restored d0,%c\n",7);
        if (d1[1] != d1_init + (d[1]-d_init)*5) printf("%%%WARNING%%% d1 and d are no longer consistent,%c\n",7);
        break;
      }
    default:         printf("programme jumped to memory location %5x\n",tmp[1] & mask_a[1]);
  }
  if (!return_flag) exit(0);
  else printf("%%%WARNING%%% programme continuing without executing routine at%5x%c\n",tmp[1] & mask_a[1],7);

start_prg:

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


------------------------- %% END OF PACKAGE %% ------------------------------