Ejemplo n.º 1
0
void Inflator::OutputPast(unsigned int length, unsigned int distance)
{
	if (distance > m_maxDistance)
		throw BadBlockErr();
	unsigned int start;
	if (m_current > distance)
		start = m_current - distance;
	else
		start = m_current + m_window.size - distance;

	if (start + length > m_window.size)
	{
		for (; start < m_window.size; start++, length--)
			OutputByte(m_window[start]);
		start = 0;
	}

	if (start + length > m_current || m_current + length >= m_window.size)
	{
		while (length--)
			OutputByte(m_window[start++]);
	}
	else
	{
		memcpy(m_window + m_current, m_window + start, length);
		m_current += length;
		m_maxDistance = STDMIN(m_window.size, m_maxDistance + length);
	}
}
Ejemplo n.º 2
0
void Inflator::OutputPast(unsigned int length, unsigned int distance)
{
	size_t start;
	if (distance <= m_current)
		start = m_current - distance;
	else if (m_wrappedAround && distance <= m_window.size())
		start = m_current + m_window.size() - distance;
	else
		throw BadBlockErr();

	if (start + length > m_window.size())
	{
		for (; start < m_window.size(); start++, length--)
			OutputByte(m_window[start]);
		start = 0;
	}

	if (start + length > m_current || m_current + length >= m_window.size())
	{
		while (length--)
			OutputByte(m_window[start++]);
	}
	else
	{
		memcpy(m_window + m_current, m_window + start, length);
		m_current += length;
	}
}
Ejemplo n.º 3
0
/*
 * codegen_string_table:  Write out string table.
 */
void codegen_string_table(void)
{
   int i, curpos, total_len;
   char *str;
   list_type l;

   OutputInt(outfile, st.num_strings);

   curpos = FileCurPos(outfile);

   /* Write out offsets of strings (need to know string lengths) */
   total_len = 0;
   l = st.strings;
   for (i=0; i < st.num_strings; i++)
   {
      OutputInt(outfile, curpos + total_len + st.num_strings * 4);
      str = (char *) (l->data);
      total_len += strlen(str) + 1;
      l = l->next;
   }

   /* Now write out the strings themselves */
   l = st.strings;
   for (i=0; i < st.num_strings; i++)
   {
      str = (char *) (l->data);
      write(outfile, str, strlen(str));
      OutputByte(outfile, 0);    // null terminate
      l = l->next;
   }
}
Ejemplo n.º 4
0
T_void CompileCommand(T_byte8 *p_line)
{
    T_byte8 command[80] ;
    T_byte8 command2[80] ;
    T_byte8 *p_open ;
    T_sword16 commandNum ;

    sscanf(p_line, "%s", command) ;

    p_open = strstr(command, "(") ;
    if (p_open)
        *p_open = '\0' ;
    command2[0] = '\0' ;
    sscanf(command, "%s", command2) ;
    if (!command2[0])
         return ;
    commandNum = FindCommand(command2) ;
    if (commandNum == -1)  {
        printf("Error!  Unknown command '%s' on line %d\n", command2, G_line) ;
        exit(201) ;
    }
//    printf("command: <%s> = %d\n", command2, commandNum) ;
    OutputByte((T_byte8)commandNum) ;

    p_open = strstr(p_line, "(") ;
    if (!p_open)  {
        printf("Error!  Missing '(' on line %d\n", G_line) ;
        exit(202);
    }

    CompileArgs(p_open, G_commands[commandNum].numArgs) ;
}
Ejemplo n.º 5
0
/*
 * codegen_header: Write out header stuff before class info.
 */
void codegen_header(void)
{
   int i;
   for (i=0; i < 4; i++)
      OutputByte(outfile, bof_magic[i]);

   OutputInt(outfile, BOF_VERSION);
}
Ejemplo n.º 6
0
T_void OutputNumber(T_sword32 value)
{
    if ((value >= -120L) && (value <= 120L))  {
        OutputByte(SCRIPT_DATA_TYPE_8_BIT_NUMBER) ;
        OutputByte(((T_byte8 *)&value)[0]) ;
    } else if ((value >= -32760L) && (value <= 32760L))  {
        OutputByte(SCRIPT_DATA_TYPE_16_BIT_NUMBER) ;
        OutputByte(((T_byte8 *)&value)[0]) ;
        OutputByte(((T_byte8 *)&value)[1]) ;
    } else {
        OutputByte(SCRIPT_DATA_TYPE_32_BIT_NUMBER) ;
        OutputByte(((T_byte8 *)&value)[0]) ;
        OutputByte(((T_byte8 *)&value)[1]) ;
        OutputByte(((T_byte8 *)&value)[2]) ;
        OutputByte(((T_byte8 *)&value)[3]) ;
    }
}
Ejemplo n.º 7
0
VOID OutputWord (UWORD w)
{
    UBYTE   W [2];


    memcpy (W, &w, 2);

    if (LittleEndian)
    {
        OutputByte (W [1]);
        OutputByte (W [0]);
    }
    else
    {
        OutputByte (W [0]);
        OutputByte (W [1]);
    }
}
Ejemplo n.º 8
0
/*
 * codegen_message: Generate code for a single message handler.
 */
