26

A co jest w F.I na stosie? Bo może warto by zrobić tak:
- jeśli I=1 to IRQ na pewno nie przerwie IRQ, więc jedynymi opcjami są NMI i BRK.
- jeśli B=0 to było BRK więc można od razu wykonać nie uruchamiając detekcji źródeł IRQ.
Widzę jeszcze jeden problem.
Załóżmy, że wykonujemy BRK i CPU wszedł w obsługę przerwania, sprawdza kolejne źródła i w tym momencie przychodzi jakieś IRQ. Zapala się flaga w IRQEN/PxCTL/PDVREG czy gdzie tam i nagle CPU zamiast zrealizować BRK zboczy nam w któreś IRQ. Obsłuży przyjęcie i nie zwracając na stan B na stosie wyjdzie z przerwania. W tym momencie jest po ptakach, bo drugi raz w przerwanie nie wejdziemy (analogicznie jest z NMI, ale to tylko dygresja) :/ Może w OS po prostu źle zrobiono detekcję i BRK powinno mieć najwyższy priorytet?

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje

27

ja widze jeden powazny blad. BRK moze sie "zgubic" jesli wystapi razem z IRQ. wydaje mi sie ze mozna temu zaradzic jesli BRK bedzie wykonywane z ustawionym I czyli tak jak w poprzednim poscie napisalem. moznaby wtedy bezpiecznie uzywac BRK w kodzie. no ale wlasnie nie przy systemowej procedurze rozpoznawania przerwania IRQ, ma sporo bledow. BRK musi miec bardzo wysoki priorytet, teraz ma najnizszy chyba.

http://atari.pl/hsc/ad.php?i=1.

28

oh, juz widze nowy wątek z cyklu 'atari tak chcialo tylko nie zrobilo bo czekalo na xxla'

"Was powinny uzbrojone służby wyciągać z domów do punktów szczepień, a potem zamykać do pi* za rozpowszechnianie zagrożenia epidemicznego" - Epi 2021
"Powinno się pałować tylko tych co tego nie rozumieją. No i nie szmatki i nie chirurgiczne tylko min FFP3, to by miało jakiś sens. U mnie we firmie, to jak przychodzi bezmaskowiec, to stoi w deszczu przed firmą" - Pin 2021

29

mono napisał/a:

ASL ładne, ale to i tak nie załatwia całkowicie sprawy - trzeba by poprawić w ROMie procedurę NMI, bo tam nie mamy już takiego fajnego wektora VIMNMI (z NMIVEC możemy wszystko). Inaczej problem będzie z pierwszym IRQ wykonywanym po NMI.

ASL rozwiązuje problem: IRQ i NMI występują kolejno i obsługują to samo NMI. Trzeba dodać STA NMIRES w DLI oraz sprawdzenie b6 NMIST w VBLKI - czy na pewno mamy obsługiwać VBLKI, czy może IRQ już się tym zajmuje - czyli inne punkty wejścia do VBLKI z NMI, niż IRQ. Da się to zrobić bez wymiany ROMu.

Zakładam, że w obsłudze NMI nie robimy BRK, przynajmniej nie dopóki nie zrobimy STA NMIRES. ;)

xxl napisał/a:

a takie cos zalatwi sprawe?
SEI
BRK
.byte cokolwiek
CLI
? (pod warunkiem ze wlasna procka IRQ bedzie sprawdzac B wczesniej)

Ten SEI nic nie daje. Natomiast procka IRQ powinna sprawdzać BRK najpierw, a sprawdza na końcu.

Jeszcze trzeba obsłużyć BRK skaczące pod wektor NMI. W NMI trzeba obsłużyć kolejno oba te przerwania.

https://www.youtube.com/watch?v=jofNR_WkoCE

30 Ostatnio edytowany przez xxl (2014-02-12 14:25:58)

> Ten SEI nic nie daje.

tego nie rozumiem, jesli cpu nie reaguje na IRQ natomiast reaguje na BRK to moze wystapic sytuacja ze IRQ zamaskuje BRK? (chodzi o prawidlowe ustawienie bitu B w rejestrze stanu odlozonym na stosie)

http://atari.pl/hsc/ad.php?i=1.

31

mono napisał/a:

