OldComp.cz

Komunitní diskuzní fórum pro fanoušky historických počítačů


Právě je 27.04.2024, 08:24

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]




Odeslat nové téma Odpovědět na téma  [ Příspěvků: 598 ]  Přejít na stránku Předchozí  1, 2, 3, 4, 5, 6, 7, 8 ... 40  Další
Autor Zpráva
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 13.06.2020, 13:43 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Kubik píše:

https://www.root.cz/clanky/programovaci-jazyk-forth-a-zasobnikove-procesory/nazory/
Jses to ty co tam pred 15 lety napsal:
Citace:
To je prima, tenhle serial. Kdysi sem zbastlil Forth pro IQ-151 a pro ADT 4500 a pak sem na nej nejak pozapomenul, tak se tesim na pokracovani, abych si oprasil znalosti :)

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 13.06.2020, 13:52 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Naucil jsem bash skript v sedu rozpoznavat jmena funkci, konstant a promennych. Takze uz vytvari CALL(name) nebo PUSH(name), a co nezna na to nesaha, tak je hned videt co se musi dodelat.
Aby se u konstant provedly optimalizace, tak je nutne aby konstanta byla chapana jako cislo. Udelal jsem to tak, ze se prvne jmeno konstanty nahradi za cislo a pak nakonec nazpet. Zacina se od 1, ale je pred to pridano deset nul.

Delalo to chybu kdyz je v programu "3 *" a kdyz se pouzivaji pojmenovane konstanty je to "tri *". Tak M4 makro nedokazalo zjistit jakou hodnotu ma"tri". Takze se CONSTNANT(tri,3) rozbaluje na:

tri EQU 3
define({tri},{3})

Kde ten druhy radek je novy. A pak PUSH_MUL(tri) uz vnitrne M4 vidi jako PUSH_MUL(3).

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.06.2020, 12:21 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Opravil jsem smycky ve Forthu. Vedel jsem, ze smycka probehne vzdy aspon jednou. Coz je pravda. Ale zbytek jsem programoval defenzivne. Pokud ma byt smycka 5 az skoro 11 tak jsem tam mel podminku "index >= 5" tak ukonci smycku a neopakuj ji. Ono se to blbe testuje, protoze kdyz zadate spatne parametry tak ty online kompilery vytuhnou. Ale jakmile tam pridate nejakou kontrolu maximalniho opakovani tak zjistite ze...

Forth to ma jinak. "5 10 do i . loop" zacne vypisovat cisla "10 11 12 13 14 15... ...2 3 4". Nejenom 10.

Pak je tu druha zalezitost kdyz neni prirustek +1, ale libovolne cislo. Tady se to dost komplikuje. Jedine reseni je zjistit zda pred prictenim "step" lezi index na jedne strane "stop" a pro pricteni na druhe. Ze se otoci znamenka kdyz to vhodne napiseme.

Prvni odhad byl, ze udelam "index-stop" a pak "index-stop+step". Takze kdyz udelame +step a otoci se znamenko bude mit vysledek automaticky carry. Houby s octem. To plati pouze kdyz je "step" kladne cislo. A "step" muze byt i zaporne cislo! Treba -1. Takze pri otoceni znamenka naopak carry nebude.

Uf! A to jeste ma Forth chovani, ze kdyz je step zaporne tak konec neni vyjma, ale vcetne.

"5 10 do i . -1 loop" vypisuje 10 9 8 7 6 5.
"10 5 do i . 1 loop" vypisuje 5 6 7 8 9.

Jedina fungujici varianta me vychazela:
A = index-stop
B = index-stop+step

A zjistit zda se zmenilo znamenko. Takze (A xor B) a kdyz je priznak SIGN tak koncime smycku. Pri tomhle zpusobu i samo od sebe funguje to ukonceni "vcetne" u zapornych cisel. Coz bude asi duvod proc to tak je definovany.

Kód:
: down1
over . dup . ."  do -1 +loop: "
do i .
    i -8 < if ." ..." cr unloop exit then
    i  8 > if ." ..." cr unloop exit then
-1 +loop cr ;

: up1
over . dup . ."  do  1 +loop: "
do i .
    i -8 < if ." ..." cr unloop exit then
    i  8 > if ." ..." cr unloop exit then
