Rimio a scris:
Nu am mai programat pentru procesoare ARM (sunt chichite de care trebuie sa tin cont? optimizari?)
Programarea pe ARM este in mare la fel ca pe x86, avand totusi cateva chichite :
- Procesorul poate rula atat in big endian, cat si litle endian, endianess-ul fiind stabilit de OS. Deci trebuie sa cam stii dinainte ce endian foloseste, sau sa scri cod care merge pe ambele reprezentari...
- Citirea si scrierea in memorie trebuie sa fie aliniata la tipul de date folosit. Deci daca citesti din memorie un WORD, atunci acel word trebuie sa se gaseasca la o adresa multiplu de 2, pentru DWORD, la multiplu de 4. Daca nu faci asta, atunci rezultatul va fi nedefinit.
Ca optimizari specifice pentru ARM ar fi bine de stiut urmatoarele:
1. NU ARE FPU!!! ( operatiile in virgula mobila sunt emulate ) Trebuie sa folosesti
fixed point pentru viteza...
2. NU ARE INSTRUCTIUNE DE IMPARTIRE!!! ( div-ul este emulat ) Evita div-urile si mod-urile acolo unde poti...
3. Orice instructiune se poate executa conditionat. Deci daca ai codul urmator:
Cod sursă:
if (a>b) a -= b; else b -= a;
, atunci acel if nu va genera instructiune de branch deoarece a-=b si b-=a pot fi conditionate in functie de a>b. Codul ASM ar fi de genu:
Cod sursă:
CMP r1, r2
SUBGT r1, r1, r2
SUBLT r2, r2, r1
Daca ai avea in blocurile if si else mai mult cod, atunci se vor folosi branch-uri...
4. Aproape toate instructiunile ( in afara de inmultiri ) pot aplica o shiftare sau rotatie cu o constanta celui de-al doilea operand. Deci urmatoarele doua expresii sunt echivalente din punctul de vedere al performantei si numarului de instructiuni:
Cod sursă:
rezultat = a + b; // ADD R1, R2, R3
rezultat = a + (b << 16); // ADD R1, R2, R3, LSL#16
5. Exista instructiune de Multiply and Accumulate, asta inseamna ca urmatoarele doua expresii sunt echivalente din punctul de vedere al performantei si numarului de instructiuni:
Cod sursă:
rezultat = a * b; // SMULL R1, R2, R3, R4
rezultat = a * b + c; // SMLAL R1, R2, R3, R4
6. Toate instructiunile aritmetice lucreaza numai cu registrii, deci daca folosesti constante, acestea vor fi incarcate din memorie ( deci o instructiune in plus ), sau in unele cazuri favorabile vor fi generate folsind shiftarile...
Urmatoarele patru sfaturi sunt valabile cam pentru orice platforma :
7. ARM-ul are 16 registrii din care doar 12 de uz general, iar accesul la memorie aduce penalizari, deci trebuie sa incerci sa folosesti cat mai putine variabile, astfel incat cele care sunt mai des folosite sa incapa in registrii...
8. Unde este posibil foloseste for-uri cu decrementare :
Cod sursă:
for(i = 0; i 0)
10. Foloseste loop unrolling acolo unde este posibil...
Mai sunt si alte optimizari specifice, dar pentru alea ar cam trebui sa scri ASM... Daca te bagi la asa ceva, nu strica sa arunci o privire prin
cartea de referinta pentru programarea ARM.
Pentru celelalte intrebari nu stiu ce sa raspund ( dar totusi nu m-as avanta sa dezvolt pentru ceva ce inca nu a aparut si nici nu se stie ce succes va avea).