Jinak si stale hraji s FORTHem. Smycky jsou podle me uz dostatecne otestovane a spis delam neco s tim prevodem tokenu na jine tokeny.
Par novych slov jako treba:
PUSH4 - Nema to uplne nejefektivnejsi kod, duvo proc jsem to potreboval je ze po PUSH3 kdyz nasleduje PUSH se nic nedelo.
Takze kdyz pak nasledovalo neco XXX co chce 2 parametry tak videl jen jeden a misto PUSH2_XXX to udelalo PUSH_XXX.
Konkretne slo o smycku. Kdyz to dost bolelo, ze znam konec i zacatek a pritom to generovalo kod ze znam jen zacatek,
coz je zrovna nejmene dulezity parametr.
Druhy duvod byl ze samotne push je neefektivni, protoze je to licha hodnota pro ulozeni a generuje to zbytecny "ex DE,HL".
Takze pokud po PUSH4 nasleduje PUSH tak to vytvori celkem efektivni PUSH2 z prvnich dvou hodnot
a pak nasleduje PUSH3 z poslednich 2 hodnot a nove hodnoty. A PUSH3 je dostatecny pocet pro vsechny dalsi XXX
jako treba MOVE, ktery si vezme tri hodnoty FROM,TO,TIMES.
PUSH3_CMOVE, aby to "ladilo" s PUSH3_MOVE.
U te fronty tokenu se me podarilo editovat i predposledni token. To bylo docela zajimave, protoze zatim byl parametr vzdy konstantu "__TOKEN_COUNT" a ted jsem musel mit "eval(__TOKEN_COUNT-1)". A to me prestalo fungovat, protoze vstup uz nebyla konstanta, ale prvne se to muselo vypocitat, nez se to stalo vstupem. Nevim jak, ale po ruznych pokusech s obalenim do {} a nebo vyjmutim { }tohle_se_udela_drive{ }. To zacalo fungovat az jsem to vyzkousel resit az v podfunkci. Takze by to melo bezet obecne pro jakoukoliv promenou hodnotu.
Slo o tokeny jako
PUSH4 CMOVE kde lze resit pres pomocne promenne a nebo vytvorit novy token PUSH3_CMOVE. Nacist do nej hodnoty tez uz nove z predchoziho tokenu, protoze uz je zvednute __TOKEN_COUNT. A pak editovat predchozi token, v podstate ho vytvorit znovu bez poslednich 3 parametru.
No a u toho jsem zjistil ze by bylo vhodne mit neco jako je makro "shift", ktere maze prvni parametr. Ale reverzne, aby to mazalo posledni parametr. A dale mit neco jako $-1, kdy by to vypsalo zase reverzne posledni parametr. Nebo $-2 predposledni atd.
Protoze napr. pokud mam neco co ma jeden parametr a vznikne PUSH_XXX
Tak u PUSH XXX je to snadne, proste jen zmeni nazev posledniho tokenu na PUSH_XXX a upravi info na "puvodne" + " xxx", parametry zustavaji.
PUSH2 XXX uz manipuluje s poslednim parametrem predchoziho tokenu a pak ho odmaze.
PUSH3 XXX uz manipuluje s poslednim parametrem predchoziho tokenu a pak ho odmaze.
PUSH4 XXX uz manipuluje s poslednim parametrem predchoziho tokenu a pak ho odmaze.
No a pokazde jsem to psal jako
__LAST_TOKEN_ARRAY_2
__LAST_TOKEN_ARRAY_3
__LAST_TOKEN_ARRAY_4
a ted to mam vsude stejne
__LAST_TOKEN_REVERSE_1
a odmazani bylo predtim jako ze to pridam znova
__LAST_TOKEN_ARRAY_1
__LAST_TOKEN_ARRAY_1,__LAST_TOKEN_ARRAY_2
__LAST_TOKEN_ARRAY_1,__LAST_TOKEN_ARRAY_2,__LAST_TOKEN_ARRAY_3
a ted to mam vsude jako
__DROP_1(__BEFORELAST_TOKEN_ARRAY)
Manipulace s predposlednim je pres __LAST_TOKEN_REVERSE_2
__LAST_TOKEN_LAST_2 me vypise
__LAST_TOKEN_REVERSE_2,__LAST_TOKEN_REVERSE_1
tzn posledni 2 tokeny.
Je to vsude komplikovanejsi, protoze se osetruje kdyz je parametru mene. Vtipne je ze dalo docela dost prace vymyslet nazvy tech funkci aby to aspon trosku davalo smysl. A pritom byly co nejkratsi.
Bylo toho mnohem vic, ale nepamatuji si to. Delam na co zrovna narazim... .)
Kód:
dnl # u3 u2 u1 cmove
dnl # ( from_addr to_addr u -- )
dnl # If u is greater than zero, copy the contents of u consecutive characters at addr1 to the u consecutive characters at addr2.
define({PUSH3_CMOVE},{dnl
__{}__ADD_TOKEN({__TOKEN_PUSH3_CMOVE},{$1 $2 $3 cmove},$@){}dnl
}){}dnl
dnl
define({__ASM_TOKEN_PUSH3_CMOVE},{dnl
__{}define({__INFO},__COMPILE_INFO){}dnl
__{}ifelse($#,0,{
__{} .error .error {$0}($@): Missing from_address parameter!},
$#,1,{
__{} .error .error {$0}($@): Missing to_address parameter!},
$#,2,{
__{} .error .error {$0}($@): Missing u_times parameter!},
eval($#>3),1,{
__{} .error .error {$0}($@): Unexpected parameter!},
__SAVE_EVAL($3),0,{},
__SAVE_EVAL($3),1,{dnl
__{}ifelse(__IS_MEM_REF($1),1,{
__{} ld BC,format({%-12s},{$1}); 4:20 __INFO ( $1 $2 $3 -- )
__{} ld A,(BC) ; 1:7 __INFO},
__{}{
__{} ld A,format({%-12s},{($1)}); 3:13 __INFO ( $1 $2 $3 -- )})
__{}ifelse(__IS_MEM_REF($2),1,{dnl
__{} ld BC,format({%-12s},{$2}); 4:20 __INFO
__{} ld (BC),A ; 1:7 __INFO},
__{}{dnl
__{} ld format({%-16s},{($2),A}); 3:13 __INFO})},
__SAVE_EVAL($3),2,{dnl
__{}ifelse(__IS_MEM_REF($1),{1},{
__{} push HL ; 1:11 __INFO ( $1 $2 $3 -- )
__{} mov HL,format({%-12s},{$1}); 3:16 __INFO from_addr
__{} mov C,(HL) ; 1:7 __INFO
__{} inc HL ; 1:6 __INFO
__{} mov B,(HL) ; 1:7 __INFO},
__IS_MEM_REF($2),{1},{
__{} push HL ; 1:11 __INFO ( $1 $2 $3 -- )
__{} ld BC,format({%-12s},{($1)}); 4:20 __INFO},
__{}{
__{} ld BC,format({%-12s},{($1)}); 4:20 __INFO ( $1 $2 $3 -- )}){}dnl
__{}ifelse(__IS_MEM_REF($2),{1},{
__{} mov HL,format({%-12s},{$2}); 3:16 __INFO to_addr
__{} mov (HL),C ; 1:7 __INFO
__{} inc HL ; 1:6 __INFO
__{} mov (HL),B ; 1:7 __INFO
__{} pop HL ; 1:10 __INFO},
__{}__IS_MEM_REF($1),{1},{
__{} ld format({%-16s},{($2),BC}); 4:20 __INFO
__{} pop HL ; 1:10 __INFO)},
__{}{
__{} ld format({%-16s},{($2),BC}); 4:20 __INFO})},
{
push DE ; 1:11 __INFO ( $1 $2 $3 -- )
push HL ; 1:11 __INFO{}dnl
__{}define({_TMP_INFO},__INFO{ from_addr}){}__LD_REG16({HL},$1){}__CODE_16BIT{}dnl
__{}define({_TMP_INFO},__INFO{ to_addr}){}__LD_REG16({DE},$2,{HL},$1){}__CODE_16BIT{}dnl
__{}define({_TMP_INFO},__INFO{ u_times}){}__LD_REG16({BC},$3,{HL},$1,{DE},$2){}__CODE_16BIT{}dnl
__{}ifelse(__IS_NUM($3),0,{
ld A, C ; 1:4 __INFO
or B ; 1:4 __INFO
jr z, $+4 ; 2:7/12 __INFO})
ldir ; 2:u*21/16 __INFO
pop HL ; 1:10 __INFO
pop DE ; 1:10 __INFO}){}dnl
}){}dnl
Tady to mate pekne i s chybou u PUSH_CMOVE, to jsem delal taky nove.
Kód:
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0) CMOVE'
pop HL ; 1:10 0 cmove
pop DE ; 1:10 0 cmove ( b a -- )
;[ 2:20]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(aaa) CMOVE'
.error __ASM_TOKEN_PUSH_CMOVE(): Bad parameter!
;[ 0:0]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(1) CMOVE'
;[5:40] 1 cmove ( from_addr to_addr -- ) u = 1 char
ex DE, HL ; 1:4 1 cmove HL = from_addr, DE = to_addr
ldi ; 2:16 1 cmove 1x
pop HL ; 1:10 1 cmove
pop DE ; 1:10 1 cmove
;[ 5:40]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(2) PUSH(1) CMOVE'
;[8:42] 2 1 ( -- 2 1 )
push DE ; 1:11 2 1
push HL ; 1:11 2 1
ld DE, 0x0002 ; 3:10 2 1
ld HL, 0x0001 ; 3:10 2 1
ld A, H ; 1:4 cmove ( from_addr to_addr u_chars -- )
or L ; 1:4 cmove
ld B, H ; 1:4 cmove
ld C, L ; 1:4 cmove BC = u_chars
pop HL ; 1:10 cmove HL = from_addr
jr z, $+4 ; 2:7/12 cmove
ldir ; 2:u*21/16 cmove
pop HL ; 1:10 cmove
pop DE ; 1:10 cmove
;[17:95]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(3) PUSH(2) PUSH(1) CMOVE'
ld A,(3) ; 3:13 3 2 1 cmove ( 3 2 1 -- )
ld (2),A ; 3:13 3 2 1 cmove
;[ 6:26]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(3) PUSH(2) PUSH(0) CMOVE'
;[ 0:0]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(3) PUSH(2) PUSH(2) CMOVE'
ld BC,(3) ; 4:20 3 2 2 cmove ( 3 2 2 -- )
ld (2),BC ; 4:20 3 2 2 cmove
;[ 8:40]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(3) PUSH((2)) PUSH(2) CMOVE'
push HL ; 1:11 3 (2) 2 cmove ( 3 (2) 2 -- )
ld BC,(3) ; 4:20 3 (2) 2 cmove
mov HL,(2) ; 3:16 3 (2) 2 cmove to_addr
mov (HL),C ; 1:7 3 (2) 2 cmove
inc HL ; 1:6 3 (2) 2 cmove
mov (HL),B ; 1:7 3 (2) 2 cmove
pop HL ; 1:10 3 (2) 2 cmove
;[12:77]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH((3)) PUSH((2)) PUSH(2) CMOVE'
push HL ; 1:11 (3) (2) 2 cmove ( (3) (2) 2 -- )
mov HL,(3) ; 3:16 (3) (2) 2 cmove from_addr
mov C,(HL) ; 1:7 (3) (2) 2 cmove
inc HL ; 1:6 (3) (2) 2 cmove
mov B,(HL) ; 1:7 (3) (2) 2 cmove
mov HL,(2) ; 3:16 (3) (2) 2 cmove to_addr
mov (HL),C ; 1:7 (3) (2) 2 cmove
inc HL ; 1:6 (3) (2) 2 cmove
mov (HL),B ; 1:7 (3) (2) 2 cmove
pop HL ; 1:10 (3) (2) 2 cmove
;[14:93]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH((3)) PUSH(2) PUSH(2) CMOVE'
push HL ; 1:11 (3) 2 2 cmove ( (3) 2 2 -- )
mov HL,(3) ; 3:16 (3) 2 2 cmove from_addr
mov C,(HL) ; 1:7 (3) 2 2 cmove
inc HL ; 1:6 (3) 2 2 cmove
mov B,(HL) ; 1:7 (3) 2 2 cmove
ld (2),BC ; 4:20 (3) 2 2 cmove
pop HL ; 1:10 (3) 2 2 cmove)
;[12:77]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(3) PUSH(2) PUSH(3) CMOVE'
push DE ; 1:11 3 2 3 cmove ( 3 2 3 -- )
push HL ; 1:11 3 2 3 cmove
ld HL, 0x0003 ; 3:10 3 2 3 cmove from_addr
ld DE, 0x0002 ; 3:10 3 2 3 cmove to_addr
ld C, L ; 1:4 3 2 3 cmove u_times C = L = 0x03
ld B, H ; 1:4 3 2 3 cmove u_times B = H = 0x00
ldir ; 2:u*21/16 3 2 3 cmove
pop HL ; 1:10 3 2 3 cmove
pop DE ; 1:10 3 2 3 cmove
;[12:70]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(aaa) PUSH(2) PUSH(3) CMOVE'
push DE ; 1:11 aaa 2 3 cmove ( aaa 2 3 -- )
push HL ; 1:11 aaa 2 3 cmove
ld HL, aaa ; 3:10 aaa 2 3 cmove from_addr
ld DE, 0x0002 ; 3:10 aaa 2 3 cmove to_addr
ld BC, 0x0003 ; 3:10 aaa 2 3 cmove u_times
ldir ; 2:u*21/16 aaa 2 3 cmove
pop HL ; 1:10 aaa 2 3 cmove
pop DE ; 1:10 aaa 2 3 cmove
;[13:72]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(aaa) PUSH((2)) PUSH(3) CMOVE'
push DE ; 1:11 aaa (2) 3 cmove ( aaa (2) 3 -- )
push HL ; 1:11 aaa (2) 3 cmove
ld HL, aaa ; 3:10 aaa (2) 3 cmove from_addr
ld DE, (2) ; 4:20 aaa (2) 3 cmove to_addr
ld BC, 0x0003 ; 3:10 aaa (2) 3 cmove u_times
ldir ; 2:u*21/16 aaa (2) 3 cmove
pop HL ; 1:10 aaa (2) 3 cmove
pop DE ; 1:10 aaa (2) 3 cmove
;[14:82]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(aaa) PUSH((2)) PUSH(2) CMOVE'
push HL ; 1:11 aaa (2) 2 cmove ( aaa (2) 2 -- )
ld BC,(aaa) ; 4:20 aaa (2) 2 cmove
mov HL,(2) ; 3:16 aaa (2) 2 cmove to_addr
mov (HL),C ; 1:7 aaa (2) 2 cmove
inc HL ; 1:6 aaa (2) 2 cmove
mov (HL),B ; 1:7 aaa (2) 2 cmove
pop HL ; 1:10 aaa (2) 2 cmove
;[12:77]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(aaa) PUSH(bbb) PUSH(2) CMOVE'
ld BC,(aaa) ; 4:20 aaa bbb 2 cmove ( aaa bbb 2 -- )
ld (bbb),BC ; 4:20 aaa bbb 2 cmove
;[ 8:40]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$
PS: Jedna dalsi dulezita zmena byla v makrech pro vypis cisla
__HEX_L
__HEX_H
__HEX_HL
Stavalo se mi ze tam lezly neplatne hodnoty jako "abc+5", protoze jsem to nekde spatne osetril.
Takze nove jsem zmenil uz zmenenou vlastost, kdy predtim ty makra si uz nove hlidaly prazdny vstup na cokoliv co neni cislo se meni na prazdny vystup.
To me usetri nejaky if a mohu psat neco jako
__HEX_HL($1),0x0001,{jednicka}
misto
ifelse(__IS_MEM_REF($1),1,{ukazatel},
__IS_NUM($1),0,{nezname},
{ifelse(__HEX_HL($1),0x0001,{jendicka})})
Zvolil jsem trochu blbou hodnotu u -1 je to lepe videt, protoze to chytne jak -1 tak 0xFFFF nebo cokoliv jineho jako 32768+32767.
PPS: A jeste predtim jsem zmenil __IS_NUM na to aby chytal i __IS_MEM_REF. Takze jsem si musel vsude osetrit ze nedelam vstup jako __HEX_HL(($1+1) & 0xFF) nebo ($1+1)/2 a bud prohodit za 0xFF & ($1+1) nebo pridat plus
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ grep -R "(+("
stack.m4:__{}ifelse(__HEX_H(+($1+1)/2),{0x00},,{