1 +loop cr ;

: down3
over . dup . ."  do -3 +loop: "
do i .
    i -8 < if ." ..." cr unloop exit then
    i  8 > if ." ..." cr unloop exit then
-3 +loop cr ;

: up3
over . dup . ."  do  3 +loop: "
do i .
    i -8 < if ." ..." cr unloop exit then
    i  8 > if ." ..." cr unloop exit then
3 +loop cr ;

: smycka
over . dup . ."  do     loop: "
do i .
    i -8 < if ." ..." cr unloop exit then
    i  8 > if ." ..." cr unloop exit then
loop cr ;

: otaznik
over . dup . ." ?do     loop: "
?do i .
    i -8 < if ." ..." cr unloop exit then
    i  8 > if ." ..." cr unloop exit then
loop cr ;

5 7 down1
5 7 down3
5 7 up1
5 7 up3
5 7 smycka
5 7 otaznik
cr
5 5 down1
5 5 down3
5 5 up1
5 5 up3
5 5 smycka
5 5 otaznik
cr
5 3 down1
5 3 down3
5 3 up1
5 3 up3
5 3 smycka
5 3 otaznik



variable stop
variable krok

: smycka
    krok !
    6 stop !
    over . dup . krok @ . ." :"
    do
        i .
        stop @ 1- dup stop !
        0= if ." ..." leave then
        krok @
    +loop
    cr
;

4 4 -1 smycka
1 4 -1 smycka
4 1 -1 smycka
4 1  0 smycka
0 0  0 smycka
1 4  0 smycka
1 4  1 smycka
4 1  1 smycka
4 4  1 smycka
2 -1 -1 smycka
-1 2 -1 smycka
2 -1 0 smycka
-1 2 0 smycka
-1 2 1 smycka
2 -1 1 smycka
-20 20 -10 smycka
-20 21 -10 smycka
-20 19 -10 smycka

Vystup
Kód:
5 7  do -1 +loop: 7 6 5
5 7  do -3 +loop: 7
5 7  do  1 +loop: 7 8 9 ...
5 7  do  3 +loop: 7 10 ...
5 7  do     loop: 7 8 9 ...
5 7 ?do     loop: 7 8 9 ...

5 5  do -1 +loop: 5
5 5  do -3 +loop: 5
5 5  do  1 +loop: 5 6 7 8 9 ...
5 5  do  3 +loop: 5 8 11 ...
5 5  do     loop: 5 6 7 8 9 ...
5 5 ?do     loop:

5 3  do -1 +loop: 3 2 1 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 ...
5 3  do -3 +loop: 3 0 -3 -6 -9 ...
5 3  do  1 +loop: 3 4
5 3  do  3 +loop: 3
5 3  do     loop: 3 4
5 3 ?do     loop: 3 4

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.06.2020, 17:53 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
_dworkin píše:
Pokud ma byt smycka 5 az skoro 11 tak jsem tam mel podminku "index >= 5" tak ukonci smycku a neopakuj ji.

index >= 11

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 20.06.2020, 10:18 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Mam radost! :D
Napsal jsem hru zivota pro M4 FORTH, myslim tu od nedavno zesnuleho matematika Conway's Game of Life.
Verze pro basic je na http://rosettacode.org/wiki/Conway%27s_Game_of_Life#ZX_Spectrum_Basic a je neskutecne pomala...
Ta moje byla mnohem rychlejsi, ale nelibila se mi cast kdy jsem si to udelal slozite, protoze jsem zvolil hraci plochu nekonecnou, kdy z jednoho okraje propadnete na druhy. Takze jsem musel osetrovat pri podteceni leveho okraje tohle:
dup 1- 0x1F and swap 0xFFE0 and +
popripade pri preteceni praveho okraje:
dup 1+ 0x1F and swap 0xFFE0 and +
Kde slovni popis tohoto kousku kodu je: vytvor kopii kopii 16bitove adresy, pricti nebo odecti jednicku, ponech jen spodnich 5 bitu, prohod se s originalem, tam vynuluj spodnich 5 bitu a cisla secti.

No a protoze cely ten assembler je M4 makro, tak jsem si rovnou mohl vytvorit do programu slova LEFT a RIGHT a pouzit je. Vypada to prehledne a je to mnohem vykonejsi a kratsi, protoze pracuji jen s 8bitovou hodnotou. :D

