
// type masks

int TYPEOF(int x) {return x & 0x60000000;}
int TYPEPLUSPROC(int x) {return x & 0x70000000;}
int CELLADDRMASK(int x) {return x & 0x0fffffff;}
int SYMPROCMASK(int x) {return x & 0x00ff0000;}
int VECTORSUBTYPEOF(int x) {return x & 0xff000000;}
int VECTORSIZEMASK(int x) {return x & 0x00ffffff;}
int SYMBOLSIZEMASK(int x) {return x & 0x0000ffff;}
int CHARMASK(int x) {return x & 0x000000ff;}

// primitive functions

int Mnull(int x) {return x == NULLTYPE;}
int Mnotnull(int x) {return x != NULLTYPE;}
int Meq(int x, int y) {return x == y;}
int Mcar(int x) {return cells[CELLADDRMASK(x)];}
int Mcdr(int x) {return cells[CELLADDRMASK(x) + 1];}

void Msetcar(int x, int y) { // TODO rename to setcat and setcdr
  cells[CELLADDRMASK(x)] = y;
  return;
}

void Msetcdr(int x, int y) {
  cells[CELLADDRMASK(x) + 1] = y;
  return;
}

int Mlistp(int x) {return Mnotnull(x) && (TYPEOF(x) == LISTTYPE);}
int Mprocp(int x) {return (x & PROCTYPE) == PROCTYPE;}
int Mpairp(int x) {return Mlistp(x) && (! Mprocp(x));}
int Mvectorp(int x) {return TYPEOF(x) == VECTORTYPE;}
int Mcharp(int x) {return TYPEOF(x) == CHARTYPE;}
int Mboolp(int x) {return TYPEOF(x) == BOOLTYPE;}
int MlistProcp(int x) {return Mlistp(x) || Mprocp(x);}

void Mvecset(int x, int y, int z) {
  cells[CELLADDRMASK(x) + y] = z; return;}
int Mvecref(int x, int y) {return cells[CELLADDRMASK(x) + y];}
int Mveclength(int x) {return VECTORSIZEMASK(Mvecref(x, 0));}
int MvecSymlength(int x) {return SYMBOLSIZEMASK(Mvecref(x, 0));}

int MstrSizeRef(int x) {return Mvecref(x, 1);}
void MstrSizeSet(int x, int y) {Mvecset(x, 1, y); return;}
void Mstrset(int x, int y, int z) {
  int temp;
  temp = Mvecref(x, 2 + (y >> 2));
  temp =
    (temp & ~(FF << ((y & 3) << 3)))
      | (z << ((y & 3) << 3));
  Mvecset(x, 2 + (y >> 2), temp); return;}
int Mstrref(int x, int y) {
  return CHARMASK(Mvecref(x, 2 + (y >> 2)) >> ((y & 3) << 3));}

// let the first data word (4 bytes) serve as a string hash
int MstrHashRef(int x) {return Mvecref(x, 2);}
// let the second data word (4 bytes) serve as a string hash
int MstrHash2Ref(int x) {return Mvecref(x, 3);}
int MsymProcRef(int x) {
  return SYMPROCMASK(cells[CELLADDRMASK(x)]) >> 16;}
void MsymProcSet(int x, int y) {
  cells[CELLADDRMASK(x)] = cells[CELLADDRMASK(x)] | (y << 16); return;}

int MgetVecSubtype(int x) {return VECTORSUBTYPEOF(Mvecref(x, 0));}
int MvecSubtypep(int x, int y) {return MgetVecSubtype(x) == y;}
int Mintvecref(int x) {return Mvecref(x, 1);}
void Mvecvecset(int x, int y, int z) {Mvecset(x, y + 1, z); return;}
int Mvecvecref(int x, int y) {return Mvecref(x, y + 1);}
int MvectorpProper(int x) {
  return Mvectorp(x) && MvecSubtypep(x, VECTORSUBTYPE);}
int Mintegerp(int x) {
  return Mvectorp(x) && MvecSubtypep(x, INTEGERSUBTYPE);}
int Mrealp(int x) {
  return Mvectorp(x) && MvecSubtypep(x, REALSUBTYPE);}
int Mnumberp(int x) {
  return Mvectorp(x) && (MvecSubtypep(x, INTEGERSUBTYPE) ||
                         MvecSubtypep(x, REALSUBTYPE));}
int Msymbolp(int x) {
  return Mvectorp(x) && MvecSubtypep(x, SYMBOLSUBTYPE);}
int Mstringp(int x) {
  return Mvectorp(x) && MvecSubtypep(x, STRINGSUBTYPE);}

int MgetChar(int x) {return CELLADDRMASK(x);}
int MmakeChar(int x) {return CELLADDRMASK(x) | CHARTYPE;}
int MmakeProc(int x) {return x | PROCTYPE;}

// machine operations

int Mopcode() {return Mcar(instruction);}
int Moperands() {return Mcdr(instruction);}
int Marg1() {return Mcar(operands);}
int Marg2() {return Mcar(Mcdr(operands));}
int Marg3() {return Mcar(Mcdr(Mcdr(operands)));}
void MNextInstruction() {instructions = Mcdr(instructions); return;}

int MStackArg1Ref() {return Mcar(stack);}
int MStackArg2Ref() {return Mcar(Mcdr(stack));}
int MStackArg3Ref() {return Mcar(Mcdr(Mcdr(stack)));}
int MStackArg4Ref() {return Mcar(Mcdr(Mcdr(Mcdr(stack))));}
void MGetStackArg1() {stack_arg1 = MStackArg1Ref(); return;}
void MGetStackArg2() {stack_arg2 = MStackArg2Ref(); return;}
void MGetStackArg3() {stack_arg3 = MStackArg3Ref(); return;}
void MGetStackArg4() {stack_arg4 = MStackArg4Ref(); return;}
void MSetStackArg1(int x) {Msetcar(stack, x); return;}
void Mpush(int x) {stack = kons(x, stack); return;} // TODO eliminate
void MPop() {stack = Mcdr(stack); return;}
void MpushOld(int x) {Mpush(x); return;}
int MakeClosure(int x, int y) {return kons(x, y);}
int ClosureCode(int x) {return Mcar(x);}
void MrestoreEnv() {env = Mcdr(closure); return;}

// garbage collection routines

void MmarkCell(int x) {Msetcar(x, Mcar(x) | MARK_BIT); return;}
int MIsMarkedCell(int x) {return (Mcar(x) & MARK_BIT) == MARK_BIT;}
int MmarkedCellValue(int x) {return Mcar(x) & NOT_MARK_BIT;}