A nie wynika to z tego, że przerwanie jest przyjmowane po zakończeniu bieżącego cyklu rozkazowego więc mając np LDA NMIST i NMI, które wystąpi po prefetchu a przed 4 cyklem rozkazu w A dostaniemy info o NMI?

Ma to sens. Z głównego wątku zapalony status NMI jest widoczny przez dokładnie jeden cykl.

Natomiast ANTIC sygnalizuje 6502 NMI przez dokładnie 2 cykle, więc 6502 musi tę informację buforować.

https://www.youtube.com/watch?v=jofNR_WkoCE

32

xxl napisał/a:

> Ten SEI nic nie daje.

tego nie rozumiem, jesli cpu nie reaguje na IRQ natomiast reaguje na BRK to moze wystapic sytuacja ze IRQ zamaskuje BRK?

Chyba jesteśmy zgodni co do tego, że procka powinna sprawdzać BRK na początku.

Jeśli tego nie robi (a nie robi), to robiąc BRK skaczemy do ogólnej procedury IRQ niezależnie od znacznika I. I ta procedura sprawdza źródła przerwania IRQ i może np. zawołać przerwanie klawiatury.

https://www.youtube.com/watch?v=jofNR_WkoCE

33 Ostatnio edytowany przez mono (2014-02-12 14:40:30)

NMI jest wymuszane zboczem, więc nie ma szans wejść w to samo NMI po raz drugi. Jeśli chcielibyśmy obsługiwać BRK też i na NMI, to trzeba by odłożyć na stos powrót do obsługi BRK i kontynuować NMI.
Można jeszcze skorzystać z patentów xxla na programowe wywołanie IRQ i spokojnie wyjść z NMI.

Edit: "ASL..." załatwia sprawę, ale nie CAŁKOWICIE, bo jak sam się zgodziłeś potrzebne jest jeszzcze STA NMIRES na DLI :/ albo zmiana ROMu z główną procedurą obsługi NMI (tak, żeby użytkownik nie musiał już robić nic z NMIRES w swoim kodzie).

Edit 2: "Wejść w to samo NMI po raz drugi" - chodzi o podtrzymanie wymuszenia na linii NMI. IRQ jest wymuszane poziomem, więc przerwanie może być odroczone - wystarczy tylko nie obsługiwać go w IRQST (lub innych). W NMI to nie wystarczy, bo po powrocie przez RTI wymuszenia już nie ma.

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje

34

tu jest pelna zgoda. procka IRQ MUSI sprawdzac BRK na poczatku!

ja mowie o czyms innym:

problem jest taki ze jesli wystapi przerwanie IRQ i przerwanie BRK JEDNOCZESNIE to bit B jest ustawiany nieprawidlowo - procka rozpoznawania przerwania nawet gdyby sprawdzila przerwanie na poczatku to go nie wykryje.
dlatego uzywanie BRK na atari mija sie z celem bo moze zostac "pominiete" niezaleznie od tego czy mamy swoja procke rozpoznawania przerwania z detekcja BRK na poczatku czy nie. chodzi mi o to, ze jestli BRK zastosujemy w taki sposob jak wyzej to jest mozliwosc bezpiecznego uzywania BRK (oczywiscie caly czas wymaga to sprawdzania na poczatku przerwania BRK w procedurze rozpoznawania IRQ)

http://atari.pl/hsc/ad.php?i=1.

35

W atariki stoi: "Wystąpienie przerwania podczas wykonywania rozkazu BRK spowoduje, że zostanie on zignorowany". Tylko co to znaczy? Czy to, że błąd leży w procedurze obsługi IRQ, czy że jest to własność processora?

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje

36

nie wiem, wiem ze Fox wie :-) dlatego staram sie ustalic jedna bardzo dla mne istotna rzecz:

czy bit B w rejestrze stanu podczas jednoczesnego wystapienia IRQ i BRK jest ustawiany tak jak podczas wystapienia IRQ czy tak jak podczas wystapienia BRK.

http://atari.pl/hsc/ad.php?i=1.

37

mono napisał/a:

W atariki stoi: "Wystąpienie przerwania podczas wykonywania rozkazu BRK spowoduje, że zostanie on zignorowany". Tylko co to znaczy? Czy to, że błąd leży w procedurze obsługi IRQ, czy że jest to własność processora?