void codegen_message(message_handler_type m)
{
   int numlocals, maxtemp, maxlocals;
   list_type s, p = m->header->params;
   long localpos;

   /* Leave space for # of local variables */
   localpos = FileCurPos(outfile); 
   OutputByte(outfile, (BYTE) 0);
   
   /* Write out # of arguments */
   OutputByte(outfile,  (BYTE) list_length(p));
   
   /* Write out arguments themselves */
      for ( ; p != NULL; p = p->next)
	 codegen_parameter( (param_type) p->data);

   /* # of local variables, including parameters.  -1 is to start at 0. */
   numlocals = list_length(m->locals) + list_length(m->header->params) - 1;
   maxlocals = numlocals;

   /* Write out code */
   for (s = m->body; s != NULL; s = s->next)
   {
      maxtemp = codegen_statement( (stmt_type) s->data, numlocals);
      if (maxtemp > maxlocals)
	 maxlocals = maxtemp;

      /* Bomb out if statement had unforseen errors */
      if (!codegen_ok)
	 return;
   }

   /* Backpatch in # of local variables */
   if (maxlocals > MAX_LOCALS)
      codegen_error("More than %d local variables in handler %s.", MAX_LOCALS, 
		    m->header->message_id->name);

   FileGoto(outfile, localpos);
   OutputByte(outfile,  (BYTE) (maxlocals + 1));  /* +1 because we start counting at 0 */
   FileGotoEnd(outfile);
}
Ejemplo n.º 9
0
VOID OutputLong (ULONG l)
{
    UBYTE   L [4];

    memcpy (L, &l, 4);

    if (LittleEndian)
    {
        OutputByte (L [3]);
        OutputByte (L [2]);
        OutputByte (L [1]);
        OutputByte (L [0]);
    }
    else
    {
        OutputByte (L [0]);
        OutputByte (L [1]);
        OutputByte (L [2]);
        OutputByte (L [3]);
    }
}
Ejemplo n.º 10
0
/* 
 * codegen_call: Generate code for performing a function call and storing
 *   the return value in the given location (must be local or property).
 *   Set this location to NULL to ignore the return value.
 *   maxlocal is highest # local variable used so far in this message handler.
 *   Returns highest # local variable used in code for call.
 */
