Отключить 64-битное деление в компиляторе Code Composer Studio

В настоящее время я пишу программу на C, используя Code Composer Studio (CCS) V7.4.0.00015. В программе есть несколько самописных библиотек, которые выполняют Byte, unsigned int и float деление.

Я достиг той стадии проекта, когда мне нужно уменьшить размер кода, чтобы обеспечить достаточно места для загрузчика.

Глядя на мой файл .map, я обнаруживаю несколько объектов поддержки времени выполнения, которые CCS автоматически включает. Некоторые из них включают следующее:

  • div64u.obj --> 846 байт
  • div64s.obj --> 316 байт

Эти объекты из rts430x_lc_sd_eabi.lib

Мой вопрос: почему эти 64-битные объекты деления включены (особенно, когда в моей программе нет 64-битных чисел с плавающей запятой)? И, что более важно, могу ли я отключить их (или запретить CCS включать их)?

Я провел несколько дней в поиске и просмотре различных сайтов, но мне не удалось найти много документации по этим объектам или по их отключению.

Редактировать: Оказывается, у меня действительно есть одна функция, использующая long long int (typedef'd как SLLONG)

/**
 * @brief Compensate the raw pressure gained from the BME
 * @details Uses the pressure compensation parameters to 
 *      calculate the true pressure from the raw pressure
 *      
 *      Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa
 *
 *      The contents of this function have been taken from the Adafruit Github page
 *      https://github.com/adafruit/Adafruit_BME280_Library
 * 
 * @param rawPressure The raw pressure
 * @param tempFine The temperature in high resoltuion format, 
 *      gained from the BME_compensateTemp() function
 * 
 * @return the pressure read from the device
 */
float BME_compensatePressure(ULONG rawPressure, SLONG tempFine)
{
    SLLONG var1, var2, p;

    if (rawPressure == 0x800000) // value in case pressure measurement was disabled
        return SNaN;
    rawPressure >>= 4;

    var1 = ((SLLONG)tempFine) - 128000;                                         // SLONG cast to SLLONG 
    var2 = var1 * var1 * (SLLONG)compParamsStruct.dig_P6;                       // SLONG^2 x (SWORD cast to SLLONG) 
    var2 = var2 + ((var1*(SLLONG)compParamsStruct.dig_P5)<<17);                 // SLLONG + (SLLONG * SWORD cast to SLLONG)
    var2 = var2 + (((SLLONG)compParamsStruct.dig_P4)<<35);
    var1 = ((var1 * var1 * (SLLONG)compParamsStruct.dig_P3)>>8) +
           ((var1 * (SLLONG)compParamsStruct.dig_P2)<<12);
    var1 = (((((SLLONG)1)<<47)+var1))*((SLLONG)compParamsStruct.dig_P1)>>33;

    if (var1 == 0) {
        return 0; // avoid exception caused by division by zero
    }
    p = 1048576 - rawPressure;
    p = (((p<<31) - var2)*3125) / var1;
    var1 = (((SLLONG)compParamsStruct.dig_P9) * (p>>13) * (p>>13)) >> 25;
    var2 = (((SLLONG)compParamsStruct.dig_P8) * p) >> 19;

    p = ((p + var1 + var2) >> 8) + (((SLLONG)compParamsStruct.dig_P7)<<4);
    return ((float)p)/256;
}

Новый вопрос:

  • Может ли кто-нибудь найти способ изменить функцию так, чтобы она не требовала использования длинных длинных целых чисел (без потери точности?)
  • ИЛИ, более конкретно, может ли кто-нибудь понять, как я могу сделать это длинное длинное деление по-другому, то есть строку, показанную ниже:
p = (((p<<31) - var2)*3125) / var1;

person dlenno89    schedule 15.10.2019    source источник
comment
почти все компиляторы имеют возможность оптимизации размера кода, например -Os в gcc и /Os в MSVC. Проверьте руководство по компилятору. И я не думаю, что div64u/s предназначены для деления с плавающей запятой. Они выглядят как целочисленное деление и могут использоваться другими утилитами, которые вы вызываете.   -  person phuclv    schedule 15.10.2019
comment
Проверьте документацию вашего компоновщика, чтобы показать, почему он включает модуль, и проверьте все ваши объектные модули (включая модули из библиотек) на наличие ссылок на эти символы.   -  person Eric Postpischil    schedule 15.10.2019
comment
@phuclv Я думаю, вы правы в том, что это целочисленное деление. Однако в моем проекте определенно нет 64-битных типов данных. У меня есть 32-битные беззнаковые и подписанные целые числа, где над ними выполняются математические операции. Есть ли что-то, что я должен искать (или избегать), что может привести к включению этого 64-битного объекта?   -  person dlenno89    schedule 16.10.2019
comment
@EricPostpischil спасибо за идеи. У меня возникли небольшие проблемы с поиском документации компоновщика. Командный файл компоновщика называется lnk_msp430fr2433.cmd. Есть ли у вас какие-либо идеи относительно общих поисковых терминов/ключевых слов, которые я должен использовать, чтобы найти то, что я ищу? извините за новичок.   -  person dlenno89    schedule 16.10.2019
comment
@EricPostpischil неважно, в конце концов я нашел нужную документацию здесь, но я не могу найти ничего, ссылающегося на div64u.obj или почему некоторые объекты, а не другие, включены в библиотеку поддержки времени выполнения   -  person dlenno89    schedule 16.10.2019
comment
в порядке. Оказывается, у меня действительно есть несколько длинных длинных целых чисел. Пожалуйста, обновите вопрос выше для более подробной информации   -  person dlenno89    schedule 16.10.2019
comment
если приемлема более низкая точность, просто используйте (float)((p<<31) - var2)/var1*3125.0f;, поскольку вы уже используете float в своем коде. Но не слишком ли много 316 байт? Сколько у вас осталось флешки?   -  person phuclv    schedule 15.12.2019
comment
@phuclv да, возможно, я переусердствовал с попытками уменьшить размер кода. Я ценю ваш вклад, и я буду держать вашу идею под рукой, если я обнаружу, что мне нужно выжать немного больше места из кода. Спасибо!   -  person dlenno89    schedule 16.12.2019


Ответы (1)


Резюме моего решения исходной проблемы 64-битных операций с плавающей запятой:

Сначала в флаги компилятора были вставлены следующие строки:

--float_operations_allowed=32

Однако это привело к нескольким ошибкам в проекте. Ошибка была одинаковой для каждого местоположения:

#1558-D 64-bit floating point operations are not allowed

Код, вызвавший эти ошибки, был:

float lowerFence = med -1.5 * IQR;
float upperFence = med +1.5 * IQR;

и

return 0.5*coeffs->c0+tempScaled*coeffs->c1;                

Ошибка была исправлена ​​путем приведения литералов к числам с плавающей запятой и переноса нескольких операций с числами с плавающей запятой в одну строку.

float IQR = STATS_Iqr(sorted, numSamples);
float iqrScaled = 1.5 * IQR;
float lowerFence = med - iqrScaled;
float upperFence = med + iqrScaled;

и

float half = 0.5;
float c0Scaled = half*coeffs->c0;
float c1Scaled = tempScaled*coeffs->c1;
return c0Scaled + c1Scaled;  

После устранения вышеуказанных ошибок проект был очищен и пересобран. Добавление этого флага компилятора привело к удалению следующих объектов.

person dlenno89    schedule 16.12.2019
comment
Я считаю, что вы получите гораздо большую экономию ПЗУ, заменив double литералы, такие как 1.5 и 0.5, на 1.5f и 0.5f. Если вы не знаете, то литералы с плавающей запятой без суффикса всегда двойные, поэтому float iqrScaled = 1.5 * IQR; выполняется путем повышения IQR до двойного, умножения его на двойное 1,5, а затем обратного приведения к float. Если вам не нужна двойная точность, всегда используйте суффикс f. Но в этом случае вы можете полностью отказаться от операций с плавающей запятой и использовать все целые числа: int IQR;int iqrScaled = IQR*3/2; - person phuclv; 16.12.2019
comment
@phuclv легендарное предложение! Я реализую оба метода и посмотрю, как я пойду! Большое спасибо за идеи! я очень ценю это - person dlenno89; 17.12.2019