/*[

mov.c

LOCAL CHAR SccsID[]="@(#)mov.c	1.12 02/13/95";

MOV CPU Functions.
------------------

]*/


#include <stdio.h>

#include <insignia.h>

#include <host_def.h>
#include <xt.h>
#include <c_main.h>
#include <c_addr.h>
#include <c_bsic.h>
#include <c_prot.h>
#include <c_seg.h>
#include <c_stack.h>
#include <c_xcptn.h>
#include <c_reg.h>
#include <mov.h>
#include <c_tlb.h>
#include <c_debug.h>
#include <fault.h>
#include  <config.h>	/* For C_SWITCHNPX */


/*
   =====================================================================
   EXTERNAL ROUTINES START HERE
   =====================================================================
 */


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Generic - one size fits all 'lods'.                                */
/* Generic - one size fits all 'mov'.                                 */
/* Generic - one size fits all 'movzx'.                               */
/* Generic - one size fits all 'movs'.                                */
/* Generic - one size fits all 'stos'.                                */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
MOV
       	    	               
IFN2(
	IU32 *, pop1,	/* pntr to dst operand */
	IU32, op2	/* src operand */
    )


   {
   *pop1 = op2;
   }

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* 'mov' to segment register.                                         */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
MOV_SR
       	    	               
IFN2(
	IU32, op1,	/* index to segment register */
	IU32, op2	/* src operand */
    )


   {
   switch ( op1 )
      {
   case DS_REG:
   case ES_REG:
   case FS_REG:
   case GS_REG:
      load_data_seg((ISM32)op1, (IU16)op2);
      break;

   case SS_REG:
      load_stack_seg((IU16)op2);
      break;

   default:
      break;
      }
   }


#ifdef SPC486
#define CR0_VALID_BITS 0xe005003f
#define CR3_VALID_BITS 0xfffff018
#else
#define CR0_VALID_BITS 0x8000001f
#define CR3_VALID_BITS 0xfffff000
#endif /* SPC486 */


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* 'mov' to control register.                                         */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
MOV_CR
       	    	               
IFN2(
	IU32, op1,	/* index to control register */
	IU32, op2	/* src operand */
    )


   {
   IU32 keep_et;

   /*
      Maintain all Reserved bits as 0.
    */
   switch ( op1 )
      {
   case CR_STAT:   /* system control flags */
      /* If trying to set PG=1 and PE=0, then fault. */
      if ( (op2 & BIT31_MASK) && !(op2 & BIT0_MASK) )
	 GP((IU16)0, FAULT_MOV_CR_PAGE_IN_RM);

      /* Note ET bit is set at RESET time and remains unchanged */
      keep_et = GET_ET();
      SET_CR(CR_STAT, op2 & CR0_VALID_BITS);
      SET_ET(keep_et);
      break;

   case 1:   /* reserved */
      break;

   case CR_PFLA:   /* page fault linear address */
      SET_CR(CR_PFLA, op2);
      break;

   case CR_PDBR:   /* page directory base register (PDBR) */
      SET_CR(CR_PDBR, (op2 & CR3_VALID_BITS));
      flush_tlb();
      break;

   default:
      break;
      }
   }

#define DR7_VALID_BITS 0xffff03ff
#define DR6_VALID_BITS 0x0000e00f

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* 'mov' to debug register.                                           */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
MOV_DR
       	    	               
IFN2(
	IU32, op1,	/* index to debug register, (0 - 7) */
	IU32, op2	/* src operand */
    )


   {
   switch ( op1 )
      {
   case 0:   /* Breakpoint Linear Address */
   case 1:
   case 2:
   case 3:
      SET_DR(op1, op2);
      setup_breakpoints();
      break;

   case 4:   /* Reserved */
   case 5:
      break;

   case 6:   /* Debug Status Register */
      SET_DR(DR_DSR, (op2 & DR6_VALID_BITS));
      break;

   case 7:   /* Debug Control Register */
      SET_DR(DR_DCR, (op2 & DR7_VALID_BITS));
      setup_breakpoints();
      break;

   default:
      break;
      }
   }

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* 'mov' to test register.                                            */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GLOBAL VOID
MOV_TR
       	    	               
IFN2(
	IU32, op1,	/* index to test register */
	IU32, op2	/* src operand */
    )


   {
   switch ( op1 )
      {
   case 0:   /* Reserved */
   case 1:
   case 2:
      break;

   case TR_CDR:   /* Cache test Data Register */
      printf("Write to Cache Test Data Register.\n");
      break;

   case TR_CSR:   /* Cache test Status Register */
      printf("Write to Cache Test Status Register.\n");
      break;

   case TR_CCR:   /* Cache test Control Register */
      printf("Write to Cache Test Control Register.\n");
      break;

   case TR_TCR:   /* Test Command Register */
      SET_TR(TR_TCR, op2);
      test_tlb();
      break;

   case TR_TDR:   /* Test Data Register */
      SET_TR(TR_TDR, op2);
      break;

   default:
      break;
      }
   }