Kód:
; dup 1- 0x1F and swap 0xFFE0 and +
define({LEFT},{
    ld    A, L          ; 1:4       left
    dec   A             ; 1:4       left
    xor   L             ; 1:4       left
    and  0x1F           ; 2:7       left
    xor   L             ; 1:4       left
    ld    L, A          ; 1:4       left})dnl

; dup 1+ 0x1F and swap 0xFFE0 and +
define({RIGHT},{
    ld    A, L          ; 1:4       right
    inc   A             ; 1:4       right
    xor   L             ; 1:4       right
    and  0x1F           ; 2:7       right
    xor   L             ; 1:4       right
    ld    L, A          ; 1:4       right})dnl


Cely minimalisticky kod najdete tady: https://github.com/DW0RKiN/M4_FORTH/blob/master/Game/life.m4 doporucuji prohlednout.
A vygenerovany assembler tady: https://github.com/DW0RKiN/M4_FORTH/blob/master/Game/life.asm

PS: Predtim jsem se snazil prevest nejaky kod ve forthu, ale po 2 tydnech marneho snazeni jsem si to radeji napsal sam.


Přílohy:
life.png
life.png [ 3.32 KiB | Zobrazeno 2329 krát ]
life.z80 [2.94 KiB]
130 krát

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH
Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 21.06.2020, 13:21 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Napoveda pro cteni: HL je TOP data stack, nasleduje DE, nasleduje (SP), nasleduje (SP+2), atd.
Forth pouziva postfixovou notaci takze "3 5 +" je 3+5, "3 5 -" je (ted pozor) 3-5, "3 5 =" je (3=5) test.
push je ulozeni neceho do TOP a posunuti zbytku zasobniku. "n addr !" je ulozeni "n" do pameti na adresu "addr". "addr fetch" je nacteni do TOP z addresy "addr". "over" je kopie druhe polozky na zasobniku (teda kopie DE).

