2016-02-05 2 views
2

Я новичок в X86, и я застрял в обновлении двойного массива, используя значения другого двойного массива. Следующий код - это моя функция, и я хочу использовать встроенную сборку для замены фрагмента кода внутри цикла. Я приложил сообщение об ошибке ниже. Может ли кто-нибудь помочь мне указать на мои ошибки? Я запутался в сообщениях об ошибках и не знаю, как их пересмотреть.Как обновить все элементы в двойном массиве в X86?

static inline void update(double * x,double * y,double * z,double * vx, 
     double * vy,double * vz,uint32_t size){ 
     for (uint32_t i=0;i<size;++i){ 
      x[i] = x[i] + vx[i]; 
      y[i] = y[i] + vy[i]; 
      z[i] = z[i] + vz[i]; 
     } 
} 
uint32_t counter = 0; 
__asm__ __volatile__ ( 
    "loop: \n\t" 
    "faddq (%4), (%1)\n\t" 
    "faddq (%5), (%2)\n\t" 
    "faddq (%6), (%3)\n\t" 
    "addq $8, %1\n\t" 
    "addq $8, %2\n\t" 
    "addq $8, %3\n\t" 
    "addq $8, %4\n\t" 
    "addq $8, %5\n\t" 
    "addq $8, %6\n\t" 
    "incq %0\n\t" 
    "cmp %0, %7\n\t" 
    "jne loopb" 
    : "+r"(counter) 
    : "r" (x),"r" (y),"r"(z),"r"(vx),"r"(vy),"r"(vz),"r"(size) 
    : "memory", "cc"); 

Сообщения об ошибках:

update_locations_ass.c:150:15: error: invalid instruction mnemonic 'faddq' 
     "loop: \n\t" 
       ^
<inline asm>:2:2: note: instantiated into assembly here 
     faddq (%rdi), (%rcx) 
     ^~~~~ 
update_locations_ass.c:151:25: error: invalid instruction mnemonic 'faddq' 
     "faddq (%4), (%1)\n\t" 
         ^
<inline asm>:3:2: note: instantiated into assembly here 
     faddq (%r8), (%rdx) 
     ^~~~~ 
update_locations_ass.c:152:28: error: invalid instruction mnemonic 'faddq' 
     "faddq (%5), (%2)\n\t" 
         ^
<inline asm>:4:2: note: instantiated into assembly here 
     faddq (%r9), (%rsi) 
     ^~~~~ 
update_locations_ass.c:159:23: error: invalid operand for instruction 
     "addq $8, %6\n\t" 
        ^
<inline asm>:11:7: note: instantiated into assembly here 
     incq %eax 

Компилятор версия: сконфигурированного с: prefix =/Применения/Xcode.app/Содержание/Developer/USR --with-Gxx-включают-DIR = /usr/include/c++/4.2.1 компании Apple LLVM версии 6.1.0 (лязг-602.0.53) (на основе LLVM 3.6.0svn) Цель: x86_64-яблочно-darwin14.0.0 Автор модели:

POSIX
+1

Какой компилятор вы используете? Пожалуйста, не публикуйте скриншоты сообщений об ошибках. Скопируйте и вставьте их в свой вопрос. И почему вы пишете это в сборке? Компилятор может генерировать лучший код. –

+0

Он не распознает инструкцию 'faddq'. Вероятно, ваш компилятор не поддерживает FPU. –

+0

Компилятор clang-602.0.53 – PLNewbie

ответ

5

Я тоже здесь смущен. Что такое faddq, и откуда вы его взяли? Предполагается, что это fadd? Вы не можете использовать два операнда памяти с fadd в любом случае, поэтому код выглядит совершенно неправильно. Если вам интересно, как правильно это сделать, попробуйте выполнить компиляцию с -S и -O2, чтобы вы могли посмотреть на оптимизированный вывод компилятора.

Если вы хотите получить более быструю версию функции, проще всего сделать это в C в любом случае. Предполагая, что массивы не перекрывают друг друга, здесь гораздо быстрее, версия:

// Assuming x and vx do not overlap 
void update1(double *restrict x, const double *restrict vx, unsigned count) { 
    for (unsigned i = 0; i < count; i++) { 
     x[i] += vx[i]; 
    } 
} 

void update(/* ... */) { 
    update1(x, vx, count); 
    update1(y, vy, count); 
    update1(z, vz, count); 
} 

Если вы компилируете с -O3, компилятор генерирует код, который использует addpd, в зависимости от вашей цели компиляции. Это будет лучше, чем все, что вы могли бы написать, используя инструкции FDA.

Эти простые функции - просто добавление массивов в другие массивы - очень просто для компилятора для оптимизации, поэтому, если вы не преподаете язык ассемблера, просто дайте компилятору сделать это за вас.

+0

Большое вам спасибо! – PLNewbie

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