void
dae_process(struct trapframe *eframe, u_int x,
            u_int dmax, u_int dmdx, u_int dmtx)
{
    u_int v, reg;

    if (!ISSET(dmtx, DMT_VALID))
        return;

    DAE_DEBUG(
        if (ISSET(dmtx, DMT_WRITE))
        printf("[DMT%d=%x: st.%c %x to %x as %d %s %s]\n",
               x, dmtx, dmtx & DMT_DAS ? 's' : 'u', dmdx, dmax,
               DMT_ENBITS(dmtx),
               dmtx & DMT_DOUB1 ? "double": "not double",
               dmtx & DMT_LOCKBAR ? "xmem": "not xmem");
        else
            printf("[DMT%d=%x: ld.%c r%d <- %x as %d %s %s]\n",
                   x, dmtx, dmtx & DMT_DAS ? 's' : 'u',
                   DMT_DREGBITS(dmtx), dmax, DMT_ENBITS(dmtx),
                   dmtx & DMT_DOUB1 ? "double": "not double",
                   dmtx & DMT_LOCKBAR ? "xmem": "not xmem")
        );

    dmax += dmt_en_info[DMT_ENBITS(dmtx)].offset;
    reg = DMT_DREGBITS(dmtx);

    if (!ISSET(dmtx, DMT_LOCKBAR)) {
        /* the fault is not during an XMEM */

        if (x == 2 && ISSET(dmtx, DMT_DOUB1)) {
            /* pipeline 2 (earliest stage) for a double */

            if (ISSET(dmtx, DMT_WRITE)) {
                /*
                 * STORE DOUBLE WILL BE REINITIATED BY rte
                 */
            } else {
                /* EMULATE ld.d INSTRUCTION */
                v = do_load_word(dmax, dmtx & DMT_DAS);
                if (reg != 0)
                    eframe->tf_r[reg] = v;
                v = do_load_word(dmax ^ 4, dmtx & DMT_DAS);
                if (reg != 31)
                    eframe->tf_r[reg + 1] = v;
            }
        } else {
            /* not pipeline #2 with a double */
            if (dmtx & DMT_WRITE) {
                switch (dmt_en_info[DMT_ENBITS(dmtx)].size) {
                case DMT_BYTE:
                    DAE_DEBUG(
                        printf("[byte %x -> [%x(%c)]\n",
                               dmdx & 0xff, dmax,
                               ISSET(dmtx, DMT_DAS) ? 's' : 'u')
                    );
                    do_store_byte(dmax, dmdx,
                                  dmtx & DMT_DAS);
                    break;
                case DMT_HALF:
                    DAE_DEBUG(
                        printf("[half %x -> [%x(%c)]\n",
                               dmdx & 0xffff, dmax,
                               ISSET(dmtx, DMT_DAS) ? 's' : 'u')
                    );
                    do_store_half(dmax, dmdx,
                                  dmtx & DMT_DAS);
                    break;
                case DMT_WORD:
                    DAE_DEBUG(
                        printf("[word %x -> [%x(%c)]\n",
                               dmdx, dmax,
                               ISSET(dmtx, DMT_DAS) ? 's' : 'u')
                    );
                    do_store_word(dmax, dmdx,
                                  dmtx & DMT_DAS);
                    break;
                }
            } else {
                /* else it's a read */
                switch (dmt_en_info[DMT_ENBITS(dmtx)].size) {
                case DMT_BYTE:
                    v = do_load_byte(dmax, dmtx & DMT_DAS);
                    if (!ISSET(dmtx, DMT_SIGNED))
                        v &= 0x000000ff;
                    break;
                case DMT_HALF:
                    v = do_load_half(dmax, dmtx & DMT_DAS);
                    if (!ISSET(dmtx, DMT_SIGNED))
                        v &= 0x0000ffff;
                    break;
                case DMT_WORD:
                    v = do_load_word(dmax, dmtx & DMT_DAS);
                    break;
                }
                DAE_DEBUG(
                    if (reg == 0)
                    printf("[no write to r0 done]\n");
                    else
                        printf("[r%d <- %x]\n", reg, v);
                    );
                if (reg != 0)
                    eframe->tf_r[reg] = v;
            }
        }
    } else {
Example #2
0
void data_access_emulation(unsigned *eframe)
{
    register int x;
    register struct dmt_reg *dmtx;
    register unsigned  dmax, dmdx;
    register unsigned  v, reg;

    if (!(eframe[EF_DMT0] & DMT_VALID))
	return;

    for (x = 0; x < 3; x++)
    {
	dmtx = (struct dmt_reg *)&eframe[EF_DMT0+x*3];

	if (!dmtx->dmt_valid)
		continue;

	dmdx = eframe[EF_DMD0+x*3];
	dmax = eframe[EF_DMA0+x*3];

	DAE_DEBUG
	(
	  if (dmtx->dmt_write)
	    DEBUG_MSG("[DMT%d=%x: st.%c %x to %x as [%s] %s %s]\n",
	      x, eframe[EF_DMT0+x*3], dmtx->dmt_das ? 's' : 'u',
	      dmdx, dmax, bytes[dmtx->dmt_en], 
	      dmtx->dmt_doub1 ? "double": "not double",
	      dmtx->dmt_lockbar ? "xmem": "not xmem");
	  else
	    DEBUG_MSG("[DMT%d=%x: ld.%c r%d<-%x as [%s] %s %s]\n",
	      x, eframe[EF_DMT0+x*3], dmtx->dmt_das ? 's' : 'u',
	      dmtx->dmt_dreg, dmax, bytes[dmtx->dmt_en], 
	      dmtx->dmt_doub1 ? "double": "not double",
	      dmtx->dmt_lockbar ? "xmem": "not xmem");
	)

	dmax += dmt_en_info[dmtx->dmt_en].offset;
	reg = dmtx->dmt_dreg;

	if ( ! dmtx->dmt_lockbar)
	{
	    /* the fault is not during an XMEM */

	    if (x == 2 && dmtx->dmt_doub1)
	    {
		/* pipeline 2 (earliest stage) for a double */

		if (dmtx->dmt_write)
		{
		    /* STORE DOUBLE WILL BE RE-INITIATED BY rte */
		}
		else
		{
		    /* EMULATE ld.d INSTRUCTION */
			v = do_load_word(dmax, dmtx->dmt_das);
			if (reg != 0)
			    eframe[EF_R0 + reg] = v;
			v = do_load_word(dmax ^ 4, dmtx->dmt_das);
			if (reg != 31)
			    eframe[EF_R0 + reg + 1] = v;
		}
	    }
	    else	 /* not pipeline #2 with a double */
	    {
		if (dmtx->dmt_write) switch (dmt_en_info[dmtx->dmt_en].size)
		{
		  case DMT_BYTE:
		    DAE_DEBUG(DEBUG_MSG("[byte %x -> [%x(%c)]\n",
			dmdx & 0xff, dmax, dmtx->dmt_das ? 's' : 'u'))
		    do_store_byte(dmax, dmdx, dmtx->dmt_das);
		    break;
		  case DMT_HALF:
		    DAE_DEBUG(DEBUG_MSG("[half %x -> [%x(%c)]\n",
			dmdx & 0xffff, dmax, dmtx->dmt_das ? 's' : 'u'))
		    do_store_half(dmax, dmdx, dmtx->dmt_das);
		    break;
		  case DMT_WORD:
		    DAE_DEBUG(DEBUG_MSG("[word %x -> [%x(%c)]\n",
			dmdx, dmax, dmtx->dmt_das ? 's' : 'u'))
		    do_store_word(dmax, dmdx, dmtx->dmt_das);
		    break;
		}
		else	/* else it's a read */
		{
		    switch (dmt_en_info[dmtx->dmt_en].size)
		    {
		      case DMT_BYTE:
			v = do_load_byte(dmax, dmtx->dmt_das);
			if (!dmtx->dmt_signed)
			    v &= 0x000000ff;
			break;
		      case DMT_HALF:
			v = do_load_half(dmax, dmtx->dmt_das);
			if (!dmtx->dmt_signed)
			    v &= 0x0000ffff;
			break;
		      case DMT_WORD:
		      default: /* 'default' just to shut up lint */
			v = do_load_word(dmax, dmtx->dmt_das);
			break;
		    }
	   	    if (reg == 0) {
			DAE_DEBUG(DEBUG_MSG("[no write to r0 done]\n"));
		    }
		    else
		    {
			DAE_DEBUG(DEBUG_MSG("[r%d <- %x]\n",
				reg, v));
			eframe[EF_R0 + reg] = v;
		    }
		}
	    }
	}
	else /* if lockbar is set... it's part of an XMEM */
	{
	    /*
	     * According to Motorola's "General Information",
	     * the dmt_doub1 bit is never set in this case, as it should be.
	     * They call this "general information" - I call it a f*cking bug!
	     *
	     * Anyway, if lockbar is set (as it is if we're here) and if
	     * the write is not set, then it's the same as if doub1
	     * was set...
	     */
	    if ( ! dmtx->dmt_write)
	    {
		if (x != 2)
		{
		    /* RERUN xmem WITH DMD(x+1) */
		    x++;
		    dmdx = eframe[EF_DMD0 + x*3];
		}
		else
		{
		    /* RERUN xmem WITH DMD2 */
		}

		if (dmt_en_info[dmtx->dmt_en].size == DMT_WORD)
		    v = do_xmem_word(dmax, dmdx, dmtx->dmt_das);
		else
		    v = do_xmem_byte(dmax, dmdx, dmtx->dmt_das);
		eframe[EF_R0 + reg] = v;
	    }
	    else
	    {
		if (x == 0)
		{
		    eframe[EF_R0 + reg] = dmdx;
		    eframe[EF_SFIP] = eframe[EF_SNIP];
		    eframe[EF_SNIP] = eframe[EF_SXIP];
		    eframe[EF_SXIP] = 0;
		    /* xmem RERUN ON rte */
		    eframe[EF_DMT0] = 0;
		    return;
		}
	    }
	}
    }
Example #3
0
void
data_access_emulation(unsigned *eframe)
{
	int x;
	unsigned dmax, dmdx, dmtx;
	unsigned v, reg;

	dmtx = eframe[EF_DMT0];
	if (!ISSET(dmtx, DMT_VALID))
		return;

	for (x = 0; x < 3; x++) {
		dmtx = eframe[EF_DMT0 + x * 3];
		if (!ISSET(dmtx, DMT_VALID) || ISSET(dmtx, DMT_SKIP))
			continue;

		dmdx = eframe[EF_DMD0 + x * 3];
		dmax = eframe[EF_DMA0 + x * 3];

      DAE_DEBUG(
		if (ISSET(dmtx, DMT_WRITE))
			printf("[DMT%d=%x: st.%c %x to %x as %d %s %s]\n",
			    x, dmtx, dmtx & DMT_DAS ? 's' : 'u', dmdx, dmax,
			    DMT_ENBITS(dmtx),
			    dmtx & DMT_DOUB1 ? "double": "not double",
			    dmtx & DMT_LOCKBAR ? "xmem": "not xmem");
		else
			printf("[DMT%d=%x: ld.%c r%d <- %x as %d %s %s]\n",
			    x, dmtx, dmtx & DMT_DAS ? 's' : 'u',
			    DMT_DREGBITS(dmtx), dmax, DMT_ENBITS(dmtx),
			    dmtx & DMT_DOUB1 ? "double": "not double",
			    dmtx & DMT_LOCKBAR ? "xmem": "not xmem")
	);

		dmax += dmt_en_info[DMT_ENBITS(dmtx)].offset;
		reg = DMT_DREGBITS(dmtx);

		if (!ISSET(dmtx, DMT_LOCKBAR)) {
			/* the fault is not during an XMEM */

			if (x == 2 && ISSET(dmtx, DMT_DOUB1)) {
				/* pipeline 2 (earliest stage) for a double */

				if (ISSET(dmtx, DMT_WRITE)) {
					/*
					 * STORE DOUBLE WILL BE REINITIATED
					 * BY rte
					 */
				} else {
					/* EMULATE ld.d INSTRUCTION */
					v = do_load_word(dmax, dmtx & DMT_DAS);
					if (reg != 0)
						eframe[EF_R0 + reg] = v;
					v = do_load_word(dmax ^ 4,
					    dmtx & DMT_DAS);
					if (reg != 31)
						eframe[EF_R0 + reg + 1] = v;
				}
			} else {
				/* not pipeline #2 with a double */
				if (dmtx & DMT_WRITE) {
					switch (dmt_en_info[DMT_ENBITS(dmtx)].size) {
					case DMT_BYTE:
					DAE_DEBUG(
						printf("[byte %x -> [%x(%c)]\n",
						    dmdx & 0xff, dmax,
						    ISSET(dmtx, DMT_DAS) ? 's' : 'u')
					);
						do_store_byte(dmax, dmdx,
						    dmtx & DMT_DAS);
						break;
					case DMT_HALF:
					DAE_DEBUG(
						printf("[half %x -> [%x(%c)]\n",
						    dmdx & 0xffff, dmax,
						    ISSET(dmtx, DMT_DAS) ? 's' : 'u')
					);
						do_store_half(dmax, dmdx,
						    dmtx & DMT_DAS);
						break;
					case DMT_WORD:
					DAE_DEBUG(
						printf("[word %x -> [%x(%c)]\n",
						    dmdx, dmax,
						    ISSET(dmtx, DMT_DAS) ? 's' : 'u')
					);
						do_store_word(dmax, dmdx,
						    dmtx & DMT_DAS);
						break;
					}
				} else {
					/* else it's a read */
					switch (dmt_en_info[DMT_ENBITS(dmtx)].size) {
					case DMT_BYTE:
						v = do_load_byte(dmax,
						    dmtx & DMT_DAS);
						if (!ISSET(dmtx, DMT_SIGNED))
							v &= 0x000000ff;
						break;
					case DMT_HALF:
						v = do_load_half(dmax,
						    dmtx & DMT_DAS);
						if (!ISSET(dmtx, DMT_SIGNED))
							v &= 0x0000ffff;
						break;
					case DMT_WORD:
						v = do_load_word(dmax,
						    dmtx & DMT_DAS);
						break;
					}
					DAE_DEBUG(
						if (reg == 0)
							printf("[no write to r0 done]\n");
						else
							printf("[r%d <- %x]\n", reg, v);
					);
					if (reg != 0)
						eframe[EF_R0 + reg] = v;
				}
			}
		} else {
			/* if lockbar is set... it's part of an XMEM */
			/*
			 * According to Motorola's "General Information",
			 * the DMT_DOUB1 bit is never set in this case, as it
			 * should be.
			 * If lockbar is set (as it is if we're here) and if
			 * the write is not set, then it's the same as if DOUB1
			 * was set...
			 */
			if (!ISSET(dmtx, DMT_WRITE)) {