2017-01-12 3 views
2

Я разработал модуль ядра Linux, и для этого требуется использование констант с плавающей запятой. Недавно я столкнулся с сборкой ядра, с которой мне нужно работать, и отключает использование регистров с плавающей запятой для модулей ядра.Постоянная с плавающей запятой без использования регистров с плавающей запятой (модуль ядра Linux)

Полнота моих операций с плавающей точкой может быть во время компиляции, и все, что мне нужно, в конце концов, чтобы иметь переменную в куче, которая находится в-памяти двоичный эквивалент конкретной плавающей (объявленный тип переменной не имеет значения). Например:

const float fval = 3.8 * 0.98/1000.0; 
const int * const iptr = (const int *)&fval; 
const int ival = *iptr; 

Это свернуто, но, надеюсь, уточняет, чего я пытаюсь выполнить. В принципе, мне нужно выполнить эти шаги во время компиляции, чтобы у меня была переменная ival в куче, но без использования регистров с плавающей запятой в скомпилированном коде.

Мое решение hack-ish до сих пор состояло в том, чтобы запустить приведенный выше код для различных значений константы с плавающей запятой, которые мне нужно представлять, а затем вручную переписать их целочисленное представление в код модуля.

Выразили более четко (и, да, мне действительно нужно использовать с плавающей точкой в ​​некотором смысле ... Мне просто нужно избегать использования регистров с плавающей запятой в скомпилированном модуле). Предположим, у меня есть:

float val = 3.1415926; 

И пусть это будет храниться в памяти, как: 0xDA0F4940

Есть ли способ, чтобы получить компилятор для заполнения области памяти в куче с 0xDA0F4940 без скомпилирован в плавающей точечные операции?

+1

В качестве общего руководства: Не используйте плавающие точки в коде ядра. Существует очень малое, что можно сделать с помощью FP, что невозможно без него. –

+1

Препроцессор не работает с плавающей запятой. Однако ваш размещенный код C должен быть оптимизирован с помощью любого уровня оптимизации> 0 только в форме, в которой вы нуждаетесь (без регистров и без операций, только с инициализированными переменными). Попробуйте и посмотрите в сгенерированной сборке. –

+0

XY проблема. Существует простой и понятный способ обойтись без поплавков. Примените общую математику. Этот код вызывает неопределенное поведение. И на куче ничего не выделяется. – Olaf

ответ

2

Как насчет использования что-то вроде этого:

union val { 
    float fval; 
    int ival; 
}; 

static const union val my_val1 = { .fval = 3.8 * 0.98/1000.0 }; 

int *vp = whatever; 
*vp = my_val1.ival; 

Использование static const должно быть достаточно, чтобы предотвратить вычисления с плавающей точкой во время выполнения.

+0

Надеюсь, это сделает трюк. И спасибо за интерпретацию моего использования «препроцессора» как того, что я на самом деле имел в виду, «в любое время до времени выполнения». –

+0

Хорошо, я проверил, что это именно то, что мне нужно. Я был удивлен (но не очень), обнаружив, что я даже не мог выполнить назначение или копирование типов float без «использования регистров с плавающей запятой». Даже что-то вроде «static const float val1 = 3.1415; float val2 = val1;» не разрешалось. Еще раз спасибо! –

Смежные вопросы