Pravidlo pro prekladace: Jakmile je v programu vlozeni konstanty tak POKAZDE jde kod optimalizovat.
Kód:
-    push DE             ; 1:11      push(2)
-    ex   DE, HL         ; 1:4       push(2)
-    ld   HL, 2          ; 3:10      push(2)
-    push DE             ; 1:11      push(direction)
-    ex   DE, HL         ; 1:4       push(direction)
-    ld   HL, direction  ; 3:10      push(direction)
-    ld  (HL), E         ; 1:7       ! store
-    inc  HL             ; 1:6       ! store
-    ld  (HL), D         ; 1:7       ! store
-    pop  HL             ; 1:10      ! store
-    pop  DE             ; 1:10      ! store
+    ld   BC, 2          ; 3:10      push2_store(2,direction)
+    ld   (direction), BC; 4:20      push2_store(2,direction)
Kód:
-    push DE             ; 1:11      push(apple_x)
-    ex   DE, HL         ; 1:4       push(apple_x)
-    ld   HL, apple_x    ; 3:10      push(apple_x)
-    ld  (HL), E         ; 1:7       ! store
-    inc  HL             ; 1:6       ! store
-    ld  (HL), D         ; 1:7       ! store
-    pop  HL             ; 1:10      ! store
-    pop  DE             ; 1:10      ! store
-    push DE             ; 1:11      push(apple_y)
-    ex   DE, HL         ; 1:4       push(apple_y)
-    ld   HL, apple_y    ; 3:10      push(apple_y)
-    ld  (HL), E         ; 1:7       ! store
-    inc  HL             ; 1:6       ! store
-    ld  (HL), D         ; 1:7       ! store
-    pop  HL             ; 1:10      ! store
-    pop  DE             ; 1:10      ! store
+    ld   (apple_x), HL  ; 3:16      apple_x ! push(apple_x) store
+    ex   DE, HL         ; 1:4       apple_x ! push(apple_x) store
+    pop  DE             ; 1:10      apple_x ! push(apple_x) store
+    ld   (apple_y), HL  ; 3:16      apple_y ! push(apple_y) store
+    ex   DE, HL         ; 1:4       apple_y ! push(apple_y) store
+    pop  DE             ; 1:10      apple_y ! push(apple_y) store
Kód:
-    push DE             ; 1:11      push(direction)
-    ex   DE, HL         ; 1:4       push(direction)
-    ld   HL, direction  ; 3:10      push(direction)
-    ld    A, (HL)       ; 1:7       @ fetch
-    inc  HL             ; 1:6       @ fetch
-    ld    H, (HL)       ; 1:7       @ fetch
-    ld    L, A          ; 1:4       @ fetch
+    push DE             ; 1:11      direction @ push(direction) fetch
+    ex   DE, HL         ; 1:4       direction @ push(direction) fetch
+    ld   HL,(direction) ; 3:16      direction @ push(direction) fetch
Nasledujici je vtipny, protoze jsem uz mel vylepsenou variantu, ale prehledl jsem ze "3 OVER" je to same co "DUP 3". Mimochodem to "= if" je uz zkraceny kod protoze jsou to dve slova v jednom.
Kód:
-    push DE             ; 1:11      push(0)
-    ex   DE, HL         ; 1:4       push(0)
-    ld   HL, 0          ; 3:10      push(0) 
-    push DE             ; 1:11      over
-    ex   DE, HL         ; 1:4       over ( b a -- b a b )
-    or    A             ; 1:4       = if
-    sbc  HL, DE         ; 2:15      = if
-    pop  HL             ; 1:10      = if
-    pop  DE             ; 1:10      = if
-    jp   nz, else101    ; 3:10      = if
+    ld    A, high 0     ; 2:7       dup 0 = if
+    xor   H             ; 1:4       dup 0 = if
+    ld    B, A          ; 1:4       dup 0 = if
+    ld    A, low 0      ; 2:7       dup 0 = if
+    xor   L             ; 1:4       dup 0 = if
+    or    B             ; 1:4       dup 0 = if
+    jp   nz, else101    ; 3:10      dup 0 = if
Dalsi prehlednuti kdy jedne vylepsena varianta mohla vzit dalsi konstantu navic.
Kód:
-    push DE             ; 1:11      push(1)
-    ex   DE, HL         ; 1:4       push(1)
-    ld   HL, 1          ; 3:10      push(1)   
-    ld   (direction), HL; 3:16      direction ! push(direction) store
-    ex   DE, HL         ; 1:4       direction ! push(direction) store
-    pop  DE             ; 1:10      direction ! push(direction) store
+    ld   BC, 1          ; 3:10      push2_store(1   ,direction)
+    ld   (direction), BC; 4:20      push2_store(1   ,direction)
Doplneni pro ADD,SUB,AND,XOR,OR (zvlast u tech poslednich to jde krasne zlepsit, protoze se pracuje s 16bitovymi cisly a kolikrat staci s jednim 8bitovym parem.)
Kód:
-    push DE             ; 1:11      push(4)
-    ex   DE, HL         ; 1:4       push(4)
-    ld   HL, 4          ; 3:10      push(4)
-    ex   DE, HL         ; 1:4       -
-    or    A             ; 1:4       -
-    sbc  HL, DE         ; 2:15      -
-    pop  DE             ; 1:10      -
+    ld   BC, 4          ; 3:10      4 -
+    or    A             ; 1:4       4 -
+    sbc  HL, BC         ; 2:15      4 -
A fungovalo to na prvni dobrou!
Kód:
dworkin@Aspire:~/Forth/Makra/Game$ ls -l snake.bin
-rw-rw-r-- 1 dworkin dworkin 1648 čen 20 11:16 snake.bin
dworkin@Aspire:~/Forth/Makra/Game$ ../compile.sh snake
dworkin@Aspire:~/Forth/Makra/Game$ ls -l snake.bin
-rw-rw-r-- 1 dworkin dworkin 1466 čen 21 11:51 snake.bin

PS: Obavam se ze to stejne nikdo necte. Nevim zda je to moc slozite nebo jsem hodne mimo. :D Zrovna tohle me prijde snadno srozumitelne.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 21.06.2020, 14:23 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Tak uz vim proc jsem mel ty smycky od pocatku spatne. A mel je neprogramovany defenzivne. Protoze jsem pridaval slova podle https://theultimatebenchmark.org/ Kde je uveden kod
Kód:
: fib2 ( n1 -- n2 )                                                               
   0 1 rot 0 do
      over + swap loop
   drop ;
 
