1

witam,

najkrotsza petla opozniajaca, na stronie zero mamy dane 2 komorki w ktorych znajduje sie ilosc cykli procesora do pozarcia.

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

2 Ostatnio edytowany przez tebe (2009-02-03 23:44:39)

to jakieś zadanie, czy zdanie stwierdzające stan?

w G2F mam predefiniowane małe fragmenty kodu realizujące opóźnienia w cyklach CPU, stworzenie uniwersalnej pętli realizującej opóźnienie np. od 2..XX cykli CPU jest nie realne, wie o tym każdy kto zna rozkazy 6502

poniżej tablica NOP z rozkazami realizującymi opóźnienie od 2..36 cykli

 NOP: array [0..34] of string[30] =
 ('nop','cmp byt2',':2 nop','inc byt2','inc byt3','inc byt2\ nop',
  ':4 nop','nop\ pha:pla',':2 inc byt2','cmp byt3\ pha:pla',
  'jsr _rts','inc byt3\ pha:pla','jsr _rts\ nop','jsr _rts\ cmp byt2',
  'jsr _rts\ :2 nop','jsr _rts\ inc byt2','jsr _rts\ inc byt3',
  'jsr _rts\ inc byt2\ nop','jsr _rts\ :4 nop','jsr _rts\ nop\ pha:pla',
  'jsr _rts\ :2 inc byt2','jsr _rts\ cmp byt3\ pha:pla',
  ':2 jsr _rts','jsr _rts\ inc byt3\ pha:pla',':2 jsr _rts\ nop',
  ':2 jsr _rts\ cmp byt2',':2 jsr _rts\ :2 nop',':2 jsr _rts\ inc byt2',
  ':2 jsr _rts\ inc byt3',':2 jsr _rts\ inc byt2\ nop',':2 jsr _rts\ :4 nop',
  ':2 jsr _rts\ nop\ pha:pla',':2 jsr _rts\ :2 inc byt2',
  ':2 jsr _rts\ cmp byt3\ pha:pla',':3 jsr _rts');
*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

3

jak conajmniej dziesięć cykli lub regularnie się powtarzające, to zrzucić to na barki zegara, albo nawet dwóch...

___
Press play on tape...

4

czy "docyklowanie" musi być idealne ?
tzn. czy możliwa jest sytuacja, że pętla opóźniająca wykona się PRAWIE tyle ile wynikałoby to z obliczeń (powiedzmy w granicach błędu określonego marginesem 8 cykli) ?

5

zeby chociaz podany byl zbior oczekiwanych wartosci opoznien - wtedy mozna by cos pokombinowac (w zaleznosci od elementow zbioru).
ale uniwersalnej od 1 cykla w gore ze skokiem co 1 cykl to faktycznie bedzie ciezko. zeby przynajmniej bylo np. minimum 50 cykli, to wtedy mozna by cos wymyslec.

6

Poniższy kod powinien spełniać następujące założenia (jeśli nie ma blędów):
- musi być wywoływany dla opóźnienia wynoszącego co najmniej 47 (39+8) cykli,
- dokładność opóźnienia do 7 cykli niedocyklowanych (za krótkiego opóźninia).

; część przygotowująca

 lda timL
 sec
 sbc #39 ;55
 sta timL
 bcs *+4
 dec timH
; ...



; część właściwa - pętla opóźniająca
 
; ldx #3
xc lsr timH
 ror timL
; dex
; bne xc
; beq xa

 lsr timH *
 ror timL *
 lsr timH *
 ror timL *
 jmp xa

xb nop
 dec timL
 dec timL
 dec timL

xa dec timL
 bne *-2

 dec timH
 bpl xb

7

Można poprawić ten fragment kodu gdzie mamy trzy pary rozkazów:

 lsr timH
 ror timL

na ten fragment, co pozwoli obniżyć granicę tolerancji dla wartości opóźnienia z obecnej o 3 cykle na 44 (39+8-3):

 lda timH
 lsr @
 ror timL
 lsr @
 ror timL
 lsr @
 ror timL
 sta timH

8

Zapomniałem dopisać:

że po podmianie fragmentu kodu z poprzedniego mojego postu, należy jeszcze poprawić wiersz:

SBC #39 na SBC #36 (konsekwencja tamtej zmiany)

oraz że jest to wersja kodu (chodzi mi teraz o wyliczenia cykli) zakładająca że skoki względne wewnątrz kodu pętli nie będą przekraczać granicy strony (co należy sprawdzić przy asemblacji)

jeśli etykieta xa miałaby mieć adres asemblacji $xxfe lub $xxff (tak przynajmniej mi się wydaje) procedura się "zgubi" i nie zadziała prawidłowo

jeśli etykieta xb miałaby mieć adres asemblacji o stronę niższą od adresu asemblacji ostatniego wiersza kodu pętli ( BPL XB) należałoby jeszcze zamienić wiersz kodu SBC #36 na SBC #37 (tak przynajmniej mi się wydaje)

9

nie jest tak zle jak mysalem. procka opozniajaca miala pozerac wielokrotnosc cykli jaki trwa inna procka... po prostu zacma. poradzilem sobie. dzieki.

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

10

i za to wszyscy kochają XXL-a, zdawkowe zdania jakby sklecone w pośpiechu, reszty domyśl się sam albo zostań telepatą, a na końcu odpowiedź na pytanie które zna tylko XXL :P

*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

11

analizowalem jeden programik nie wszystko dobrze rozumialem a poza tym bylo pozno i ciemno ;-)

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

12

