Rozkazy nieefektywne i nielegalne
W architekturze procesora MERY-400 rozróżniane są dwa szczególne przypadki rozkazów, które mimo, że zostaną pobrane z miejsca programu wskazanego licznikiem rozkazów, to ich wykonanie będzie zaniechane. Decyzja taka podejmowana jest bardzo wcześnie, bo już na etapie dekodowanie rozkazu, co w niektórych przypadkach staje się jednocześnie sprytnym skrótem do realizacji jego treści.
Warunki wystąpienia
Wszystkie rozkazy, dla których nie zostanie podjęta faza wykonania nazywane są rozkazami nieefektywnymi. Sygnał NEF na pakiecie P-D ma dla takich przypadków wartość "1". Szczególną grupę rozkazów nieefektywnych stanowią rozkazy nielegalne, czyli takie, które są niepoprawne, lub kontekst, w jakim następuje próba ich wykonania jest niewłaściwy. Dla takich rozkazów sygnał XI na pakiecie P-D przyjmuje wartość "1". Zaliczają się do nich:
- Rozkazy o kodach binarnych, które nie reprezentują żadnego z rozkazów na liście rozkazów. Są to:
- Wszystkie rozkazy, które w zapisie binarnym na dwóch najstarszych bitach mają wartość "0".
- Niektóre rozkazy o kodach binarnych zaliczających się do grupy "C". W tej grupie istnieją również rozkazy znajdujące się na liście rozkazów, ale nie obejmuje ona wszystkich możliwych kombinacji
- Niektóre rozkazy o kodach binarnych zaliczających się do grupy "S", z przyczyn jak wyżej.
- Rozkazy przeznaczone do wykonaywania wyłącznie w kontekście systemu operacyjnego (Q=0), jeśli próbę ich wywołania podjęto z programu użytkowego:
- Wszystkie rozkazy istniejące w grupie "S": HLT, MCL, SIT, SIL, SIU, CIT, GIU, LIP, GIL, także rozkazy dodane w procesorze MX-16: CRON, SINT, SIND.
- Niektóre rozkazy z grupy "B/N": MB, IM, KI, FI, SP.
- Rozkazy IN oraz OU, jeśli na pakiecie P-D zwora 1-2-3 jest w pozycji 1-3.
- Rozkaz premodyfikacji MD, jeśli został wywołany po raz czwarty
Pozostałe rozkazy nieefektywne to:
- Dowolny rozkaz, jeśli poprzedni rozkaz ustawił flagę przeskoku (P=1).
- Rozkazy skoków warunkowych, jeśli nie są spełnione warunki wymagane do podjęcia danego skoku (np. nie jest ustawiona flaga zera "Z" w trakcie dekodowania skoku JZ).
Obsługa
W przypadku napotkania rozkazu nieefektywnego zawartość licznika rozkazów jest zwiększana o 1, jak w przypadku wszystkich innych rozkazów. Dzieje się to już w fazie pobrania rozkazu. Następnie procesor kończy bieżący cykl rozkazowy, wykonując jednak kilka dodatkowych czynności "porządkowych":
- Jeśli rozkaz był nielegalny i nie był ustawiony wskaźnik przeskoku P (XI & ~P), zapalane jest przerwanie 6 (nieprawidłowy rozkaz).
- Dla nieefektywnych rozkazów dwusłowowych może nastąpić kolejne zwiększenie zawartości licznika rozkazów o 1, tak, aby ominąć również argument natychmiastowy rozkazu, znajdujący się w drugim słowie. Dzieje się to w dwóch przypadkach:
- Jeśli rozkaz nie był nielegalny (WMI & ~XI) - jest to przypadek legalnych rozkazów skoku warunkowego z argumentem w drugim słowie, np JZ 0x1234
- Lub jeśli ustawiony był wskaźnik przeskoku P (WMI & P) - jest to przypadek przeskoku przez dowolny rozkaz dwusłowowy
- Bezwarunkowo - wyzerowanie wewnętrznych wskaźników: B-modyfikacji (WBI), premodyfikacji (WPI), rozkazu dwusłowowego (WMI), przeskoku (P), oraz licznika premodyfikacji (MC).
Po tej operacji rozpoczynany jest kolejny cykl rozkazowy.
Konsekwencje praktyczne
To, jakie rozkazy mogą być nieefektywne i w jaki sposób są obsługiwane, ma kilka nieoczywistych konsekwencji praktycznych, o których warto pamiętać pisząc oprogramowanie MERY-400.
Skoki warunkowe
Obsługa niepodejmowanych skoków warunkowych już na etapie dekodowania jest ciekawym trikiem powodującym, że rozkazy te kończone są bardzo wcześnie, co skraca dla nich czas cyklu do niezbędnego minimum. Taki rozkaz nie tylko nie przejdzie do fazy wykonania, ale nie będą dla niego również obliczane argumenty. To ma kolejną ciekawą konsekwencję: jego argumentem może być adres nie objęty żadnym ze skonfigurowanych obszarów pamięci, a rozkaz mimo to nie zakończy się błędem dostępu do pamięci.
Rozkazy wejścia/wyjścia
W przypadku rozkazów IN i OU należy zwrócić uwagę na dwie kwestie.
Wieloargumentowość rozkazów IN i OU
Rozkazy IN i OU wymagają czterech dodatkowych argumentów umieszczonych bezpośrednio za rozkazem. Są one adresami, pod jeden z których nastąpi skok w zależności od sposobu zakończenia operacji wejścia/wyjścia. Ponieważ obsługa rozkazów nieefektywnych nie obejmuje scenariusza z czterema dodatkowymi argumentami, to należy zapewnić, aby rozkazy IN lub OU nie stały się w trakcie wykonywania programu nieefektywne. Zaniedbanie tego wymogu może skutkować tym, że argument zostanie potraktowany jako rozkaz i wykonany, a to może mieć nieprzewidziane konsekwencje.
W praktyce sprowadza się to do dwóch ograniczeń:
- Bezpośrednio przed rozkazami IN i OU nie należy używać rozkazów ustawiających wskaźnik przeskoku P
- Nie należy używać rozkazów IN i OU w programie użytkowym, jeśli komputer, na którym jest on uruchamiany traktuje takie rozkazy jako nielegalne, a system operacyjny maszyny nie obsługuje takiej sytuacji wyjątkowej. Należy tu jednak zauważyć, że w standardowym wykonaniu pakietu P-D rozkazy IN i OU są legalne w trybie użytkownika.
Nielegalność rozkazów IN i OU w trybie użytkownika
Obsługa nielegalności rozkazów IN i OU w trybie użytkownika niesie ze sobą jeszcze jedną pułapkę. Jeśli taki rozkaz będzie dwusłowowy, to, ponieważ jest nielegalny, nie zostanie dla niego wykonane dodatkowe zwiększenie licznika rozkazów o 1. W konsekwencji kolejnym miejscem w pamięci, z którego zostanie pobrany rozkaz programu, będzie argument rozkazu IN/OU. Rezultat, podobnie jak wyżej, jest trudny do przewidzenia.
Rozkazy rozgałęzień
Wszystkie rozkazy rozgałęzień: BB, BM, BS, BC, BN, BLC, BRC, IB, TRB mają tę cechę, że przypadek pominięcia następnego rozkazu obarczony jest dodatkowym wydatkiem czasowym (~1.5us) związanym z koniecznością pobrania tego rozkazu z pamięci (mimo, iż nie zostanie on i tak wykonany). Może to mieć zauważalne konsekwencje wydajnościowe w ciasnych pętlach używających rozgałęzień do określenia przypadku wyjścia z pętli. Cecha ta dotyczy również innych rozkazów ustawiających flagę "P": IS, GIU i GIL, ale w ich przypadku kwestie wydajnościowe nie będą grały tak istotnej roli.