: fib2-bench 1000 0 do
    20 0 do i fib2 drop loop
  loop ;
A ten je spatne, protoze pri prvnim vypoctu se pocita "0 0 do over + swap loop". Vyjde pak nesmysl, protoze okamzite preteceme. Spravne to ma byt "0 0 ?do over + swap loop" kdy ?do zjisti ze zacatek je rovny konci a nevykona se smycka ani jednou. To je dost neprijemne, protoze je to benchmark a nema ZADNY vystup. Takze neni jasne zda se ma pocitat ten nesmysl, kdy prvni smycka se vykona 65536x a nebo se to ma spravit na "?do". Pri nesmyslu trva vypocet desitky minut, pri spravnem vypoctu pomoci "?do" deset vterin... A ted to porovnejte s ostatnimi...

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 21.06.2020, 17:18 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3675
Bydliště: Bratislava
Has thanked: 373 times
Been thanked: 798 times
_dworkin píše:
PS: Obavam se ze to stejne nikdo necte. Nevim zda je to moc slozite nebo jsem hodne mimo. :D Zrovna tohle me prijde snadno srozumitelne.
Nie si mimo, ani to nie je moc zlozite. Skor je to asi tym, ze malo ludi vobec robi s FORTHom, a len malo z toho mala to vie aj nejak vyuzit v praxi.
Napriklad ja sa sice zaujimam o rozne ine jazyky na Spektre (pascal, cecko, lisp ...) ale nikdy som realne v praxi nepouzil nic ine ako basic a asembler, a ani pouzit neplanujem, takze tento moj zaujem ma pomerne nizku prioritu.
Ale to ta nesmie odradit, pokial sa ti ten projekt paci, tak ti drzim palce aby napredoval !


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 22.06.2020, 13:48 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Ok, tak ja budu spamovat dal. .)
Vcera, nebo predevcirem jsem vylepsoval jsem hru Life a na githubu mam dodelanou editaci pole po bunce a nove jsem pridaval pod klavesou "c" clear_all a pod pod "f" full_all. Takze jsem psal rutinu na vyplneni bloku. V C se to jmenuje memset a ve Forthu je to fill. Kde na zasobniku ma byt "adresa kolikrat char". Prohledl jsem rady na netu a pro Z80 bylo doporucena instrukce ldir. A protoze jsem linej tak jsem napsal jen optimalizovanou variantu PUSH2_FILL. Protoze ve hre Life je adresa bufferu a jeho velikost nemenna a cim budu vyplnovat v dane casti je take konstanta. Dnes jsem zacal psat PUSH_FILL. Prepsal jsem tu LDIR variantu a koukam na to a rikam si, ze by to mohlo byt kratsi. LDIR 21 taktu... LD (HL),A + DJNZ 7+13=20 taktu! A jeste usetrim DE. Mrknu se i na tu PUSH2_FILL a nova varianta je dokonce stejne dlouha a nekdy i o bajt kratsi kdyz se A shoduje s pocatecni hodnotou B nebo C. Navic rychlejsi. Pro dane podminky, co kde lezi a co se musi zachovat je to proste nevyhodne resit pres LDIR.