int codegen_call(call_stmt_type c, id_type destvar, int maxlocal)
{
   /* our_maxlocal gives highest #ed temporary needed to evaluate the
    * entire call.  maxtemps is the highest temp needed for a single arg. */
   int our_maxlocal = maxlocal, maxtemps, normal_args = 0;
   int argnum;
   list_type p;
   opcode_type opcode;
   arg_type arg;
   expr_type expr;
   id_type id;

   /* If an argument is complicated, we have to store it in a temporary */
   for (p = c->args; p != NULL; p = p->next)
   {
      arg = (arg_type) p->data;

      /* Get expression and place it in a temp if necessary */
      if (arg->type == ARG_EXPR)
	 expr = arg->value.expr_val;
      else expr = arg->value.setting_val->expr;

      maxtemps = simplify_expr(expr, maxlocal);
      /* If we need to use a temporary, then this temp must stay untouched until
       * the call is made.  So we must increment maxlocal in the case. */
      if (maxtemps > maxlocal)
	 maxlocal++;
      if (maxtemps > our_maxlocal)
	 our_maxlocal = maxtemps;
   }

   /* Build up call instruction */
   memset(&opcode, 0, sizeof(opcode));  /* Set opcode to all zeros */
   opcode.command = CALL;

   /* Set source1 field to place for return value */
   if (destvar == NULL)
      opcode.source1 = CALL_NO_ASSIGN;
   else
      switch (destvar->type)
      {
      case I_LOCAL:
	 opcode.source1 = CALL_ASSIGN_LOCAL_VAR;
	 break;

      case I_PROPERTY:
	 opcode.source1 = CALL_ASSIGN_PROPERTY;
	 break;

      default:
	 codegen_error("Identifier in expression not a local or property: %s", 
		       destvar->name);
      }

   OutputOpcode(outfile, opcode);

   /* Function # to call */
   OutputByte(outfile,  (BYTE) c->function);

   /* Place to store result, if any */
   if (opcode.source1 != CALL_NO_ASSIGN)
      OutputInt(outfile, destvar->idnum);

   /* Count # of "normal" arguments, i.e. all those
    * except for settings. */
   for (p = c->args; p != NULL; p = p->next)
      if ( ((arg_type) (p->data))->type != ARG_SETTING)
	 normal_args++;

   /* # of "normal" parameters */
   OutputByte(outfile,  (BYTE) normal_args);

   /* First have to generate code for "normal" parameters */
   for (p = c->args, argnum = 0; p != NULL; p = p->next, argnum++)
   {
      arg = (arg_type) p->data;

      switch (arg->type)
      {
      case ARG_EXPR:
	 /* Expression was reduced to simple form above */
	 OutputBaseExpression(outfile, arg->value.expr_val);
	 break;

      case ARG_SETTING:
	 /* Settings are handled below */
	 break;

      default:
	 codegen_error("Unknown argument type (%d) in argument %d", arg->type, argnum);	 
	 break;
      }
   }

   /* # of settings */
   OutputByte(outfile,  (BYTE) (list_length(c->args) - normal_args));

   /* Now take care of settings */
   for (p = c->args; p != NULL; p = p->next)
   {
      arg = (arg_type) p->data;

      if (arg->type == ARG_SETTING)
      {
	 id = arg->value.setting_val->id;
	 /* Write out parameter #, then rhs of assignment */
	 OutputInt(outfile, id->idnum);

	 OutputBaseExpression(outfile, arg->value.setting_val->expr);
      }
   }
   return our_maxlocal;
}
Ejemplo n.º 11
0
/*
 * codegen_filename:  Write out given filename.
 */