Nieaktualne, ale postanowiłem doszlifować procedurkę. Projektowałem ją nie testując poprawności działania w żaden sposób (w istocie jest to z uwagi na subtelność zadania programu, raczej i trudne w praktyce). Nie daję więc najmniejszej gwarancji, że zamieszczany listing wygeneruje w istocie poprawnie działający program.

* generator opóźnienia liczonego w cyklach procesora
* dokładność do 1 cykla
* dopuszczalny zakres żądanego opóźnienia <82,65535>
* komunikacja z programem poprzez ustawienie timH i timL (str.0)


; tablica opóźnień dla końcowych 0-7 cykli
; byt (gdzieś na str.0): operacje r/w

tdlay dta b($4c) ;jmp a
 dta b($05) ;ora b
 dta b($e6) ;inc b
 pha

 dta l(xc)
 dta b(byt)
 dta b(byt)
 pla

 dta h(xc)
 nop
 nop
 nop
 
; część przygotowawcza do umieszczenia w dowolnym miejscu
; po załadowaniu licznika żądanego opóźnienia

 lda timL
 sec
 sbc #36+38
 sta timL
 bcs *+4
 dec timH
; ...

; część właściwa - pętla opóźniająca

 lda timL
 and #7
 lsr @
 tax
 lda tdlay,x ;^1
 sta delay
 lda tdlay+4,x ;^1
 sta delay+1
 lda tdlay+8,x ;^1
 sta delay+2

 bcs *+2 ;^1
delay equ *

 jmp *+3

 
xc lda timH
 lsr @
 ror timL
 lsr @
 ror timL
 lsr @
 ror timL
 sta timH
 jmp xa

xb nop
 dec timL
 dec timL
 dec timL

xa dec timL
 bne *-2 ;^0

 dec timH
 bpl xb ;^2


* ^0: jeśli w wyniku wykonania rozkazu rejestr PC procesora musi przekroczyć stronę pamięci program (pętla opóźniająca) nie może właściwie działać
* ^1: jeśli w wyniku wykonania rozkazu rejestr PC procesora musi przekroczyć stronę pamięci do argumentu rozkazu SBC #36+38 należy dodać za każdym takim przypadkiem 1
* ^2: jeśli w wyniku wykonania rozkazu rejestr PC procesora musi przekroczyć stronę pamięci do argumentu rozkazu SBC #74 należy dodać za każdym wykonaniem tego rozkazu 1 (cykle opóźnienia-(74+n)/2^11)

13

i od razu zgłaszam małą nieścisłość:

jeśli jeden z wierszy programu oznaczony na końcu ;^1 (BCS *+2) zasembluje się pod mało ciekawy adres (problem przekroczenia przez PC w wyniku jego wykonania granicy strony), nie wystarczy, jak to napisałem w komentarzu na końcu, jedynie dodać jeden do argunentu w stosownym, opisanym miejcu, ponieważ nie będziemy mieli gwarancji, że ten dodatkowy cykl zostanie w istocie zużyty (instrukcja skoku warunkowego może się nie wykonać "czynnie" w zależności od żądanej wartości opóźnienia)
dlatego w tym przypadku należy szczególnie zadbać o to, by adres asemblacji zapewnił uniknięcie sytuacji przekraczania przez rejestr PC granicy strony, jeśli oczywiście zależy nam na wygenerowaniu idealnego z postulowanym opóźnienia

14

Mam nadzieję, że w temacie odzywam się po raz ostatni.

Znacznie udało mi się popracić wydajność procedury. Składam przy okazji samokrytykę że tyle wpisów zajęło mi dojście do takiej postaci kodu.

* generator opóźnienia liczonego w cyklach procesora
* dokładność do 1 cykla
* dopuszczalny zakres żądanego opóźnienia <17,65535>
* komunikacja z programem poprzez ustawienie timH i timL (str.0)


; tablica 4x3 'drobnych' ((0,2,4,6)+3) cykli opóźnień
; byt (gdzieś na str.0): operacje r/w

tdlay dta b($4c) ;jmp a
 dta b($05) ;ora b
 dta b($e6) ;inc b
 pha

 dta l(xa)
 dta b(byt)
 dta b(byt)
 pla

 dta h(xa)
 nop
 nop
 nop
 
; część przygotowawcza do umieszczenia w dowolnym miejscu
; po załadowaniu licznika żądanego opóźnienia

 lda timL
 sec
 sbc #9
 sta timL
 bcs *+4
 dec timH

 and #7
 lsr @
 php
 tax
 lda tdlay,x ;^1
 sta delay
 lda tdlay+4,x ;^1
 sta delay+1
 lda tdlay+8,x ;^1
 sta delay+2
 lda timH
 lsr @
 ror timL
 lsr @
 ror timL
 lsr @
 ror timL
 pha

;...


; tuż przed wywołaniem pętli opóźniającej
; znacznik C i rejestr X muszą pozostać niezmienione do momentu wywołania pętli

 pla
 tax
 plp

;...

; część właściwa - pętla opóźniająca

 bcs *+2 ;^1
delay equ *

 jmp *+3
 
xa dec timL
 bne *-2 ;^0

 dex
 bmi xx ;^1
 dec timL
 dec timL
 bne xa ! ;^0

xx equ * koniec pętli

* ^0: jeśli w wyniku wykonania rozkazu rejestr PC procesora musi przekroczyć stronę pamięci program (pętla opóźniająca) nie może właściwie działać (opóźnienie znacząco większe od oczekiwanego)
* ^1: jeśli w wyniku wykonania rozkazu przekroczona miałaby zostać granica strony pamięci do argumentu rozkazu SBC #9 należy dodać za każdym takim przypadkiem 1 (zmniejszy się w ten sposób zakres możliwego do wygenerowania opóźnienia na <17+n;65535>)