Jeden błąd leży w procedurze obsługi IRQ (powinna sprawdzać BRK najpierw), a drugi w procesorze (BRK razem z NMI wykona NMI, a nie wykona IRQ).

xxl napisał/a:

czy bit B w rejestrze stanu podczas jednoczesnego wystapienia IRQ i BRK jest ustawiany tak jak podczas wystapienia IRQ czy tak jak podczas wystapienia BRK.

Trochę wcześniej odpowiedziałeś na swoje pytanie:

xxl napisał/a:

problem jest taki ze jesli wystapi przerwanie IRQ i przerwanie BRK JEDNOCZESNIE to bit B jest ustawiany nieprawidlowo

Ale skoro pytasz, to chyba nie jesteś pewien. ;) I mi się wydaje, że jest odwrotnie: tj. bit B z BRK się nie gubi, nawet jeśli procek skoczy pod NMI.

https://www.youtube.com/watch?v=jofNR_WkoCE

38

@Fox @xxl: Dzięki.

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje

39 Ostatnio edytowany przez xxl (2014-02-12 15:24:46)

tak, nie jestem pewny. czyli przy jednoczesnym wystapieniu IRQ i BRK bit B jest ustawiany jak podczas wystapienia BRK tak?


> BRK razem z NMI wykona NMI, a nie wykona IRQ

wydawalo mi sie ze to jednak IRQ sie wykona a nie NMI...


kurde... musze to jeszcze raz wszystko przeczytac.

http://atari.pl/hsc/ad.php?i=1.

40

Spoko, tych dwóch rzeczy nie jestem pewien - najlepiej zrobić eksperymenty.

https://www.youtube.com/watch?v=jofNR_WkoCE

41

xxl doczytał Altirra Hardware Reference Manual, który twierdzi, że BRK może wejść w procedurę NMI zamiast IRQ, ale B zawsze ustawi.

W związku z tym proponuję poniższe:

Procedura obsługi IRQ:
1. zawsze sprawdza (ASL NMIST) i obsługuje NMI
2. zawsze sprawdza i obsługuje BRK
3. sprawdza i obsługuje IRQ (*)

Procedura obsługi NMI:
1. zawsze sprawdza i obsługuje NMI
2. zawsze sprawdza i obsługuje BRK

Kolejność:
- najpilniejsze jest DLI (VBLKI też bym zrobił najpierw)
- potem IRQ
- na końcu BRK, bo z tym się raczej nie spieszy

(*) można rozwiązać na trzy sposoby:
a. jeśli obsłużyliśmy NMI lub BRK, to nie sprawdzamy IRQ
b. jeśli obsłużyliśmy NMI lub BRK, przed sprawdzeniem IRQ sprawdzamy znacznik I na stosie
c. zawsze sprawdzamy znacznik I, potem IRQ

https://www.youtube.com/watch?v=jofNR_WkoCE

42

Przy takim zdefiniowaniu priorytetów używanie BRK mija się z celem, bo opóźnienia obsługi BRK w pesymistycznym przypadku będą rzędu 250 cykli (przejdzie cała detekcja IRQ zanim zostanie wywołana obsługa BRK). Lepiej użyć JSR/JMP i tablicy skoków. Pewnie dlatego OSowcy zrezygnowali z patchowania i zostawili PLA/RTI (co chyba najsensowniej w takim stanie rzeczy zrobić).
Pytanie dlaczego w ogóle zostawili wektor (i to dopiero w serii XL/XE) skoro wiedzieli, że to nie działa? Może planowali użyć CPU, który wszystko realizuje poprawnie? ;]
Wychodzi na to, że faktycznie sens używania BRK to tylko laboratoryjny debug.

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje

43

Jak już poprawiamy OS, możemy też zoptymalizować tę koszmarnie wolną procedurę rozpoznawania IRQ. Na pewno da się ją zrobić szybciej, niż w 250 cykli. Ale do szybkości tablicy skoków daleko.

https://www.youtube.com/watch?v=jofNR_WkoCE

44 Ostatnio edytowany przez mono (2014-02-13 19:31:16)