Jediny problem je, ze makro uz neni prehledne.
Kód:
dnl addr u char fill
dnl ( to -- )
dnl If u is greater than zero, fill the contents of u consecutive characters at addr.
define({PUSH2_FILL},{ifelse(eval($1),{0},{
__{}    ex   DE, HL         ; 1:4       $1 $2 fill
__{}    pop  DE             ; 1:10      $1 $2 fill},
__{}eval($1),{1},{
__{}    ld  (HL),format({%-11s},$2); 2:10      $1 $2 fill
__{}    ex   DE, HL         ; 1:4       $1 $2 fill
__{}    pop  DE             ; 1:10      $1 $2 fill},
__{}{define({FILL_B},eval(($1) & 0xFF)){}define({FILL_C},eval(((FILL_B>0)+($1)/256) & 0xFF))
__{}    ld   BC, 0x{}format({%-9x},eval(256*FILL_B+FILL_C)); 3:10      $1 $2 fill{}dnl
__{}__{}ifelse(eval($2-FILL_B),{0},{
__{}__{}    ld    A, B          ; 1:4       $1 $2 fill},
__{}__{}eval($2-FILL_C),{0},{
__{}__{}    ld    A, C          ; 1:4       $1 $2 fill},
__{}__{}{
__{}__{}    ld    A, format({%-11s},$2); 2:7       $1 $2 fill})
__{}    ld  (HL),A          ; 1:7       $1 $2 fill
__{}    djnz $-1            ; 2:13/8    $1 $2 fill
__{}    dec   C             ; 1:4       $1 $2 fill
__{}    jr   nz, $-6        ; 2:7/12    $1 $2 fill
__{}    ex   DE, HL         ; 1:4       $1 $2 fill
__{}    pop  DE             ; 1:10      $1 $2 fill})})dnl
Oproti
Kód:
define({PUSH2_FILL},{ifelse(eval($1),{0},{
__{}    ex   DE, HL         ; 1:4       $1 $2 fill
__{}    pop  DE             ; 1:10      $1 $2 fill},
__{}eval($1),{1},{
__{}    ld  (HL),format({%-11s},$2); 2:10      $1 $2 fill
__{}    ex   DE, HL         ; 1:4       $1 $2 fill
__{}    pop  DE             ; 1:10      $1 $2 fill},{
    ld  (HL),format({%-11s},$2); 2:10      $1 $2 fill
    ld   BC, format({%-11s},eval($1)-1); 3:10      $1 $2 fill
    push DE             ; 1:11      $1 $2 fill
    ld    D, H          ; 1:4       $1 $2 fill
    ld    E, L          ; 1:4       $1 $2 fill
    inc  DE             ; 1:6       $1 $2 fill DE = to
    ldir                ; 2:u*21/16 $1 $2 fill
    pop  HL             ; 1:10      $1 $2 fill
    pop  DE             ; 1:10      $1 $2 fill})})dnl

Je to zalozeno na principu ze se do BC ulozi pocet opakovani. Ale prohodi se B a C. A k C se pricte 1 pokud je B nenulovy. Protoze djnz smycka pak probehne o jednou vice, proze prvne bude probihat s nenulovou hodnotou B ( puvodne C).
Chytak je, pricist tu jednicku tak aby to spravne preteklo jen v C a neovlivnilo to B.
Chytak dve je, ze to samozrejme plati jen pokud pocet opakovani je nenulovy.

Tady mam otazku, proc sakra pri navrhu Z80 pro djnz zvolili counter B a ne C? V cem je B lepsi, kdyz tady je videt ze pro 16-bitovou aritmetiku je vyhodnejsi mit jako counter nizsi registr z 16-bitoveho paru. Kdyz uz mam rychlou instrukci na smycku tak ji chci pouzivat pro VNITRNI smycku a ne mene pouzivanou vnejsi. Prehledl jsem neco? Jde to napsat jinak?
Kód:
     push DE             ; 1:11      push(buff)
     ex   DE, HL         ; 1:4       push(buff)
     ld   HL, buff       ; 3:10      push(buff)
-    ld  (HL), 0         ; 2:10      32*24 0 fill
-    ld   BC, 768-1      ; 3:10      32*24 0 fill
-    push DE             ; 1:11      32*24 0 fill
-    ld   D, H           ; 1:4       32*24 0 fill
-    ld   E, L           ; 1:4       32*24 0 fill
-    inc  DE             ; 1:6       32*24 0 fill DE = to
-    ldir                ; 2:u*21/16 32*24 0 fill
-    pop  HL             ; 1:10      32*24 0 fill
+    ld   BC, 0x3        ; 3:10      32*24 0 fill
+    ld    A, B          ; 1:4       32*24 0 fill
+    ld  (HL),A          ; 1:7       32*24 0 fill
+    djnz $-1            ; 2:13/8    32*24 0 fill
+    dec   C             ; 1:4       32*24 0 fill
+    jr   nz, $-6        ; 2:7/12    32*24 0 fill
+    ex   DE, HL         ; 1:4       32*24 0 fill
     pop  DE             ; 1:10      32*24 0 fill

     push DE             ; 1:11      push(buff)
     ex   DE, HL         ; 1:4       push(buff)
     ld   HL, buff       ; 3:10      push(buff)
