Nakonec jsem precejenom vytvoril slovo TESTKEMPSTON ( mask -- bool ) a pro nej 6 promennych a fci co je prevadi na popisek. Obdobnou fci jsem udelal i pro promenne u TESTKEY, protoze to zkracuje kod generujici slova.
Kód:
define({__TESTKEMPSTON_RIGHT},0xFFFE){}dnl
define({__TESTKEMPSTON_LEFT}, 0xFFFD){}dnl
define({__TESTKEMPSTON_DOWN}, 0xFFFB){}dnl
define({__TESTKEMPSTON_UP}, 0xFFF7){}dnl
define({__TESTKEMPSTON_FIRE}, 0xFFEF){}dnl
define({__TESTKEMPSTON_FIRE2},0xFFDF){}dnl
dnl
dnl
dnl
define({__TESTKEMPSTON_NAME},{dnl
__{}ifelse(dnl
__{}__HEX_L($1),__HEX_L(__TESTKEMPSTON_RIGHT),{{"right"}},
__{}__HEX_L($1),__HEX_L(__TESTKEMPSTON_LEFT), {{"left"}},
__{}__HEX_L($1),__HEX_L(__TESTKEMPSTON_DOWN), {{"down"}},
__{}__HEX_L($1),__HEX_L(__TESTKEMPSTON_UP), {{"up"}},
__{}__HEX_L($1),__HEX_L(__TESTKEMPSTON_FIRE), {{"fire"}},
__{}__HEX_L($1),__HEX_L(__TESTKEMPSTON_FIRE2),{{"fire2"}},
__{}__HEX_L($1),0xBF, {{"6th bit"}},
__{}__HEX_L($1),0x7F, {{"7th bit"}},
__{}{{"???"}}){}dnl
}){}dnl
To ze je TRUE u nacteneho bitu 1 a ne 0 jako u klavesnice stale trochu boli, protoze u slov jako je PUSH_TESTKEMPSTON_ZF kde znam hodnotu masky, takze ji dokazi v dobe "kompilace" invertovat a mit kod neco jako
Kód:
in A,(0x1F) ; 2:11 0xFFEF testkempston if ( -- ) port(kempston) 0xFFEF invert and 0<> if
and 0x10 ; 2:7 0xFFEF testkempston if "fire"
To nemohu provest... protoze TRUE=no zf a FALSE=zf
ale pokud zjistim ze je tam testovano vic bitu a nebo neznam hodnotu masky tak to bude
Kód:
in A,(0x1F) ; 2:11 testkempston 0= while(101) ( mask -- ) port(kempston) or +1 0<> if
or 0x?? ; 2:7 testkempston 0= while(101)
inc A ; 1:4 testkempston 0= while(101)
kde vysledek bude opacny, TRUE=zf a FALSE=no zf.
Je fajn ze to jde prevest aspon na stejny priznak ale na stejnou hodnotu to udelat nejde (neumim). Na prvni reseni nejde sahnout, protoze cokoliv ho udela stejne efektivni jako druhe a XOR nejde pouzit, protoze by to selhalo pokud by nactena hodnota mela vic bitu aktivnich. To je otazka pristupu, ja to beru tak ze kdyz testuji VLEVO tak by TRUE melo byt i kdyz je to VLEVO+FIRE nebo VLEVO+NAHORU. Pokud chci testovat VLEVO+FIRE tak musim mit masku pro "VLEVO & FIRE" co odchytne zase i VLEVO+NAHORU+FIRE. Pokud bych to chtel ale jinak, tak je XOR reseni to prave.
No a kdyz sahnu na druhe reseni tak to nedokazi prevest na TRUE=no zf aniz bych to take neprodlouzil i kdyz tady jsem mel lepsi sance.
Kdyz invertuji A za bajt a 4 takty a pouziji tu masku s AND tak je to stejne dlouhe, jen je ten zero flag stale otoceny...
Ok takze zakladni varianty:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'TESTKEMPSTON'
in A,(0x1F) ; 2:11 testkempston ( mask -- bool ) bool: port(kempston) cor +1c 0c=
or L ; 1:4 testkempston
add A, 0x01 ; 2:7 testkempston
sbc HL, HL ; 2:15 testkempston
; seconds: 0 ;[ 7:37]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'TESTKEMPSTON _0EQ'
in A,(0x1F) ; 2:11 testkempston 0= ( mask -- bool ) bool: port(kempston) cor +1c 0c<>
or L ; 1:4 testkempston 0=
sub 0xFF ; 2:7 testkempston 0=
sbc HL, HL ; 2:15 testkempston 0=
; seconds: 0 ;[ 7:37]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'TESTKEMPSTON_ZF'
in A,(0x1F) ; 2:11 testkempston zf ( mask -- ) zf: port(kempston) cor +1c 0c=
or L ; 1:4 testkempston zf
inc A ; 1:4 testkempston zf
ex DE, HL ; 1:4 testkempston zf
pop DE ; 1:10 testkempston zf
; seconds: 0 ;[ 6:33]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$
Se znalosti masky:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEMPSTON_FIRE) TESTKEMPSTON'
push DE ; 1:11 0xFFEF testkempston ( -- bool ) bool: port(kempston) 0xFFEF cand 0c<>
ex DE, HL ; 1:4 0xFFEF testkempston
in A,(0x1F) ; 2:11 0xFFEF testkempston
and 0x10 ; 2:7 0xFFEF testkempston "fire"
add A, 0xFF ; 2:7 0xFFEF testkempston
sbc HL, HL ; 2:15 0xFFEF testkempston
; seconds: 0 ;[10:55]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEMPSTON_FIRE & __TESTKEMPSTON_RIGHT) TESTKEMPSTON'
push DE ; 1:11 0xFFEF & 0xFFFE testkempston ( -- bool ) bool: port(kempston) 0xFFEF & 0xFFFE cor +1c 0c=
ex DE, HL ; 1:4 0xFFEF & 0xFFFE testkempston
in A,(0x1F) ; 2:11 0xFFEF & 0xFFFE testkempston
or 0xEE ; 2:7 0xFFEF & 0xFFFE testkempston "multibit test"
inc A ; 1:4 0xFFEF & 0xFFFE testkempston
sub 0x01 ; 2:7 0xFFEF & 0xFFFE testkempston
sbc HL, HL ; 2:15 0xFFEF & 0xFFFE testkempston
; seconds: 1 ;[11:59]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(blabla) TESTKEMPSTON'
push DE ; 1:11 blabla testkempston ( -- bool ) bool: port(kempston) blabla cor +1c 0c=
ex DE, HL ; 1:4 blabla testkempston
in A,(0x1F) ; 2:11 blabla testkempston
or blabla ; 2:7 blabla testkempston
inc A ; 1:4 blabla testkempston
sub 0x01 ; 2:7 blabla testkempston
sbc HL, HL ; 2:15 blabla testkempston
; seconds: 0 ;[11:59]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH((adresa)) TESTKEMPSTON'
push DE ; 1:11 (adresa) testkempston ( -- bool ) bool: port(kempston) (adresa) cor +1c 0c=
ex DE, HL ; 1:4 (adresa) testkempston
ld HL, (adresa) ; 3:16 (adresa) testkempston
in A,(0x1F) ; 2:11 (adresa) testkempston
or L ; 1:4 (adresa) testkempston
inc A ; 1:4 (adresa) testkempston
sub 0x01 ; 2:7 (adresa) testkempston
sbc HL, HL ; 2:15 (adresa) testkempston
; seconds: 0 ;[13:72]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$
v podstate to same s "NOT"
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEMPSTON_FIRE) TESTKEMPSTON _0EQ'
push DE ; 1:11 0xFFEF testkempston 0= ( -- bool ) bool: port(kempston) 0xFFEF cand 0c=
ex DE, HL ; 1:4 0xFFEF testkempston 0=
in A,(0x1F) ; 2:11 0xFFEF testkempston 0=
and 0x10 ; 2:7 0xFFEF testkempston 0= "fire"
sub 0x01 ; 2:7 0xFFEF testkempston 0=
sbc HL, HL ; 2:15 0xFFEF testkempston 0=
; seconds: 1 ;[10:55]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEMPSTON_FIRE & __TESTKEMPSTON_RIGHT) TESTKEMPSTON _0EQ'
push DE ; 1:11 0xFFEF & 0xFFFE testkempston 0= ( -- bool ) bool: port(kempston) 0xFFEF & 0xFFFE cor +1c 0c<>
ex DE, HL ; 1:4 0xFFEF & 0xFFFE testkempston 0=
in A,(0x1F) ; 2:11 0xFFEF & 0xFFFE testkempston 0=
or 0xEE ; 2:7 0xFFEF & 0xFFFE testkempston 0= "multibit test"
inc A ; 1:4 0xFFEF & 0xFFFE testkempston 0=
add A, 0xFF ; 2:7 0xFFEF & 0xFFFE testkempston 0=
sbc HL, HL ; 2:15 0xFFEF & 0xFFFE testkempston 0=
; seconds: 1 ;[11:59]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(blabla) TESTKEMPSTON _0EQ'
push DE ; 1:11 blabla testkempston 0= ( -- bool ) bool: port(kempston) blabla cor +1c 0c<>
ex DE, HL ; 1:4 blabla testkempston 0=
in A,(0x1F) ; 2:11 blabla testkempston 0=
or blabla ; 2:7 blabla testkempston 0=
inc A ; 1:4 blabla testkempston 0=
add A, 0xFF ; 2:7 blabla testkempston 0=
sbc HL, HL ; 2:15 blabla testkempston 0=
; seconds: 1 ;[11:59]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH((adresa)) TESTKEMPSTON _0EQ'
push DE ; 1:11 (adresa) testkempston 0= ( -- bool ) bool: port(kempston) (adresa) cor +1c 0c<>
ex DE, HL ; 1:4 (adresa) testkempston 0=
ld HL, (adresa) ; 3:16 (adresa) testkempston 0=
in A,(0x1F) ; 2:11 (adresa) testkempston 0=
or L ; 1:4 (adresa) testkempston 0=
inc A ; 1:4 (adresa) testkempston 0=
add A, 0xFF ; 2:7 (adresa) testkempston 0=
sbc HL, HL ; 2:15 (adresa) testkempston 0=
; seconds: 0 ;[13:72]
A pak jeste PUSH_TESTKEMPSTON_ZF co jsem uz popisoval ze nerozlisuje pokud je testovan jediny bit, ale ukazi jak dokaze udelat malou analyzu te masky kdyz testujeme VLEVO+VPRAVO a nebo je nejvyssi bit nula coz naznacuje ze programator nepochopil ze ta maska ma byt invertovana.
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEMPSTON_FIRE) TESTKEMPSTON_ZF'
in A,(0x1F) ; 2:11 0xFFEF testkempston zf ( -- ) zf: port(kempston) 0xFFEF cor +1c
or 0xEF ; 2:7 0xFFEF testkempston zf "fire"
inc A ; 1:4 0xFFEF testkempston zf
; seconds: 0 ;[ 5:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(__TESTKEMPSTON_RIGHT & __TESTKEMPSTON_LEFT) TESTKEMPSTON_ZF'
.warning Nonsence mask! Each bit that is tested must be 0 and the others 1.
in A,(0x1F) ; 2:11 0xFFFE & 0xFFFD testkempston zf ( -- ) zf: port(kempston) 0xFFFE & 0xFFFD cor +1c
or 0xFC ; 2:7 0xFFFE & 0xFFFD testkempston zf "???"
inc A ; 1:4 0xFFFE & 0xFFFD testkempston zf
; seconds: 1 ;[ 5:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0xFC) TESTKEMPSTON_ZF'
.warning Nonsence mask! Each bit that is tested must be 0 and the others 1.
in A,(0x1F) ; 2:11 0xFC testkempston zf ( -- ) zf: port(kempston) 0xFC cor +1c
or 0xFC ; 2:7 0xFC testkempston zf "???"
inc A ; 1:4 0xFC testkempston zf
; seconds: 0 ;[ 5:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0xF3) TESTKEMPSTON_ZF'
.warning Nonsence mask! Each bit that is tested must be 0 and the others 1.
in A,(0x1F) ; 2:11 0xF3 testkempston zf ( -- ) zf: port(kempston) 0xF3 cor +1c
or 0xF3 ; 2:7 0xF3 testkempston zf "???"
inc A ; 1:4 0xF3 testkempston zf
; seconds: 0 ;[ 5:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x7F) TESTKEMPSTON_ZF'
.warning Nonsence mask! Each bit that is tested must be 0 and the others 1.
in A,(0x1F) ; 2:11 0x7F testkempston zf ( -- ) zf: port(kempston) 0x7F cor +1c
or 0x7F ; 2:7 0x7F testkempston zf "7th bit"
inc A ; 1:4 0x7F testkempston zf
; seconds: 0 ;[ 5:22]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0x7E) TESTKEMPSTON_ZF'
.warning Nonsence mask! Each bit that is tested must be 0 and the others 1.
in A,(0x1F) ; 2:11 0x7E testkempston zf ( -- ) zf: port(kempston) 0x7E cor +1c
or 0x7E ; 2:7 0x7E testkempston zf "???"
inc A ; 1:4 0x7E testkempston zf
; seconds: 1 ;[ 5:22]
No a pak jsem pracoval na spojeni tech 4 zakladnich slov (TESTKEMPSTON, TESTKEMPSTON_0EQ, PUSH_TESTKEMPSTON, PUSH_TESTKEMPSTON_0EQ,) s IF WHILE a UNTIL. Nebudu ukazovat vygenerovany kod protoze tam je navic jen odskok a pripadne break label u UNTIL.
Na cely kod "BEGIN" smycek jsem hrabal a zmenil info ze to ukazuje... aha tak neco radsi ukazu, bude to snazsi:
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'BEGIN PUSH(0xFD) TESTKEMPSTON UNTIL'
begin101: ; begin(101)
in A,(0x1F) ; 2:11 0xFD testkempston until(101) ( -- ) port(kempston) 0xFD invert and 0<> if
and 0x02 ; 2:7 0xFD testkempston until(101) "left"
jp z, begin101 ; 3:10 0xFD testkempston until(101)
break101: ; 0xFD testkempston until(101)
; seconds: 0 ;[ 7:28]
Pridaval jsem za ty smyckovy slova do informaci zavorku s cislem smycky, puvodne jsem tam nemel nic a nebo to mel oddelenne mezerou takze to vypadalo jako PUSH(101).
Trochu jsem se sam dostal, protoze ty hodnoty generuji AZ kdyz generuji instrukce, takze v tokenech nic neni, zadny parametr navic a celou dobu tokenu je tam jen 100. Takze jsem mel omylem puvodne neco jako
Kód:
define({UNTIL},{dnl
__{}__ADD_TOKEN({__TOKEN_UNTIL},{until(BEGIN_STACK)},$@){}dnl
}){}dnl
Ale to by pro vsechny slova melo ve vysledku (100).
Takze jsem to pridal az v __ASM_TOKEN... kde se generuji ty instrukce
Kód:
__{}define({__INFO},__COMPILE_INFO(BEGIN_STACK)){}dnl
ale to taky nefunguje... protoze si M4 mysli ze je to parametr makra/fce __COMPILE_INFO, takze se to nevypise!
Spravne je az
Kód:
__{}define({__INFO},__COMPILE_INFO{(BEGIN_STACK)}){}dnl
Hrabal jsem na to hromadne s cca 100 zmenama a musel jsem to neustale oprvovat tak snad jsem neco nerozdrbal.
U makra __ASM_BEGIN to musi byt trosku jinak protoze tam se to inkrementuje, takze to musi byt pred definici __INFO.
A ve vyseledku je to stejne cele spatne protoze mohou existovat spojena slova jako ...WHILE_NECO... a ta zavorka nebude u WHILE ale na konci. Reseni by bylo to mit jak jsem ukazoval u definice tokenu UNTIL a delat zmenu BEGIN_STACK v tomhle case a pridavat k tokenum dalsi parametr s cislem smycky. Ale nechce se me v tom drbat a neco rozhasit...
PS: Reseni ohledne toho vyssiho bajtu co se posila u IN a OUT me napadlo, ze pokud to bude zname (u PUSH) a bude to nula tak to ignorovat, protoze to bude signal ze to neni potreba. Klavesnice to vyzaduje, ale ani jeden bajt neni nulovy. Jen kdybych chtel cist vsechny radky najednou... a i pak by to slo protoze je na to specialni slovo TESTKEY a nemusim to delat pres PORTFETCH.
Existuje nejaky hardware u ktereho je ten horni bajt dulezity a zaroven muze byt nula?
PPS: Dalsi reseni je generovat vsude
if _neco_
xor a
endif
in a,(port)
a mit tak moznost to zmenit globalne. A nemuset kvuli tomu muset duplikovat vsechen kod/slova.
A nebo se na to uplne... .)
PPPS: Tohle me trosku vadi
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'BEGIN IF BREAK THEN'
begin101: ; begin(101)
ld A, H ; 1:4 if
or L ; 1:4 if
ex DE, HL ; 1:4 if
pop DE ; 1:10 if
jp z, else101 ; 3:10 if
jp break101 ; 3:10 break(101)
else101 EQU $ ; then = endif
endif101: ; then
; seconds: 0 ;[10:42]
Jde mi o to ze IF je delane na IF ELSE THEN, ale kdyz ELSE vetev neni a jedine co je za IF je instrukce skoku tak staci otocit priznak u skoku na ELSE a vypadne jedna instrukce. Ale tenhle pripad je celkem vyjmecny a u te ukazky nesmyslny, protoze jde nahradit WHILE
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'BEGIN WHILE'
begin101: ; begin(101)
ld A, H ; 1:4 while(101)
or L ; 1:4 while(101)
ex DE, HL ; 1:4 while(101)
pop DE ; 1:10 while(101)
jp z, break101 ; 3:10 while(101)
; seconds: 0 ;[ 7:32]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'BEGIN _0EQ WHILE'
begin101: ; begin(101)
;[7:32] 0= while(101) ( x -- ) 0 == HL variant: zero
ld A, L ; 1:4 0= while(101)
or H ; 1:4 0= while(101)
ex DE, HL ; 1:4 0= while(101)
pop DE ; 1:10 0= while(101)
jp nz, break101 ; 3:10 0= while(101)
; seconds: 0 ;[ 7:32]
a dalsi odskok je jen z definovaneho slova/fce/podprogramu. A osetrit to by znamenalo to udelat ve vsech slovech s IF... Hlidat ze je tam IF_BREAK_THEN. Takze i KEMPSTON_IF_BREAK_THEN atd. A to se mi fakt nechce takze... to necham plavat. Komu to vadi muze si to delat rucne.. .)