185 lines
7.8 KiB
C++
Executable File
185 lines
7.8 KiB
C++
Executable File
/* Лабораторная работа 14
|
||
Объединение команд для их параллельного выполнения
|
||
(оптимизация уровня команд)
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <conio.h>
|
||
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 состоит в
|
||
том, что команда должна записать новое значение в ячейку памяти или регистр,
|
||
из которых должно быть произведено чтение. Лишние зависимости появляются
|
||
по нескольким причинам: не оптимизированный программный код, ограничение
|
||
количества регистров, стремление к экономии памяти, наличие программных
|
||
циклов.
|
||
|
||
*/
|