Zapracoval jsem na te podpore pro Kempston. Presneji jsem zapracoval na obecnem cteni z portu tak, aby se za urcitych podminek vysledny kod podobal tomu co by udelalo specializovane slovo.
Musel jsem pridat podporu mnohem vice veci nez jsem myslel + neco jsem udelal dupicitne, protoze jsem to zapomnel predtim dopsat do readme.
Takze jedna z veci co jsem potreboval je vetsi podpora 8 bitove aritmeticke a logicke operace. Pak tu zavrhovanou podporu pro priznaky.
Prvne napisi vlastne jak to vypada kdyz nemam jedno slovo a musim to skladat z Forth slov.
Kód:
PUSH(0x1F) PORTFETCH PUSH(0xFF-2) COR _1CADD_ZF ZF_IF
a) Prvni dve slova nactou do TOS hodnotu portu 0x001F.
b) Dalsi dve slovo provedou 8 bitovy binarni OR
c) 1c+ pricte 8 bitove jednicku a nastavi "zero flag".
d) Pak uz muze navazovat cokoliv.
add c) Je to mysleno tak ze ta operace odstrani z TOS hodnotu a nastavi specialni promennou zero_flag. To odstraneni je dulezite a musim skontrolovat zda to mam vsude.
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'AND'
ld A, E ; 1:4 and ( x2 x1 -- x ) x = x2 & x1
and L ; 1:4 and
ld L, A ; 1:4 and
ld A, D ; 1:4 and
and H ; 1:4 and
ld H, A ; 1:4 and
pop DE ; 1:10 and
; seconds: 0 ;[ 7:34]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'AND_ZF'
ld A, E ; 1:4 and ( x2 x1 -- ) set zf: x2 & x1
and L ; 1:4 and
jr nz, $+4 ; 2:7/12 and
ld A, D ; 1:4 and
and H ; 1:4 and
pop HL ; 1:10 and
pop DE ; 1:10 and
; seconds: 0 ;[ 8:43]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'OR'
ld A, E ; 1:4 or ( x2 x1 -- x ) x = x2 | x1
or L ; 1:4 or
ld L, A ; 1:4 or
ld A, D ; 1:4 or
or H ; 1:4 or
ld H, A ; 1:4 or
pop DE ; 1:10 or
; seconds: 0 ;[ 7:34]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'OR_ZF'
ld A, L ; 1:4 or ( x2 x1 -- ) set zf: x2 | x1
or H ; 1:4 or
or D ; 1:4 or
or E ; 1:4 or
pop HL ; 1:10 or
pop DE ; 1:10 or
; seconds: 0 ;[ 6:36]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'XOR'
ld A, E ; 1:4 xor ( x2 x1 -- x ) x = x2 ^ x1
xor L ; 1:4 xor
ld L, A ; 1:4 xor
ld A, D ; 1:4 xor
xor H ; 1:4 xor
ld H, A ; 1:4 xor
pop DE ; 1:10 xor
; seconds: 0 ;[ 7:34]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'XOR_ZF'
or A ; 1:4 xor ( x2 x1 -- ) set zf: x2 ^ x1
sbc HL, DE ; 2:15 xor
pop HL ; 1:10 xor
pop DE ; 1:10 xor
; seconds: 0 ;[ 5:39]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1ADD'
inc HL ; 1:6 1+
; seconds: 0 ;[ 1:6]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1ADD_ZF'
ld A, L ; 1:4 1+ zf ( x -- ) set zf: x + 1
and H ; 1:4 1+ zf
inc A ; 1:4 1+ zf set zf
ex DE, HL ; 1:4 1+ zf
pop DE ; 1:10 1+ zf
; seconds: 0 ;[ 5:26]
Pro muj pripad bylo dulezite mit podporu pro 8 bit (ciste kvuli efektivite)
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'CAND'
ld A, E ; 1:4 cand ( x2 x1 -- x3 ) x3 = hi(x1) + lo(x2 & x1)
and L ; 1:4 cand
ld L, A ; 1:4 cand
pop DE ; 1:10 cand
; seconds: 0 ;[ 4:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'HAND'
ld A, D ; 1:4 hand ( x2 x1 -- x3 ) x3 = hi(x2 & x1) + lo(x1)
and H ; 1:4 hand
ld H, A ; 1:4 hand
pop DE ; 1:10 hand
; seconds: 0 ;[ 4:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'COR'
ld A, E ; 1:4 cor ( x2 x1 -- x3 ) x3 = hi(x1) + lo(x2 | x1)
or L ; 1:4 cor
ld L, A ; 1:4 cor
pop DE ; 1:10 cor
; seconds: 0 ;[ 4:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'HOR'
ld A, D ; 1:4 hor ( x2 x1 -- x3 ) x3 = hi(x2 | x1) + lo(x1)
or H ; 1:4 hor
ld H, A ; 1:4 hor
pop DE ; 1:10 hor
; seconds: 0 ;[ 4:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'CXOR'
ld A, E ; 1:4 cxor ( x2 x1 -- x3 ) x3 = hi(x1) + lo(x2 ^ x1)
xor L ; 1:4 cxor
ld L, A ; 1:4 cxor
pop DE ; 1:10 cxor
; seconds: 0 ;[ 4:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'HXOR'
ld A, D ; 1:4 hxor ( x2 x1 -- x3 ) x3 = hi(x2 ^ x1) + lo(x1)
xor H ; 1:4 hxor
ld H, A ; 1:4 hxor
pop DE ; 1:10 hxor
; seconds: 0 ;[ 4:22]
Poznamka: Mozna stoji za povsimnuti ze ve vysledku je tech 8 bitu na ktere se nesaha kopii z x1, protoze je to snazsi o bajt a 4 takty. Ale pokud by na to nekomu zalezelo tak je lepsi reseni to mit z x2, protoze to je pravdepodobne ta neznama a x1 je pravdepodobne konstanta co to ovlivnuje. U vetsiny operaci to jde resit jednim SWAPem navic a kod bude o ten bajt a 4 takty delsi. Ale u odcitani to chce asi dalsi slovo... Koukam ze CADD, HADD, CUSB a HSUB vubec neukazuji, neva jen me to pripomnelo ze jsem tam mel chybu v instrukcich kdy jsem psal neco jako "sub A,L" misto "sub L", a protoze jsem to netestoval tak me pasmo nervalo ze tuhle kombinaci operandu i instrukce nezna.V puvodnim kodu jsem mel spatne popisky protoze... koukam ze je to tady stale blbe. Takze se kouknete treba na posledni HXOR a tam vidite, ze to HI zapominam vynasobit 256, aby to bylo zase 16 bitova hodnota. Porovnejte popis s timhle:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1CADD'
inc L ; 1:4 1c+ ( x1 -- x2 ) x2 = 256*hi(x1) + lo(x1 + 1)
; seconds: 0 ;[ 1:4]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1CSUB'
dec L ; 1:4 1c- ( x1 -- x2 ) x2 = 256*hi(x1) + lo(x1 - 1)
; seconds: 0 ;[ 1:4]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1HADD'
inc H ; 1:4 1h+ ( x1 -- x2 ) x2 = x1 + 256
; seconds: 1 ;[ 1:4]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1HSUB'
dec H ; 1:4 1h- ( x1 -- x2 ) x2 = x1 - 256
; seconds: 0 ;[ 1:4]
No a ja jeste potrebuji to _ZF slovo. (Mozna to prejmenuji nakonec na _SETZ _SETC. I kdyz to druhe nedava presne smysl co to ma delat. Prvni je jako _0EQ_IF_SETZ_ELSE_RESZ_ENDIF, zkracene _SETZ). Jeste si vsimnete ze jsem otocil poradi u slov co to ctou na "ZF_IF". Kde to to ZF_ je neco jako if ZF=0 then TRUE else FALSE endif.
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1CADD_ZF'
inc L ; 1:4 1c+ zf ( x -- ) set zf: lo(x) c+ 1
ex DE, HL ; 1:4 1c+ zf
pop DE ; 1:10 1c+ zf
; seconds: 0 ;[ 3:18]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh '_1HADD_ZF'
inc H ; 1:4 1h+ zf ( x -- ) set zf: hi(x) c+ 1
ex DE, HL ; 1:4 1h+ zf
pop DE ; 1:10 1h+ zf
; seconds: 0 ;[ 3:18]
dworkin@dw-A15:~/Programovani/ZX/
Pak jsem postupne pridaval podporu kombinaci slov jako:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'OR _1ADD'
ld A, E ; 1:4 or ( x2 x1 -- x ) x = x2 | x1
or L ; 1:4 or
ld L, A ; 1:4 or
ld A, D ; 1:4 or
or H ; 1:4 or
ld H, A ; 1:4 or
pop DE ; 1:10 or
inc HL ; 1:6 1+
; seconds: 0 ;[ 8:40]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'COR _1ADD'
ld A, E ; 1:4 cor 1+ ( x2 x1 -- x3 ) x3 = hi(x1) + lo(x2 | x1) + 1
or L ; 1:4 cor 1+
ld L, A ; 1:4 cor 1+
inc HL ; 1:6 cor 1+
pop DE ; 1:10 cor 1+
; seconds: 0 ;[ 5:28]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'COR _1CADD'
ld A, E ; 1:4 cor 1c+ ( x2 x1 -- x3 ) x3 = hi(x1) + lo((x2 | x1) + 1)
or L ; 1:4 cor 1c+
inc A ; 1:4 cor 1c+
ld L, A ; 1:4 cor 1c+
pop DE ; 1:10 cor 1c+
; seconds: 0 ;[ 5:26]
a podporu prvni casti kde jsem to postupne pridval slovo za slovem.
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH'
push DE ; 1:11 0x1F port@ ( -- char )
ex DE, HL ; 1:4 0x1F port@
xor A ; 1:4 0x1F port@
ld H, A ; 1:4 0x1F port@
in A,(0x1F) ; 2:11 0x1F port@
ld L, A ; 1:4 0x1F port@
; seconds: 0 ;[ 7:38]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0xFF-2)'
push DE ; 1:11 0x1F port@ 0xFF-2 ( -- char 0xFF-2 )
push HL ; 1:11 0x1F port@ 0xFF-2
xor A ; 1:4 0x1F port@ 0xFF-2
ld D, A ; 1:4 0x1F port@ 0xFF-2
in A,(0x1F) ; 2:11 0x1F port@ 0xFF-2
ld E, A ; 1:4 0x1F port@ 0xFF-2
ld HL, 0x00FD ; 3:10 0x1F port@ 0xFF-2
; seconds: 1 ;[10:55]
To navazuje na
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'COR _1CADD_ZF'
ld A, E ; 1:4 cor 1c+ zf ( x2 x1 -- ) set zf: lo(x2 | x1) c+ 1
or L ; 1:4 cor 1c+ zf
inc A ; 1:4 cor 1c+ zf
pop HL ; 1:10 cor 1c+ zf
pop DE ; 1:10 cor 1c+ zf
; seconds: 41 ;[ 5:32]
A dohromady dela:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0xFF-2) COR _1CADD_ZF'
xor A ; 1:4 0x1F port@ 0xFF-2 cor 1c+ zf ( -- ) set zf: port(0x1F) and 0xFF-2
in A,(0x1F) ; 2:11 0x1F port@ 0xFF-2 cor 1c+ zf
or 0xFD ; 2:7 0x1F port@ 0xFF-2 cor 1c+ zf
inc A ; 1:4 0x1F port@ 0xFF-2 cor 1c+ zf
; seconds: 0 ;[ 6:26]
Kdyz to rozseknu:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0xFF-2) __ASM COR _1CADD_ZF'
push DE ; 1:11 0x1F port@ 0xFF-2 ( -- char 0xFF-2 )
push HL ; 1:11 0x1F port@ 0xFF-2
xor A ; 1:4 0x1F port@ 0xFF-2
ld D, A ; 1:4 0x1F port@ 0xFF-2
in A,(0x1F) ; 2:11 0x1F port@ 0xFF-2
ld E, A ; 1:4 0x1F port@ 0xFF-2
ld HL, 0x00FD ; 3:10 0x1F port@ 0xFF-2
ld A, E ; 1:4 cor 1c+ zf ( x2 x1 -- ) set zf: lo(x2 | x1) c+ 1
or L ; 1:4 cor 1c+ zf
inc A ; 1:4 cor 1c+ zf
pop HL ; 1:10 cor 1c+ zf
pop DE ; 1:10 cor 1c+ zf
; seconds: 1 ;[15:87]
Neco podobneho ale snazsiho je pro cteni jednoho bitu:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH __ASM PUSH(0x04) AND'
push DE ; 1:11 0x1F port@ ( -- char )
ex DE, HL ; 1:4 0x1F port@
xor A ; 1:4 0x1F port@
ld H, A ; 1:4 0x1F port@
in A,(0x1F) ; 2:11 0x1F port@
ld L, A ; 1:4 0x1F port@
ld A, 0x04 ; 2:7 0x04 and
and L ; 1:4 0x04 and
ld L, A ; 1:4 0x04 and
ld H, 0x00 ; 2:7 0x04 and
; seconds: 0 ;[13:60]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0x04) AND'
push DE ; 1:11 0x1F port@ 0x04 and ( -- x ) x: port(0x1F) | 0x04
ex DE, HL ; 1:4 0x1F port@ 0x04 and
ld HL, 0x0004 ; 3:10 0x1F port@ 0x04 and
xor A ; 1:4 0x1F port@ 0x04 and
in A,(0x1F) ; 2:11 0x1F port@ 0x04 and
and L ; 1:4 0x1F port@ 0x04 and
ld L, A ; 1:4 0x1F port@ 0x04 and
; seconds: 1 ;[10:48]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0x04) AND_ZF'
xor A ; 1:4 0x1F port@ 0x04 and ( -- ) set zf: port(0x1F) and 0x04
in A,(0x1F) ; 2:11 0x1F port@ 0x04 and
and 0x04 ; 2:7 0x1F port@ 0x04 and
; seconds: 0 ;[ 5:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$
Tady je nakonec videt kdyz porovname jen vysledne kody:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0xFF-4) COR _1CADD_ZF'
xor A ; 1:4 0x1F port@ 0xFF-4 cor 1c+ zf ( -- ) set zf: port(0x1F) and 0xFF-4
in A,(0x1F) ; 2:11 0x1F port@ 0xFF-4 cor 1c+ zf
or 0xFB ; 2:7 0x1F port@ 0xFF-4 cor 1c+ zf
inc A ; 1:4 0x1F port@ 0xFF-4 cor 1c+ zf
; seconds: 0 ;[ 6:26]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x1F) PORTFETCH PUSH(0x04) AND_ZF'
xor A ; 1:4 0x1F port@ 0x04 and ( -- ) set zf: port(0x1F) and 0x04
in A,(0x1F) ; 2:11 0x1F port@ 0x04 and
and 0x04 ; 2:7 0x1F port@ 0x04 and
; seconds: 1 ;[ 5:22]
Ze precejenom je to nastaveni TRUE na bit 1 o neco pomalejsi nez nataveni na TRUE na 0 jako u klavesnice. O to jedno "inc A", ktere se musi davat navic pokud cteme vice "bitu".
Porovnani pri cteni z klavesnice pres slovo co to testuje a pres port:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEY_O) TESTKEY_ZF'
ld A, 0xDF ; 2:7 0xDF02 testkey ( -- ) set zf == press "O"
in A,(0xFE) ; 2:11 0xDF02 testkey
and 0x02 ; 2:7 0xDF02 testkey
; seconds: 0 ;[ 6:25]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0xDFFE) PORTFETCH PUSH(0x02) AND_ZF'
ld A, 0xDF ; 2:7 0xDFFE port@ 0x02 and ( -- ) set zf: port(0xDFFE) and 0x02
in A,(0xFE) ; 2:11 0xDFFE port@ 0x02 and
and 0x02 ; 2:7 0xDFFE port@ 0x02 and
; seconds: 0 ;[ 6:25]
TODO: Opravit ty komentare "H|C+log_op"
Pridat optimalizace pro zapis jako DUP_ PUSH_ PUSH2_ + PORTSTORE. Mozna dokonce neco jako misto PUSH_PORTSTORE BC_PORTSTORE. Protoze nemam moc napad jak to udelat kdyz to nekdo chce mit vickrat za sebou (bez toho ze bych pouzil primo tu opakujici instrukci). Hmm... vlastne je asi lepsi na to mit slovo neco jako MOVE kopiruje z adresy na adresu u_word. Tak PORTMOVE? Jen by se jeste musel poresit nazev protoze jedno by kopirovalo na port od adresy n bunek/bajtu a druhe z portu cetlo n bunek/bajtu na adresu. To zni docela pouzitelne. Hmm.. ale asi bych musel jeste resit rychlost a vyporadat se z chybama cteni. Hmm... mozna to neni tak dobry napad, na to nemam kvalifikaci. .)