-    ld  (HL), 1         ; 2:10      32*24 1 fill
-    ld   BC, 768-1      ; 3:10      32*24 1 fill
-    push DE             ; 1:11      32*24 1 fill
-    ld   D, H           ; 1:4       32*24 1 fill
-    ld   E, L           ; 1:4       32*24 1 fill
-    inc  DE             ; 1:6       32*24 1 fill DE = to
-    ldir                ; 2:u*21/16 32*24 1 fill
-    pop  HL             ; 1:10      32*24 1 fill
+    ld   BC, 0x3        ; 3:10      32*24 1 fill
+    ld    A, 1          ; 2:7       32*24 1 fill
+    ld  (HL),A          ; 1:7       32*24 1 fill
+    djnz $-1            ; 2:13/8    32*24 1 fill
+    dec   C             ; 1:4       32*24 1 fill
+    jr   nz, $-6        ; 2:7/12    32*24 1 fill
+    ex   DE, HL         ; 1:4       32*24 1 fill
     pop  DE             ; 1:10      32*24 1 fill

PS: memset... Zda se ze pri psani prekladace Forthu si uziji skoro vsechny zakladni algoritmy.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 22.06.2020, 14:40 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Hmm.. rekl bych se jsem zapomnel ve vnitrni smycce inkrementovat DE! :D

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 22.06.2020, 16:56 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Vratil jsem PUSH2_FILL na puvodni verzi, vytvoril PUSH_FILL a FILL kde je primarne delsi, ale rychlejsi varianta s LDIR. Je tam ale moznost to prepnout.
Vytvoril jsem i prvni slepenec s tremi push. PUSH3_FILL. Ktery vypada takto
Kód:
    push DE             ; 1:11      buff 32*24 1 fill
    push HL             ; 1:11      buff 32*24 1 fill
    ld   HL, buff       ; 3:10      buff 32*24 1 fill HL = from
    ld   DE, buff+1     ; 3:10      buff 32*24 1 fill DE = to
    ld   BC, 0x2ff      ; 3:10      buff 32*24 1 fill
    ld  (HL),1          ; 2:10      buff 32*24 1 fill
    ldir                ; 2:u*21/16 buff 32*24 1 fill
    pop  HL             ; 1:10      buff 32*24 1 fill
    pop  DE             ; 1:10      buff 32*24 1 fill

Drobny problem mam s hodnotou "buff". Protoze je to label, a skutecnou hodnotu bude znat az prekladac. Ne M4 makro. Takze je to celkem nebezpecne kdyz se do parametru makra zada neco takoveho, protoze pokud s tim makro bude chtit delat neco slozitejsiho. Napriklad eval, nebo i obycejny prevod na hexadecimalni hodnotu tak vysledek bude prazdny retezec. Proto to v "ld DE,buff+1" jen tisknu jako "ld DE," $1 "+1".

No a protoze neznam hodnotu HL, DE tak nemuzu dobre zlepsit "ld (HL),1" na treba "ld (HL),E". Reseni to ma. Ze makro M4 udela makro pro pasmo. Ale to se mi moc nechce, cena me prijde prilis vysoka. Uz jen proto, ze nevim jak moc je shodne pasmo s jinymi prekladaci. Takze to nechavam plavat.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 24.06.2020, 17:59 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Jakmile jsem dodelal rutinu FILL, tak jsem se koukal, ktery dalsi benchmark se mi ted otevira a nasel SIEVE. Ktery FILL pouziva na vyplneni pameti jednickami pro Eratosthenovo sito.
Moje prvni verze mela 2.05 vterin. Ale drobnymi upravami a pridanim dalsich slepenych slov jako DUP_ADD (tady je me zahadou proc nepouzili rovnou slovo 2*, mozna se bali ze to bude fakt nasobit...), DUP_PUSH a CONDITION_WHILE jsem se dostal na 1.9 vteriny. Udelal jsem drobne zmeny, kde jsem krome jineho v kodu prepsal "dup + 3 +" na "+1 dup + +1", protoze vim ze to usetri jednu jedinou instrukci :) a byl na 1.84 vterinach.
Kód:
ld bc, 3
add hl, bc

jsem optimalizoval na

inc hl
inc hl
inc hl