void codegen_filename(char *filename)
{
   write(outfile, filename, strlen(filename));
   OutputByte(outfile, 0);    // null terminate
}
Ejemplo n.º 12
0
bool Inflator::DecodeBody()
{
    bool blockEnd = false;
    switch (m_blockType)
    {
    case 0:	// stored
        assert(m_reader.BitsBuffered() == 0);
        while (!m_inQueue.IsEmpty() && !blockEnd)
        {
            size_t size;
            const byte *block = m_inQueue.Spy(size);
            size = UnsignedMin(m_storedLen, size);
            OutputString(block, size);
            m_inQueue.Skip(size);
            m_storedLen -= (word16)size;
            if (m_storedLen == 0)
                blockEnd = true;
        }
        break;
    case 1:	// fixed codes
    case 2:	// dynamic codes
        static const unsigned int lengthStarts[] = {
            3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
            35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
        };
        static const unsigned int lengthExtraBits[] = {
            0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
            3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
        };
        static const unsigned int distanceStarts[] = {
            1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
            257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
            8193, 12289, 16385, 24577
        };
        static const unsigned int distanceExtraBits[] = {
            0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
            7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
            12, 12, 13, 13
        };

        const HuffmanDecoder& literalDecoder = GetLiteralDecoder();
        const HuffmanDecoder& distanceDecoder = GetDistanceDecoder();

        switch (m_nextDecode)
        {
        case LITERAL:
            while (true)
            {
                if (!literalDecoder.Decode(m_reader, m_literal))
                {
                    m_nextDecode = LITERAL;
                    break;
                }
                if (m_literal < 256)
                    OutputByte((byte)m_literal);
                else if (m_literal == 256)	// end of block
                {
                    blockEnd = true;
                    break;
                }
                else
                {
                    if (m_literal > 285)
                        throw BadBlockErr();
                    unsigned int bits;
                case LENGTH_BITS:
                    bits = lengthExtraBits[m_literal-257];
                    if (!m_reader.FillBuffer(bits))
                    {
                        m_nextDecode = LENGTH_BITS;
                        break;
                    }
                    m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257];
                case DISTANCE:
                    if (!distanceDecoder.Decode(m_reader, m_distance))
                    {
                        m_nextDecode = DISTANCE;
                        break;
                    }
                case DISTANCE_BITS:
                    bits = distanceExtraBits[m_distance];
                    if (!m_reader.FillBuffer(bits))
                    {
                        m_nextDecode = DISTANCE_BITS;
                        break;
                    }
                    m_distance = m_reader.GetBits(bits) + distanceStarts[m_distance];
                    OutputPast(m_literal, m_distance);
                }
            }
        }
    }
    if (blockEnd)
    {
        if (m_eof)
        {
            FlushOutput();
            m_reader.SkipBits(m_reader.BitsBuffered()%8);
            if (m_reader.BitsBuffered())
            {
                // undo too much lookahead
                SecBlockWithHint<byte, 4> buffer(m_reader.BitsBuffered() / 8);
                for (unsigned int i=0; i<buffer.size(); i++)
                    buffer[i] = (byte)m_reader.GetBits(8);
                m_inQueue.Unget(buffer, buffer.size());
            }
            m_state = POST_STREAM;
        }
        else
            m_state = WAIT_HEADER;
    }
    return blockEnd;
}
Ejemplo n.º 13
0
T_void CompileArgs(T_byte8 *p_args, T_word16 numArgs)
{
    char args[10][100] ;
    T_word16 i, j, k ;
    T_byte8 arg[100] ;
    T_sword32 value ;
    T_word16 len ;

    p_args++ ;
    if (numArgs == 0)
        p_args++ ;

    for (i=0; i<numArgs; i++)  {
        j = 0 ;
        while ((*p_args != ',') && (*p_args != ')'))  {
            if (j==100)  {
                printf("Argument %d on line %d too long!\n",
                    i+1,
                    G_line) ;
                G_errors++ ;
                return ;
            }
            args[i][j++] = *(p_args++) ;
        }
        if ((p_args[0] == ')') && ((i+1) != numArgs))  {
            printf("Error!  Wrong number of arguments on line %d\n",
                G_line) ;
            G_errors++ ;
            return ;
        }
        args[i][j] = '\0' ;
        p_args++ ;
    }
    if (p_args[-1] != ')')  {
        printf("Error!  Wrong number of arguments on line %d\n",
             G_line) ;
        G_errors ++ ;
        return ;
    }

    for (i=0; i<numArgs; i++)  {
//printf("arg[%d] = '%s'\n", i, args[i]) ;
        strcpy(arg, args[i]) ;
        Strip(arg) ;
        if ((arg[0] == '-') || (isdigit(arg[0])))  {
            /* Arg is Number. */
            value = atol(arg) ;
            OutputNumber(value) ;
        } else if (arg[0] == '&')  {
            /* Event. */
            value = atol(arg+1) ;
            if (!((value >= 1) && (value <= 3)))  {
                printf("Error!  Event parameter (%ld) out of range (1-3) on line %d!\n",
                    value,
                    G_line) ;
                G_errors++ ;
                return ;
            }
            OutputByte(SCRIPT_DATA_TYPE_EVENT_PARAMETER) ;
            OutputByte((T_byte8)value) ;
        } else if (arg[0] == QUOTE_START)  {
            len = strlen(arg)-2 ;
            if (len >= 80)  {
                printf("Error!  String too long on line %d!\n", G_line) ;
                G_errors++ ;
                return ;
            }
            OutputByte(SCRIPT_DATA_TYPE_STRING) ;
            OutputByte((T_byte8)len) ;
            for (k=0; k<len; k++)  {
                OutputByte(arg[1+k]) ;
            }
        } else {
            /* Try doing a flag name. */
            value = FindFlag(arg) ;
            if (value != -1)  {
                OutputByte(SCRIPT_DATA_TYPE_FLAG) ;
                OutputByte((T_byte8)value) ;
            } else {
                value = FindVar(arg) ;
                if (value != -1)  {
                    value = G_vars[value].number ;
                    OutputByte(SCRIPT_DATA_TYPE_VARIABLE) ;
                    OutputByte(((T_byte8 *)&value)[0]) ;
                    OutputByte(((T_byte8 *)&value)[1]) ;
                } else {
//printf("Searching for defnum: %s\n", arg) ;
                    value = FindDefnum(arg) ;
                    if (value != -1)  {
                        value = G_defnums[value].number ;
//printf("Output defnum: %s %ld\n", arg, value) ;
                        OutputNumber(value) ;
                    } else {
                        printf("Error!  Unknown argument '%s' on line %d\n",
                            arg,
                            G_line) ;
                        G_errors++ ;
                        return ;
                    }
                }
            }
        }
    }
}
Ejemplo n.º 14
0
void TD_Poll(void)              // Called repeatedly while the device is idle
{
   if(!Running) return;
   
   if(!(EP1INCS & bmEPBUSY))
   {
      if(Pending > 0)
      {
         BYTE o, n;

         AUTOPTRH2 = MSB( EP1INBUF );
         AUTOPTRL2 = LSB( EP1INBUF );
       
         XAUTODAT2 = 0x31;
         XAUTODAT2 = 0x60;
       
         if(Pending > 0x3E) { n = 0x3E; Pending -= n; } 
                     else { n = Pending; Pending = 0; };
       
         o = n;

#ifdef USE_MOD256_OUTBUFFER
         AUTOPTR1H = MSB( OutBuffer );
         AUTOPTR1L = FirstDataInOutBuffer;
         while(n--)
         {
            XAUTODAT2 = XAUTODAT1;
            AUTOPTR1H = MSB( OutBuffer ); // Stay within 256-Byte-Buffer
         };
         FirstDataInOutBuffer = AUTOPTR1L;
#else
         AUTOPTR1H = MSB( &(OutBuffer[FirstDataInOutBuffer]) );
         AUTOPTR1L = LSB( &(OutBuffer[FirstDataInOutBuffer]) );
         while(n--)
         {
            XAUTODAT2 = XAUTODAT1;

            if(++FirstDataInOutBuffer >= OUTBUFFER_LEN)
            {
               FirstDataInOutBuffer = 0;
               AUTOPTR1H = MSB( OutBuffer );
               AUTOPTR1L = LSB( OutBuffer );
            };
         };
#endif
         SYNCDELAY;
         EP1INBC = 2 + o;
         TF2 = 1; // Make sure there will be a short transfer soon
      }
      else if(TF2)
      {
         EP1INBUF[0] = 0x31;
         EP1INBUF[1] = 0x60;
         SYNCDELAY;
         EP1INBC = 2;
         TF2 = 0;
      };
   };

   if(!(EP2468STAT & bmEP2EMPTY) && (Pending < OUTBUFFER_LEN-0x3F))
   {
      BYTE i, n = EP2BCL;

      AUTOPTR1H = MSB( EP2FIFOBUF );
      AUTOPTR1L = LSB( EP2FIFOBUF );

      for(i=0;i<n;)
      {
         if(ClockBytes > 0)
         {
            BYTE m;

            m = n-i;
            if(ClockBytes < m) m = ClockBytes;
            ClockBytes -= m;
            i += m;
         
            if(WriteOnly) /* Shift out 8 bits from d */
            {
               while(m--) ShiftOut(XAUTODAT1);
            }
            else /* Shift in 8 bits at the other end  */
            {
               while(m--) OutputByte(ShiftInOut(XAUTODAT1));
            }
        }
        else
        {
            BYTE d = XAUTODAT1;
            WriteOnly = (d & bmBIT6) ? FALSE : TRUE;

            if(d & bmBIT7)
            {
               /* Prepare byte transfer, do nothing else yet */

               ClockBytes = d & 0x3F;
            }
            else
            {
               /* Set state of output pins */

               TCK = (d & bmBIT0) ? 1 : 0;
               TMS = (d & bmBIT1) ? 1 : 0;
               TDI = (d & bmBIT4) ? 1 : 0;

               /* Optionally read state of input pins and put it in output buffer */

               if(!WriteOnly) OutputByte(2|TDO);
            };
            i++;
         };
      };

      SYNCDELAY;
      EP2BCL = 0x80; // Re-arm endpoint 2
   };
}
Ejemplo n.º 15
0
void Inflator::OutputString(const byte *string, unsigned int length)
{
	while (length--)
		OutputByte(*string++);
}
Ejemplo n.º 16
0
/*

*-------------------------------------------------------------------------------

* 3.1 LZSS_ExpandData

*-------------------------------------------------------------------------------

*

* LZSS expand data stream

*

* This routine expands data from an in buffer with the LZSS algorithm.

* The routine read in flag bits to decide whether to read in an uncompressed

* character or an index/length pair and expands the data stream to an out

* buffer.

*

* param inBuf Input data buffer with bit access

* param outBuf Output data buffer with byte access

*

* return Void

*

*/
void LZSS_ExpandData(LZSS_InputBuffer_T *inBuf, LZSS_OutputBuffer_T *outBuf)

