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); } }
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; } }
/* * 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; } }
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) ; }
/* * 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); }
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]) ; } }
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]); } }
/* * 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); }
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]); } }
/* * 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; }
/* * codegen_filename: Write out given filename. */ void codegen_filename(char *filename) { write(outfile, filename, strlen(filename)); OutputByte(outfile, 0); // null terminate }
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; }
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 ; } } } } } }
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 }; }
void Inflator::OutputString(const byte *string, unsigned int length) { while (length--) OutputByte(*string++); }
/* *------------------------------------------------------------------------------- * 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); } } } } }
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 }; }
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 ); }