/* Лабораторная работа 14 Объединение команд для их параллельного выполнения (оптимизация уровня команд) */ #include #include void NullProc(void){} void ExTime(void (*PP)(void)) { long far* pTime = (long*)0x46C; //счетчик тиков long Time0, Time1, Time2, i; void (*NP)(void); NP = NullProc; Time0 = *pTime; for (i = 1; i<1000000L; i++) { NP(); NP(); NP(); NP(); NP(); NP(); NP(); NP(); NP(); NP(); } Time1 = *pTime; for (i = 1; i<1000000L; i++) { PP(); PP(); PP(); PP(); PP(); PP(); PP(); PP(); PP(); PP(); } Time2 = *pTime; Time2 = (((Time2 - Time1) - (Time1 - Time0))*(6553500L/1193180L)); printf("%ld нс\n",Time2); } void P1(void) //регистровые зависимости имеются { asm{ mov ax,bx mov dx,ax stc adc bx,cx stc sbb dx,ax add ax,bx mov cx,ax sub dx,bx mov bx,dx } } void P2(void) //регистровые зависимости устранены { asm{ } } void P3(void) //другие причины неспаренности { asm{ mov cl,3 //непосредственный операнд inc bx mov cl,3 dec bx mov cl,3 inc bx mov cl,3 dec bx inc bx //команды сдвига с cl в качестве счетчика ror ax,cl dec bx rol ax,cl inc dx //команды с префиксами м. б. в U - конвейере mov ax,ds:[bx] mov ax,ss:[bx] mov ax,es:[bx] mov ax,cs:[bx] mov cl,3 mov cl,3 mov cl,3 dec dx inc dx //команды сдвига м. б. в U - конвейере ror ax,1 rol ax,1 dec dx } } void P4(void) //причины неспаренности устранены { asm{ } } void main(void) { clrscr(); printf("Program1 - регистровые зависимости имеются\n"); ExTime(P1); printf("Program2 - регистровые зависимости устранены\n"); ExTime(P2); printf("Program3 - другие причины неспаренности\n"); ExTime(P3); printf("Program4 - причины неспаренности устранены\n"); ExTime(P4); getch(); } //Задание // 1. Устраните причины неспаренности команд. // 2. Определите и объясните время выполнения фрагментов программ. // /* ПРАВИЛА ОБЪЕДИНЕНИЯ КОМАНД Процессор Pentium может выполнять одну или две команды в каждом такте. Для выполнения в процессоре одновременно двух команд они должны удовлетворять следующим условиям: -обе команды в паре обязаны быть <простыми> в смысле, определенном ниже; -между ними не должно быть регистровых зависимостей типа чтение- после- записи или запись-после-записи (read-after-write or write-after-wnte) , -ни одна из команд не может содержать смещение (displacement) и непосредственный операнд; -команды с префиксами (за исключением OF в командах перехода JCC) могут встречаться только в U-конвейере. Под простыми командами понимаются команды, управление выполнением которых осуществляется аппаратно, без использования микрокоманд, и которые реализуются за один такт. Исключением являются команды ALU mem, reg и ALU reg, mem, требующие трех и двух тактов для выполнения соответственно. Специальные аппаратные средства используются для их выполнения как простых команд. Следующие целочисленные команды рассматриваются в качестве простых и могут быть спарены: -mov reg, reg/mem/imnl -mov mem, reg/imm (команды передачи) ; -alu reg, reg/mero/imm (команды арифметических - alu meln , reg/ imm и логических операций) ; - inc reg/mem (команды инкремента, - dec reg/mem (декремента) ; -push reg/mem (команды обращения - pop reg (к стековой памяти) ; -lea reg,mem (команды загрузки сегментных регистров) ; -jmp/call/jcc near (команды передачи управления) ; -nор (пустая команда) . Команды безусловной и условной передач управления могут о6ьединяться в пары, если они встречаются в качестве вторых команд в паре. Они не могут быть спарены со следующей последовательной командой. Также команды SHIFT/ROT со сдвигом на один разряд и SHIFT на произвольное число разрядов могут спариваться только как первые ( команды в паре). Регистровые зависимости Регистровые зависимости, запрещающие спаривание команд, включают неявные зависимости через регистры или флаги, не указанные в команде. Все виды зависимостей по данным могут быть классифицированы по типу ассоциаций: RAR - "чтение после чтения", WAR - "запись после чтения" и WAW - "запись после записи", RAW - "чтение после записи". Некоторые из зависимостей по данным могут быть устранены. RAR, по сути дела, соответствует отсутствию зависимостей, поскольку в данном случае порядок выполнения команд не имеет значения. Действительной зависимостью является только "чтение после записи" (RAW), так как необходимо прочитать предварительно записанные новые данные, а не старые. Лишние зависимости по данным появляются в результате "записи после чтения" (WAR) и "записи после записи" (WAW). Зависимость WAR состоит в том, что команда должна записать новое значение в ячейку памяти или регистр, из которых должно быть произведено чтение. Лишние зависимости появляются по нескольким причинам: не оптимизированный программный код, ограничение количества регистров, стремление к экономии памяти, наличие программных циклов. */