{

	/** Index var. for loop */

	Uint8_T i = 0;

	/** Current window position */

	Uint16_T winPos = 1;

	/** Byte to write to output buffer */

	Uint8_T outByte = 0;

	/** Length of the data match found */

	Uint8_T matchLen = 0;

	/** Position in the window of the data match */

	Uint16_T matchPos = 0;

	/** Indicator of End Of Stream reached */

	BOOL_T eosReached = FALSE;

	while (!eosReached)

	{

		/* If next bit is 1, next byte is uncompressed*/

		if (InputBit(inBuf) == 1)

		{

			/* Get uncompressed byte */

			outByte = (Uint8_T)InputBits(inBuf, (Uint8_T)8);

			/* Output byte*/

			OutputByte(outByte, outBuf);

			/* Add byte in window */

			LZSS_window[winPos] = outByte;

			/* Increase window position */

			winPos = LZSS_MOD_WINDOW(winPos + 1);

		}

		/* If next bit is 0, compressed data follows */

		else

		{

			/* Get compressed data as window position of match*/

			matchPos = (Uint16_T)InputBits(inBuf, LZSS_INDEX_BIT_COUNT);

			/* If end of stream, exit */

			if (matchPos == LZSS_END_OF_STREAM)

			{

				eosReached = TRUE;

			}

			else

			{

				/* Get length of string match */

				matchLen = (Uint8_T)InputBits(inBuf, LZSS_LENGTH_BIT_COUNT);

				/* Add break even + 1 to get the correct length. Length zero and

				* the break even value are subtracted from the length during

				* compression to save space. */

				matchLen = matchLen + (LZSS_BREAK_EVEN + 1);

				/* For every byte in match */

				for (i = 0; i < matchLen; i++)

				{

					/* Get matching byte from window */

					outByte = LZSS_window[LZSS_MOD_WINDOW(matchPos + i)];

					/* Output byte */

					OutputByte(outByte, outBuf);

					/* Add matched byte to current window position */

					LZSS_window[winPos] = outByte;

					/* Increase window position */

					winPos = LZSS_MOD_WINDOW(winPos + 1);

				}

			}

		}

	}

}
Ejemplo n.º 17
0
void usb_jtag_activity(void) // Called repeatedly while the device is idle
{
   if(!Running) return;

   ProgIO_Poll();
   
   if(!(EP1INCS & bmEPBUSY))
   {
      if(Pending > 0)
      {
         BYTE o, n;

         AUTOPTRH2 = MSB( EP1INBUF );
         AUTOPTRL2 = LSB( EP1INBUF );
       
         XAUTODAT2 = 0x31;
         XAUTODAT2 = 0x60;
       
         if(Pending > 0x3E) { n = 0x3E; Pending -= n; } 
                     else { n = Pending; Pending = 0; };
       
         o = n;

#ifdef USE_MOD256_OUTBUFFER
         APTR1H = MSB( OutBuffer );
         APTR1L = FirstDataInOutBuffer;
         while(n--)
         {
            XAUTODAT2 = XAUTODAT1;
            APTR1H = MSB( OutBuffer ); // Stay within 256-Byte-Buffer
         };
         FirstDataInOutBuffer = APTR1L;
#else
         APTR1H = MSB( &(OutBuffer[FirstDataInOutBuffer]) );
         APTR1L = LSB( &(OutBuffer[FirstDataInOutBuffer]) );
         while(n--)
         {
            XAUTODAT2 = XAUTODAT1;

            if(++FirstDataInOutBuffer >= OUTBUFFER_LEN)
            {
               FirstDataInOutBuffer = 0;
               APTR1H = MSB( OutBuffer );
               APTR1L = LSB( OutBuffer );
            };
         };
#endif
         SYNCDELAY;
         EP1INBC = 2 + o;
         TF2 = 1; // Make sure there will be a short transfer soon
      }
      else if(TF2)
      {
         EP1INBUF[0] = 0x31;
         EP1INBUF[1] = 0x60;
         SYNCDELAY;
         EP1INBC = 2;
         TF2 = 0;
      };
   };

   if(!(EP2468STAT & bmEP2EMPTY) && (Pending < OUTBUFFER_LEN-0x3F))
   {
      WORD i, n = EP2BCL|EP2BCH<<8;

      APTR1H = MSB( EP2FIFOBUF );
      APTR1L = LSB( EP2FIFOBUF );

      for(i=0;i<n;)
      {
         if(ClockBytes > 0)
         {
            WORD m;

            m = n-i;
            if(ClockBytes < m) m = ClockBytes;
            ClockBytes -= m;
            i += m;

            /* Shift out 8 bits from d */
         
            if(WriteOnly) /* Shift out 8 bits from d */
            {
               while(m--) ProgIO_ShiftOut(XAUTODAT1);
            }
            else /* Shift in 8 bits at the other end  */
            {
               while(m--) OutputByte(ProgIO_ShiftInOut(XAUTODAT1));
            }
        }
        else
        {
            BYTE d = XAUTODAT1;
            WriteOnly = (d & bmBIT6) ? FALSE : TRUE;

            if(d & bmBIT7)
            {
               /* Prepare byte transfer, do nothing else yet */

               ClockBytes = d & 0x3F;
            }
            else
            {
               if(WriteOnly)
                   ProgIO_Set_State(d);
               else
                   OutputByte(ProgIO_Set_Get_State(d));
            };
            i++;
         };
      };

      SYNCDELAY;
      EP2BCL = 0x80; // Re-arm endpoint 2
   };
}
Ejemplo n.º 18
0
static ret_code DoPatch( struct asym *sym, struct fixup *fixup )
/**************************************************************/
{
    long                disp;
    long                max_disp;
    unsigned            size;
    struct dsym         *seg;
#if LABELOPT
    struct asym         *sym2;
    struct fixup        *fixup2;
#endif

    /* all relative fixups should occure only at first pass and they signal forward references
     * they must be removed after patching or skiped ( next processed as normal fixup )
     */

    DebugMsg(("DoPatch(%u, %s): fixup sym=%s type=%u ofs=%" FX32 "h loc=%" FX32 "h opt=%u def_seg=%s\n",
              Parse_Pass + 1, sym->name,
              fixup->sym ? fixup->sym->name : "NULL",
              fixup->type,
              fixup->offset,
              fixup->location,
              fixup->option,
              fixup->def_seg ? fixup->def_seg->sym.name : "NULL" ));
    seg = GetSegm( sym );
    if( seg == NULL || fixup->def_seg != seg ) {
        /* if fixup location is in another segment, backpatch is possible, but
         * complicated and it's a pretty rare case, so nothing's done.
         */
        DebugMsg(("DoPatch: skipped due to seg incompat: %s - %s\n",
                  fixup->def_seg ? fixup->def_seg->sym.name : "NULL",
                  seg ? seg->sym.name : "NULL" ));
        SkipFixup();
        return( NOT_ERROR );
    }

    if( Parse_Pass == PASS_1 ) {
        if( sym->mem_type == MT_FAR && fixup->option == OPTJ_CALL ) {
            /* convert near call to push cs + near call,
             * (only at first pass) */
            DebugMsg(("DoPatch: Phase error! caused by far call optimization\n"));
            ModuleInfo.PhaseError = TRUE;
            sym->offset++;  /* a PUSH CS will be added */
            /* todo: insert LABELOPT block here */
            OutputByte( 0 ); /* it's pass one, nothing is written */
            FreeFixup( fixup );
            return( NOT_ERROR );
            //} else if( sym->mem_type == MT_NEAR ) {
        } else {
            /* forward reference, only at first pass */
            switch( fixup->type ) {
            case FIX_RELOFF32:
            case FIX_RELOFF16:
                FreeFixup( fixup );
                DebugMsg(("DoPatch: FIX_RELOFF32/FIX_RELOFF16, return\n"));
                return( NOT_ERROR );
            case FIX_OFF8:  /* push <forward reference> */
                if ( fixup->option == OPTJ_PUSH ) {
                    size = 1;    /* size increases from 2 to 3/5 */
                    DebugMsg(("DoPatch: FIX_OFF8\n"));
                    goto patch;
                }
            }
        }
    }
    size = 0;
    switch( fixup->type ) {
    case FIX_RELOFF32:
        size = 2; /* will be 4 finally */
    /* fall through */
    case FIX_RELOFF16:
        size++; /* will be 2 finally */
    /* fall through */
    case FIX_RELOFF8:
        size++;
        /* calculate the displacement */
        // disp = fixup->offset + GetCurrOffset() - fixup->location - size;
        disp = fixup->offset + fixup->sym->offset - fixup->location - size - 1;
        max_disp = (1UL << ((size * 8)-1)) - 1;
        if( disp > max_disp || disp < (-max_disp-1) ) {
patch:
            DebugMsg(("DoPatch(%u): Phase error, disp=%X, fixup=%s(%X), loc=%X!\n", Parse_Pass + 1, disp, fixup->sym->name, fixup->sym->offset, fixup->location ));
            ModuleInfo.PhaseError = TRUE;
            /* ok, the standard case is: there's a forward jump which
             * was assumed to be SHORT, but it must be NEAR instead.
             */
            switch( size ) {
            case 1:
                size = 0;
                switch( fixup->option ) {
                case OPTJ_EXPLICIT:
#if 0 /* don't display the error at the destination line! */
                    sym->fixup = NULL;
                    DebugMsg(("DoPatch: jump out of range, disp=%d\n", disp ));
                    EmitErr( JUMP_OUT_OF_RANGE, disp - max_disp );
                    return( ERROR );
#else
                    return( NOT_ERROR ); /* nothing to do */
#endif
                case OPTJ_EXTEND: /* Jxx for 8086 */
                    size++;       /* will be 3/5 finally */
                /* fall through */
                case OPTJ_JXX: /* Jxx for 386 */
                    size++;
                /* fall through */
                default: /* normal JMP (and PUSH) */
                    // if( CodeInfo->Ofssize ) /* v1.96: don't use CodeInfo here! */
                    if( seg->e.seginfo->Ofssize )
                        size += 2; /* NEAR32 instead of NEAR16 */
                    size++;
#if LABELOPT
                    /* v2.04: if there's an ORG between src and dst, skip
                     * the optimization!
                     */
                    if ( Parse_Pass == PASS_1 ) {
                        for ( fixup2 = seg->e.seginfo->FixupListHead; fixup2; fixup2 = fixup2->nextrlc ) {
                            if ( fixup2->orgoccured ) {
                                DebugMsg(("DoPatch: ORG/ALIGN detected, optimization canceled\n" ));
                                return( NOT_ERROR );
                            }
                            /* do this check after the check for ORG! */
                            if ( fixup2->location <= fixup->location )
                                break;
                        }
                    }
                    /* scan the segment's label list and adjust all labels
                     * which are between the fixup loc and the current sym.
                     * ( PROCs are NOT contained in this list because they
                     * use the <next>-field of dsym already!)
                     */
                    for ( sym2 = seg->e.seginfo->labels; sym2; sym2 = (struct asym *)((struct dsym *)sym2)->next ) {
                        //if ( sym2 == sym )
                        //    continue;
                        /* v2.0: location is at least 1 byte too low, so
                         * use the "<=" operator instead of "<"!
                         */
                        //if ( sym2->offset < fixup->location )
                        if ( sym2->offset <= fixup->location )
                            break;
                        sym2->offset += size;
                        DebugMsg(("DoPatch(loc=%" FX32 "): sym %s, offset changed %" FX32 " -> %" FX32 "\n", fixup->location, sym2->name, sym2->offset - size, sym2->offset));
                    }
                    /* v2.03: also adjust fixup locations located between the
                     * label reference and the label. This should reduce the
                     * number of passes to 2 for not too complex sources.
                     */
                    if ( Parse_Pass == PASS_1 ) /* v2.04: added, just to be safe */
                        for ( fixup2 = seg->e.seginfo->FixupListHead; fixup2; fixup2 = fixup2->nextrlc ) {
                            if ( fixup2->sym == sym )
                                continue;
                            if ( fixup2->location <= fixup->location )
                                break;
                            fixup2->location += size;
                            DebugMsg(("for sym=%s fixup loc %" FX32 " changed to %" FX32 "\n", fixup2->sym->name, fixup2->location - size, fixup2->location ));
                        }
#else
                    DebugMsg(("DoPatch: sym %s, offset changed %" FX32 " -> %" FX32 "\n", sym->name, sym->offset, sym->offset + size));
                    sym->offset += size;
#endif
                    /*  it doesn't matter what's actually "written" */
                    for ( ; size; size-- )
                        OutputByte( 0xCC );
                    break;
                }
                break;
            case 2:
            case 4:
                DebugMsg(("DoPatch: jump out of range, disp=%d\n", disp ));
                EmitWarn( 4, JUMP_OUT_OF_RANGE, disp - max_disp );
                break;
            }
        }
#ifdef DEBUG_OUT
        else
            DebugMsg(("DoPatch, loc=%" FX32 ": displacement still short: %Xh\n", fixup->location, disp ));
#endif
        /* v2.04: fixme: is it ok to remove the fixup?
         * it might still be needed in a later backpatch.
         */
        FreeFixup( fixup );
        break;
    default:
        DebugMsg(("DoPatch: default branch, unhandled fixup type=%u\n", fixup->type ));
        SkipFixup();
        break;
    }
    return( NOT_ERROR );
}