takze dup + 3 + udela

add hl, hl  ; dup +
inc hl
inc hl
inc hl      ; 3 +

A +1 dup + +1 udela

inc hl      ; +1
add hl, hl  ; dup +
inc hl      ; +1
Pridaval jsem slovo DUP_PUSH_CONDITION_WHILE a s nim jsem se dostal na konecnych 1.51 vteriny.

Koukal jsem se jak to zvladne C64. DurexForth 1.6.1 (STC) to zvladne za 10 vterin a Commodore C64 6510 s Audiogenic Forth-64 za 18.1 vteriny. To me uz ani tak neprekvapilo. Protoze jsem byl pokazde rychlejsi.

Ale... nasel jsem stejny test prepsany i pro C. Dve ruzne verze. Zkousel jsem to skompilovat se zcc a neuspel jsem ani u jedne. Nakonec jsem zvolil tu rucne psanou, protoze prvni verze vypadala jako nejaky autmaticky prekladac z forthu do C. A prepisoval podle toho kde me zcc rval chyby. Az jsem skoncil na chybe, ktera nesla opravit. Proste ted uz zcc neumi malloc. Nakonec me doslo, ze vlastne muzu udelat pole staticky. Par zakysu, nez me doslo ze tam mam zapomenuty free a zkompiloval jsem to. Vysledek shodny s Fortem.

Ale zcc trva 5.94 vteriny!!! Skoro 4x pomaleji. Uf.
Cekal jsem neco relativne shodneho. Nedoufal jsem ze budu rychlejsi jak c compiler. Ale ze budu temer 4x rychlejsi. A to jeste po tezkem boji abych to vubec prelozil.
Takze jsem se ani nepokousel zapnout nejake optimalizace. Ale ten zdrojak je vicemene ok: https://github.com/DW0RKiN/M4_FORTH/blob/master/Benchmark/sieve.c. Je tu nekdo odbornik na zcc?

Oproti M4_FORTHu: https://github.com/DW0RKiN/M4_FORTH/blob/master/Benchmark/sieve.m4
s ASM vysledkem: https://github.com/DW0RKiN/M4_FORTH/blob/master/Benchmark/sieve.asm


Přílohy:
sieve_c.z80 [11.02 KiB]
154 krát
sieve.z80 [8.44 KiB]
137 krát

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH
Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 24.06.2020, 19:43 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3675
Bydliště: Bratislava
Has thanked: 373 times
Been thanked: 798 times
_dworkin píše:
Zkousel jsem to skompilovat se zcc
Skus popripade aj Hisoft C. To by mohlo dat lepsi vysledok.


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 24.06.2020, 20:16 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
Na ruzne C prekladace pro ZX jsem se dival, ale nechtelo se mi to psat (znovu) primo v emulatoru. Ale vsechno to chce znalosti, ktere nemam a bojuji jen s tim abych zkompiloval obycejny hello_word.c v podstate. Coz je taky jeden z duvodu proc nakonec pisi ten M4_FORTH.

No muzu se pokusit. .)

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 24.06.2020, 20:21 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1120
Has thanked: 100 times
Been thanked: 161 times
hmm... WoS je dost nefunkcni, neplatny odkaz na soubory... .)

https://worldofspectrum.org/infoseekid.cgi?id=0008252


Přílohy:
Poznámka: To bude boj... a napsat to primo v emulatoru nehrozi, protoze nedam psat na slepo, kde je jaky znak. Chtel jem jen napsat #include < a uz tam jsou 2 problematicke znaky.
HiSoftCV1.3.png
HiSoftCV1.3.png [ 5.46 KiB | Zobrazeno 2315 krát ]

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH
Nahoru
 Profil  
 
Zobrazit příspěvky za předchozí:  Seřadit podle  
Odeslat nové téma Odpovědět na téma  [ Příspěvků: 598 ]  Přejít na stránku Předchozí  1, 2, 3, 4, 5, 6, 7, 8 ... 40  Další

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 28 návštevníků


Nemůžete zakládat nová témata v tomto fóru
Nemůžete odpovídat v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete přikládat soubory v tomto fóru

Hledat:
Přejít na:  
Založeno na phpBB® Forum Software © phpBB Group
Český překlad – phpBB.cz