soyle cok uzun cevap gerektirmeyen bi tip ne atilabilir diye dusundum ve su geldi aklima: adim adim optimizasyon ornegi
mesela elinizde yapmaniz gereken matematiksel bi islem var. yani bi fonksiyon. iki arguman alip bi sonuc veriyo olsun mesela.
f(a,b) = 2sin a + ab + bcosa
gibi bisey.
bunu hesaplamak icin nasil bi kod yazmali. hemen dikkatimizi ceken sin, cos ve carpma islemleri var ki bunlarin c64 ile kolay olmayacagini biliyoruz. mesela sinus'u ele alalim
g(a)= sin a
aslinda bu da bi fonksiyon ve tek arguman aliyor.
1.KURAL: c64'te karsiniza tek arguman alan bi fonksiyon siktiginda hemen TABLO yapin.
tabi bu argumanin araligina da bagli mesela x bir bayt ise (mesela fixed point olarak -1/128, +1/127 araligindaysa) hemen butun x degerleri icin sinx hesaplanip bi tabloya konacak ve oradan okunacak yani g(x) codu
ldx a
lda gSinTable,x
boylece 7-8 cycle icinde sin hesapladik
Ayni seyi cos a icinde tablo hazirlayarak tekrarlayacagimizi soylememe gerek yok herhalde
CARPMA:
bunu anlatmasi uzun surer. birkac degisik method var ama bunlar su an benim amacim acisindan onemsiz. diyelim ki bi sekilde bu iki sayiyi carpan bi rutin yazdiniz. aslinda carpma islemi de bi fonksiyon. iki arguman aliyor
h(a,b) = a * b
2.KURAL: c64'te karsiniza iki arguman alan fonksiyon cikarsa input argumanlarinin araligina (alabilecekleri farkli deger sayisina) bakin. Eger bu araliklarin butun kombinasyonlari kadar bayti harcamayi goze alabilecekseniz tablo yapin. mesela a ve b $40 farkli deger alabiliyorsa. ikisi toplam $1000 farkli deger alabilir. boyle bi bellegi harcamayi goze alabiliyorsaniz (demo kodluyorsaniz almalisiniz) tablo hazirlayin. bellekte
gTablo:
h(0,1)
h(0,2)
...
h(0, 63)
h(1,0)
h(1,1)
...
h(1,63)
...
...
...
h(63, 62)
h(63, 63)
seklinde bi tabloyu hazirladiktan sonra ikinci bi tablo daha hazirlayin
gTabloReadLo:
$00, $40, $80, $c0
$00, $40, $80, $c0
...
$00, $40, $80, $c0
(16 satir)
gTabloReadHi:
gTablo_hi + $00, gTablo_hi + $00, gTablo_hi + $00, gTablo_hi + $00
gTablo_hi + $01, gTablo_hi + $01, gTablo_hi + $01, gTablo_hi + $01
gTablo_hi + $02, gTablo_hi + $02, gTablo_hi + $02, gTablo_hi + $02
...
gTablo_hi + $0f, gTablo_hi + $0f, gTablo_hi + $0f, gTablo_hi + $0f
ve son olarak code:
ldx a
lda gTabloReadLo,a
sta aReader + 1
lda gTabloReadHi,a
sta aReader + 2
ldx b
aReader:
lda $0000,x
boylece 22-24 cycle da carpma yapilabilir. Aslinda 16 cycle da baska methodlarla carpma yapmak mumkun ama geciniz su an o onemli degil.
boylece son kod soyle bisey olur en bastaki fonksiyon icin
;; f(a,b) = 2sin a + ab + bcosa
ldx a
lda gSinTable, x
asl
sta lTemp1
lda gCosTable,x
sta lTemp2
lda gMulTabLo,x
sta aMulReader + 1
lda gMulTabHi,x
sta aMulReader + 2
ldy b
aMulReader:
lda $0000,y
sta lTemp3
;; b * cos x, cosx is in temp2 b in Y register
lda gMulTabLo,y
sta aMulReader2 + 1
lda gMulTabHi,y
sta aMulReader2 + 2
ldx lTemp2
aMulReader2:
lda $0000,x
clc
adc lTemp1
clc
adc lTemp3
simdi tam hesaplayamayacagim ama bu kadar optimizasyondan sonra 100 cycle civarina boyle complex bi hesaplamayi kotarmak mumkun.
Daha iyisi olabilir mi
3. KURAL: Fonksiyonlari birlestirebildiginiz yerlerde birlestirip tek tablo yapin.
yani sin icin 1 cos icin 1 ve carpma icin bir tablo yapacaginiza f(a,b) icin bir tablo yapin. yani bellege her a,b cifti icin f(a,b)nin tamamini hesaplayip onu koyun ve bir seferde tablodan okuyun
ldx a
lda gMyFxTableReadLo,x
sta aReader + 1
lda gMyFxTableReadHi,x
sta aReader + 2
ldx b
aReader:
lda $0000,x
boylece 100 cycle'lik islemi 4 kat hizlandirmis oluyoruz.
Bunun anlami su.
1- yapilan islemlere "top down" bir bakis acisi ile bakip islemlerin mumkun oldugunca tek fonksiyona indirgenmesi
2- fonksiyonlara giren argumanlarin alabilecegi deger sayisinin en basta dizayn yapilirken kisitlanmasi
3- sonra da buna uygun tablolarin yaratilmasi
bu uc islem ile cok olumcul optimizasyonlar yapilabilir.
son bi not:
bu ornekteki 2 argumanli fonksiyon icin table- lookup rutini kendini degistiren bir rutin. (sta aReader + 1 falan ile)
Bu rutin kisa bi rutin oldugu icin kendisini 0. sayfaya koyabiliriz. bunu yaparak sta komutlarindan birer cycle daha kurtarabiliriz. ama bu rutine cok fazla jsr rts yapacaksak cok anlamli olmayacaktir. onun yerine jsr yaptigimiz yere rutini acik yazsak daha iyi. (cunku jsr rts toplam 12 cycle yer)
ama basit bir dongu ile bu islem yapiliyorsa dongusu ile beraber 0. sayfaya konulabilir.
---------------
Guya kisa biseyler yazacaktim