Tak, ale niestety patch spowoduje też spory wzrost opóźnień (dla DLI ok 20 cykli, dla VBLK ok 35, dla IRQ ok 25). W przypadku DLI chyba lepiej nie wprowadzać takich delayów? 7 cykli przy samym NMI patch w sumie może byłoby i akceptowalne...
Zrobiłem małą przymiarkę dla wektoryzowania przez NMIVEC i IRQVEC:

nmi:
  pha             ;3
  lda #>brkopcode ;2
  pha             ;3
  lda #<brkopcode ;2
  pha             ;3
  php             ;3

  asl NMIST
  scc
  jmp (VDSLST)

  pha
  txa
  pha
  tya
  pha
  cld
  jmp (VVBLKI)

irq:
  pha             ;3
  lda #>brkopcode ;2
  pha             ;3
  lda #<brkopcode ;2
  pha             ;3
  php             ;3

  asl NMIST
  scc
  jmp (VDSLST)

  cld
  smi
  jmp (VIMIRQ)

  pha
  txa
  pha
  tya
  pha
  jmp (VVBLKI)

brkopcode:
  txa
  pha
  tsx
  lda $103,x
  and #$10
  beq ?ret
  pla
  tax
  jmp (VBREAK)

?ret:
  pla
  tax
  pla
  rti

oraz dla VDLST, VVBLKI i VIMIRQ:

vdslst:
  sta NMIRES      ;4
  pha             ;3
  lda #>brkopcode ;2
  pha             ;3
  lda #<brkopcode ;2
  pha             ;3
  php             ;3
  ...             ;-------20 cykli

vvblki:
  pla             ;4
  tay             ;2
  pla             ;4
  tax             ;2
  lda #>brkopcode ;2
  pha             ;3
  lda #<brkopcode ;2
  pha             ;3
  php             ;3
  txa             ;2
  pha             ;3
  tya             ;2
  pha             ;3
  ...             ;-------35 cykli

vimirq:
  bit NMIST       ;4
  spl             ;23
  jmp (VDSLST)    ;5 -----11 cykli

  svc             ;23
  jmp (VVBLKI)    ;5 -----14 cykli

  pha             ;3
  lda #>brkopcode ;2
  pha             ;3
  lda #<brkopcode ;2
  pha             ;3
  php             ;3
  ...             ;-------26 cykli

Na razie teoretyzuję, bo nie uruchamiałem tego. W tym przypadku IRQ w obydwu przypadkach uruchomi 2x obsługę BRK kiedy nie wejdzie mu w drogę ani NMI, ani IRQ.

Edit: 2x wywołanie BRK akurat da się obejść realizując zamiast PHP po prostu LDA #%00100100+PHA.

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje

45

off

z Twojej stopki: "Sparta DOSn't!" (c) by xxl"

cytuj mnie wlasciwie: "xBios do, Sparta DOSn't"

:D

http://atari.pl/hsc/ad.php?i=1.

46 Ostatnio edytowany przez Fox (2014-02-14 22:45:42)

Ja teoretyzuję tak:

    org    {nop}<<8    ; albo inaczej
nmi
    jsr    handle_nmi
    sta    $28c
    pla
    pha
    and    #$10
    beq    no_brk
    lda    $28c
    jmp    ($206)
no_brk
    lda    $28c
no_nmi
    rti

handle_nmi
    php
    asl    ^4f
    jcs    ($200)
    bpl    no_nmi
    cld
    pha
    txa:pha
    tya:pha
    jmp    ($222)

edit: literówka

https://www.youtube.com/watch?v=jofNR_WkoCE

47 Ostatnio edytowany przez mono (2014-02-14 11:06:01)

Piękny kawałek kodu ("Dowód jest elegancki kiedy da się go zapisać na marginesie" haha). Szacun!

Edit: Zastanawiam się czy NEWIOP nie spowoduje, że w pewnych warunkach procedura nie będzie reentrant, ale jeśli przepiszemy IRQMAIN to można go nie używać, albo zapewnić żeby była tam zawsze zawartość .A sprzed wywołania.
Podoba mi się JSR+NOP zamiast odkładania dokładnego powrotu na stos - zgrabne.

hex, code and ror'n'rol
niewiedza buduje, wiedza rujnuje