OldComp.cz https://oldcomp.cz/ |
|
Macro FORTH https://oldcomp.cz/viewtopic.php?f=124&t=8564 |
Stránka 25 z 39 |
Autor: | _dworkin [ 07.11.2022, 17:25 ] |
Předmět příspěvku: | Re: Macro FORTH |
Takze to je univerzalni TO(name), ktere nacita bud jen z TOS nebo i z NOS. Pripadne optimalizovane PUSH_TO(name) nebo PUSHDOT_TO(name). Kód: ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/Nova_testovaci$ ../check_word.sh 'VALUE(_a) TO(_a)' ld (_a), HL ; 3:16 value _a ex DE, HL ; 1:4 value _a pop DE ; 1:10 value _a ld (_a), HL ; 3:16 to _a pop HL ; 1:10 to _a ex DE, HL ; 1:4 to _a VARIABLE_SECTION: _a: dw 0x0000 ;[10:60] dworkin@dw-A15:~/Programovani/ZX/Forth/Nova_testovaci$ ../check_word.sh 'DVALUE(_a) TO(_a)' ld (_a), HL ; 3:16 dvalue _a lo ld (_a+2), DE ; 4:20 dvalue _a hi pop HL ; 1:10 dvalue _a pop DE ; 1:10 dvalue _a ld (_a), HL ; 3:16 to _a lo ex DE, HL ; 1:4 to _a ld (_a+2), HL ; 3:16 to _a hi pop HL ; 1:10 to _a pop DE ; 1:10 to _a VARIABLE_SECTION: _a: ; dw 0x0000 dw 0x0000 ;[18:112] PS: Premyslim nad tim zda neomezit velikost tech cisel v pameti na nasobky dvou. Jako 2,4,6,...256. To ze to bude sudy umozni i drobne optimalizace v operacich PADD, PSUB atd. I nepatrne zrychleni. Odstrani mi to problem jak to udelat v tech promennych, kdy lichy pocet podporuje v podstate jen PCONSTANT. Pokud se to ma nastavovat tak to proste zabere o bajt vice... Nebo udelat dve verze, zkontrolovat si zda se licha pouziva a podle toho tam dat tu spravnou... nevim. Jak moc to bude nekomu vadit ,ze nemuze nema podporu pro jedno bajtova, nebo tribajtova, petibajtova cisla? |
Autor: | _dworkin [ 12.11.2022, 05:09 ] |
Předmět příspěvku: | Re: Macro FORTH |
Pridal jsem do tokenu moznost zjistit pocet parametru. Normalne na to existuje symbol $#. Takze kdyz napisete neco jako Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'define({NUM},{$#}) NUM(10,20,30)' 3 ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'define({NUM},{$#}) NUM(10,20)' 2 ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'define({NUM},{$#}) NUM(10)' 1 ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'define({NUM},{$#}) NUM()' 1 ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'define({NUM},{$#}) NUM' 0 ;[ 0:0] Prazdny retezec je ale bran taky jako parametr... Takze: Kód: define({__DIM},{ifelse({$#},1,{ifelse({$1},{},0,1)},{$#})}){}dnl Jenze tokeny maji parametry obaleny do zavorky, takze cele pole je jen jedna polozka. Takze se prvne vola makro co spojuje nazev makra s parametry. Neco jako __SPOJ(__ALL,(10,20,30)) co vytvori __ALL(10,20,30). A makro _ALL jen tiskne vsechny parametry. Kód: define({__GET_TOKEN_ITEMS}, {__DIM(__SPOJ({__ALL},defn(__TOKEN[}$1{].PARAM)))}){}dnl Tenhle zpusob nejak funguje. Ale staci nekde pridat {} a uz se to rozbali pozde atd. Pro zkratku je vytvoreno i makro __LAST_TOKEN_ITEMS, ktere je temer totozne z predchozim jen nema parametr, ale implicitni __TOKEN_COUNT, ktery ukazuje na posledni existujici token ve fronte. Kód: define({__LAST_TOKEN_ITEMS}, {__DIM(__SPOJ({__ALL},defn(__TOKEN[}__TOKEN_COUNT{].PARAM)))}){}dnl Proc jsem to potreboval? Protoze jsem si hral s temi dlouhymi cisly... Predelal jsem zpusob jak si ukladam informaci jak je dlouha ta promenna v pameti. Predtim jsem mel jen single a double. Ted se automaticky vytvori k promenne xxx makro __PSIZE_xxx ktere se nahrazuje za pocet bajtu. Potrebuje to slovo TO, ktere nahraje ze zasobniku data do dane promenne v pameti. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PCONSTANT(10,0,xxx) TO(xxx)' ; no_segment(10) ld (xxx), HL ; 3:16 to xxx ex DE, HL ; 1:4 to xxx ld (xxx+2), HL ; 3:16 to xxx pop HL ; 1:10 to xxx ld (xxx+4), HL ; 3:16 to xxx pop HL ; 1:10 to xxx ld (xxx+6), HL ; 3:16 to xxx pop HL ; 1:10 to xxx ld (xxx+8), HL ; 3:16 to xxx pop HL ; 1:10 to xxx pop DE ; 1:10 to xxx VARIABLE_SECTION: ; The padding will fill if the following X bytes overflow the 256 byte segment. ; Any use of Allot with a negative value exceeding this address will result in undefined behavior. if ((($ + 10 - 1) / 256) != ($/256)) DEFS (($/256)+1)*256 - $ endif xxx: ; = 0 dw 0x0000 dw 0x0000 dw 0x0000 dw 0x0000 dw 0x0000 ;[21:134] Tady je to jeste v pohode. Ale nez to tahame ze zasobniku do promenne tak to tam musime nejak dostat. A ze budeme sypat do zasobniku tolik dat jsem nepocital... Z tokenu PUSH PUSH to dela PUSH2, dalsi PUSH vytvori PUSH3, dalsi PUSH4 a dalsi to uz rozsekne na PUSH2 a PUSH3. Protoze nemam slovo pro PUSH5. A ted si jeste vemte ze diky tomu ze mam token PUSH3 a PUSH4 tak mam "duplicitne" vsechny pravidla pro "PUSH3 AND" a "PUSH4 AND" atd. Co se teda stane kdyz nasypu deset nul na zasobnik? Vytvori to PUSH2(0,0) PUSH2(0,0) PUSH2(0,0) PUSH4(0,0,0,0). A ani jeden netusi co lezi v registrech... takze vysledek je Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0) PUSH(0) PUSH(0) PUSH(0) PUSH(0) PUSH(0) PUSH(0) PUSH(0) PUSH(0) PUSH(0)' ;[7:40] 0 0 0 0 2drop ( -- 0 0 ) push DE ; 1:11 0 0 0 0 2drop push HL ; 1:11 0 0 0 0 2drop ld DE, 0x0000 ; 3:10 0 0 0 0 2drop ld L, D ; 1:4 0 0 0 0 2drop L = D = 0x00 ld H, L ; 1:4 0 0 0 0 2drop H = L = 0x00 ;[7:40] 0 0 0 0 2drop ( -- 0 0 ) push DE ; 1:11 0 0 0 0 2drop push HL ; 1:11 0 0 0 0 2drop ld DE, 0x0000 ; 3:10 0 0 0 0 2drop ld L, D ; 1:4 0 0 0 0 2drop L = D = 0x00 ld H, L ; 1:4 0 0 0 0 2drop H = L = 0x00 ;[7:40] 0 0 0 0 2drop ( -- 0 0 ) push DE ; 1:11 0 0 0 0 2drop push HL ; 1:11 0 0 0 0 2drop ld DE, 0x0000 ; 3:10 0 0 0 0 2drop ld L, D ; 1:4 0 0 0 0 2drop L = D = 0x00 ld H, L ; 1:4 0 0 0 0 2drop H = L = 0x00 push DE ; 1:11 0 0 0 0 ( -- 0 0 0 0 ) push HL ; 1:11 0 0 0 0 ld DE, 0x0000 ; 3:10 0 0 0 0 ld L, D ; 1:4 0 0 0 0 L = D = 0x00 ld H, L ; 1:4 0 0 0 0 H = L = 0x00 push DE ; 1:11 0 0 0 0 push HL ; 1:11 0 0 0 0 ;[30:182] No a z toho se me delalo spatne. Rikal jsem si ze proste pridam nejakou informaci jakou maji registry hodnotu po ukonceni makra, takze pristi to bude videt. Tohle se musi ale udelat PRO KAZDE MAKRO BEZ VYJIMKY. Docela dost prace. A ke vsemu jsem se dival jak mam udelany treba PUSH3 a nebylo by lehke tam na zacatek tohle pridat. Tak jsem zkusil napsat PUSHS(). Obecne slovo pro N parametru. Ukazalo se to nakonec lehci i kdyz jsem zvolil ne uplne idealni reseni. Ale latka kterou jsem musel preskocit byla fakt nizko jak vidite vysse. PUSHS reseni zabira presne polovinu bajtu. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,0,0,0,0,0,0,0,0,0)' push DE ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 ld HL, 0x0000 ; 3:10 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 push HL ; 1:11 0 0 0 0 0 0 0 0 0 0 ld E, H ; 1:4 0 0 0 0 0 0 0 0 0 0 E = H = 0x00 ld D, E ; 1:4 0 0 0 0 0 0 0 0 0 0 D = E = 0x00 ;[15:128] Udelal jsem to proste tak, ze pro kazde ukladane cislo zkoumam 3 reseni a volim to nejlepsi. Zda to ulozit do BC, DE a nebo HL. Pritom k tomu jeste pridavam test kolik bude jeste stat udelat posledni 2 hodnoty u kterych vim ze posledni musi byt v HL(TOS) a predposledni v DE(NOS). Nic vic. Takze by to slo udelat obcas i efektivneji... Nejhorsi je se podivat na ten vysledek a hned vidite, kde by to slo jeste vylepsit... 8x push HL? Co smycka pres B kdyz vim ze neblo pouzito a rychlost bych i ozelel atd. Zkousel jsem tomu hazet nejake data a i to BC se obcas pouzije. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,0,0,0,0,0,0,0,0,10)' push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push HL ; 1:11 0 0 0 0 0 0 0 0 0 10 ld DE, 0x0000 ; 3:10 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 push DE ; 1:11 0 0 0 0 0 0 0 0 0 10 ld HL, 0x000A ; 3:10 0 0 0 0 0 0 0 0 0 10 ;[16:130] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,0,0,10,0,0,0,0,0,10)' push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 push HL ; 1:11 0 0 0 10 0 0 0 0 0 10 ld DE, 0x0000 ; 3:10 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 ld HL, 0x000A ; 3:10 0 0 0 10 0 0 0 0 0 10 push HL ; 1:11 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 push DE ; 1:11 0 0 0 10 0 0 0 0 0 10 ;[16:130] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,0,0,10,0,0,10,0,0,(10))' push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) push HL ; 1:11 0 0 0 10 0 0 10 0 0 (10) ld DE, 0x0000 ; 3:10 0 0 0 10 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) ld HL, 0x000A ; 3:10 0 0 0 10 0 0 10 0 0 (10) push HL ; 1:11 0 0 0 10 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) push HL ; 1:11 0 0 0 10 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 10 0 0 10 0 0 (10) ld HL, (10) ; 3:16 0 0 0 10 0 0 10 0 0 (10) ;[19:146] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,0,0,(10),0,0,10,0,0,(10))' push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) push HL ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) ld DE, 0x0000 ; 3:10 0 0 0 (10) 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) ld HL, (10) ; 3:16 0 0 0 (10) 0 0 10 0 0 (10) push HL ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) ld BC, 0x000A ; 3:10 0 0 0 (10) 0 0 10 0 0 (10) push BC ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) push DE ; 1:11 0 0 0 (10) 0 0 10 0 0 (10) ;[19:146] Fajn... ale to taky znamena ze musim upravit i ty tokenove pravidla. Nakonec jsem se rozhodl tak ze vsechna slova jako PUSH2 nebo PUSH3 budou rovnou volat PUSHS a pravidla budou jen pro PUSHS. A prave proto potrebuji znat pocet polozek. Protoze "PUSHS(15) AND" nedela nic, zato "PUSHS(15,3) AND" by melo vytvorit PUSHS(3). Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(15) AND' push DE ; 1:11 15 ex DE, HL ; 1:4 15 ld HL, 15 ; 3:10 15 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 ;[12:59] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(15,3) AND' push DE ; 1:11 15 3 and ex DE, HL ; 1:4 15 3 and ld HL, 3 ; 3:10 15 3 and ;[ 5:25] Jedno pravidlo pro PUSH4 a AND vypadalo takto Kód: __LAST_TOKEN_NAME:$1:__LAST_TOKEN_IS_PTR_REVERSE_2_1, __TOKEN_PUSH4:__TOKEN_AND:0, {__SET_TOKEN({__TOKEN_PUSH3}, __LAST_TOKEN_INFO{ }$2,__DROP_2_PAR(__LAST_TOKEN_ARRAY),__EVAL_S16(&,__LAST_TOKEN_LAST_2_PAR))}, Pro PUSHS a AND to vypada takto Kód: __LAST_TOKEN_NAME:eval(__LAST_TOKEN_ITEMS>1):$1:__LAST_TOKEN_IS_PTR_REVERSE_2_1, __TOKEN_PUSHS:1:__TOKEN_AND:0, {__SET_TOKEN(__TOKEN_PUSHS, __LAST_TOKEN_INFO{ }$2,ifelse(__LAST_TOKEN_ITEMS,2,,__DROP_2_PAR(__LAST_TOKEN_ARRAY){,})__EVAL_S16(&,__LAST_TOKEN_LAST_2_PAR))}, Zalomil jsem to tady tak ze prvni radek nacita aktualni data, druhy radek je co musi odpovidat aby se volal treti radek. V kodu to mam jen oddelene carkama. Je to zatim jen jedine testovaci pravidlo po PUSHS co mam... PS: To predavani informaci o hodnotach v registrech by se ale stejne melo jednou udelat. Jen to nechci uplne rozdrbavat kdyz nemam uplne ani otestovano, kde mam jeste chyby diky tokenizaci. V hlave mam reseni ze se pro kazdy __ASM_TOKEN_name musi na zacatek udelat nejaky BEGIN a na konci nejaky END. BEGIN by slo udelat skriptem automaticky vsude. END uz ne, ale dobra zprava je ze by slo udelat tak, aby sam BEGIN zjistil zda v predchozim slove byl nejaky END nebo ne. Reseni je spousta, staci treba aby BEGIN nastavil nejakou vlajku a END ji rusi. Makra BEGIN a END by byla udelana tak, ze v END by se nastavoval vystup. A BEGIN by registry vyprazdnilo na prazdny retezec a nebo nacetlo predchozi hodnoty co byly v makru END. No nic, 3 rano..., cas jit spat. Zitra je rusna sobota v praci, nastesti uz ve dvou. |
Autor: | _dworkin [ 13.11.2022, 17:53 ] |
Předmět příspěvku: | Re: Macro FORTH |
Pridana tokenova pravidla pro PUSHS + ... FILL (tady mam u PUSH4+FILL chybu kdy to generuje PUSH4_FILL token, ale existuje jen PUSH3_FILL) UMDIVMOD SMDIVREM FMDIVMOD MADD AND dvou cisel AND jedno cislo je 0 (druhe muze byt i pointer) AND jedno cislo je -1 (druhe muze byt i pointer) OR dvou cisel OR jedno cislo je 0 (druhe muze byt i pointer) OR jedno cislo je -1 (druhe muze byt i pointer) XOR dvou cisel XOR jedno cislo je 0 (druhe muze byt i pointer), tohle jsem predtim zapomnel udelat s PUSH4 a mozna i PUSH3, atd. ADD dvou cisel ADD jedno cislo je 0 (druhe muze byt i pointer) SUB dvou cisel SUB druhe cislo je 0 (prvni muze byt i pointer) MUL dvou cisel MUL jedno cislo je 0 (druhe muze byt i pointer) MUL jedno cislo je 1 (druhe muze byt i pointer) MUL jedno cislo je -1 (druhe muze byt i pointer) DIV dvou cisel DIV prvni cislo je 0 (druhe muze byt i pointer) DIV druhe cislo je 1 (prvni muze byt i pointer) MOD dvou cisel UMOD dvou cisel DIVMOD dvou cisel UDIVMOD dvou cisel MMUL dvou cisel UMMUL dvou cisel MAX dvou cisel MIN dvou cisel EQ dvou cisel NE dvou cisel LT dvou cisel GT dvou cisel LE dvou cisel GE dvou cisel UEQ dvou cisel UNE dvou cisel ULT dvou cisel UGT dvou cisel ULE dvou cisel UGE dvou cisel U tech porovnani jsem opravil vystup kdy se me TRUE generovalo jako 1 jak to dela M4, misto -1 jak to chce FORTH. <irony>Prekvapive si toho nikdo za celou dobu nevsimnul... </irony> Vsechny vetveni jsou delane pro 0 a nebo nenulovou hodnotu, takze rozdil by byl jen pokud vystup pouzije nejaky AND. PS: Asi pred tydnem me na githubu pribyl treti lajk! .) |
Autor: | _dworkin [ 14.11.2022, 02:50 ] |
Předmět příspěvku: | Re: Macro FORTH |
Vytvoreno slovo PVALUE (takze uz neni jen PPUSH_VALUE), pouziva uvnitr slovo TO, ktere nacita polozky ze zasobniku na adresu v pameti. Pridany kombinace PUSHS+... CMOVE MOVE SWAP WITHIN PUSH PUSHS STORE _2STORE FETCH _2FETCH VALUE DVALUE a konecne i PVALUE. Posledni kombinace slov nebyla jen o pravidlech tokenu, ale dala hodne zabrat. Musel jsem vytvorit pomocna makra __IS_ARRAY_NUM ... overuje zda vsechny polozky pole jsou cisla (a ne pointery nebo nezname promenne) __FIRST_X_PAR ... vypise oddelene carkama prvnich X polozek pole __LAST_X_PAR ...vypise oddelene carkama poslednich X polozek pole __ARRAY2HEXSTRING ...udela z pole hex retezec a s nema jsem to uz nejak dal dohromady. Po overeni, ze je vse ok se pak uvnitr tokenovych pravidel vola PPUSH_VALUE(bytes,hex_string,val_name). Protoze ani ten nema token a jen vytvari nekolik tokenu pro NO_SEGMENT,CREATE a PHEXPUSH_COMMA_REC. A ten pak postupne teprve tvori tokeny PUSHS_COMMA. Pokud mate radi barvicky: https://github.com/DW0RKiN/M4_FORTH/commit/e7e6b5464a6215a44efad30e8c2324b28509e1b7 Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS((0x6655),0x1122,0x1122,0x2244) PVALUE(8,_a) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: (0x6655) 0x1122 0x1122 0x2244 ;items: 4 ;param: ((0x6655),0x1122,0x1122,0x2244) ;array1: >(0x6655)< ;array2: >0x1122< ;array3: >0x1122< ;array: (0x6655),0x1122,0x1122,0x2244 push DE ; 1:11 (0x6655) 0x1122 0x1122 0x2244 ( -- (0x6655) 0x1122 0x1122 0x2244 ) push HL ; 1:11 (0x6655) 0x1122 0x1122 0x2244 ld DE, 0x1122 ; 3:10 (0x6655) 0x1122 0x1122 0x2244 ld HL, (0x6655) ; 3:16 (0x6655) 0x1122 0x1122 0x2244 push HL ; 1:11 (0x6655) 0x1122 0x1122 0x2244 push DE ; 1:11 (0x6655) 0x1122 0x1122 0x2244 ld HL, 0x2244 ; 3:10 (0x6655) 0x1122 0x1122 0x2244 ; p8value _a ld (_a), HL ; 3:16 p8value _a ex DE, HL ; 1:4 p8value _a ld (_a+2), HL ; 3:16 p8value _a pop HL ; 1:10 p8value _a ld (_a+4), HL ; 3:16 p8value _a pop HL ; 1:10 p8value _a ld (_a+6), HL ; 3:16 p8value _a pop HL ; 1:10 p8value _a pop DE ; 1:10 p8value _a VARIABLE_SECTION: ; The padding will fill if the following X bytes overflow the 256 byte segment. ; Any use of Allot with a negative value exceeding this address will result in undefined behavior. if ((($ + 8 - 1) / 256) != ($/256)) DEFS (($/256)+1)*256 - $ endif _a: ; dw 0x0000 dw 0x0000 dw 0x0000 dw 0x0000 ;[30:188] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS((0x6655),0x1122,0x1122,0x2244) PVALUE(6,_a) __SHOW_TOKEN(1)' _a EQU __create__a ; name: __TOKEN_PUSHS ; info: (0x6655) ;items: 1 ;param: ((0x6655)) ;array1: >(0x6655)< ;array2: >< ;array3: >< ;array: (0x6655) push DE ; 1:11 (0x6655) ex DE, HL ; 1:4 (0x6655) ld HL, (0x6655) ; 3:16 (0x6655) ; no_segment(6) push HL ; 1:11 0x2244 , 0x1122 , ... 0x1122 , default version ld HL, 0x1122 ; 3:10 0x1122 , ld (__create__a+2),HL; 3:16 0x1122 , ld (__create__a+4),HL; 3:16 0x1122 , add HL, HL ; 1:11 0x2244 , 0x2244 = 0x1122+0x1122 ld (__create__a),HL; 3:16 0x2244 , pop HL ; 1:10 0x2244 , 0x1122 , ... 0x1122 , ;[15:90] 0x2244 , 0x1122 , ... 0x1122 , VARIABLE_SECTION: ; The padding will fill if the following X bytes overflow the 256 byte segment. ; Any use of Allot with a negative value exceeding this address will result in undefined behavior. if ((($ + 6 - 1) / 256) != ($/256)) DEFS (($/256)+1)*256 - $ endif __create__a: ; dw 0x2244 dw 0x1122 dw 0x1122 ;[20:121] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0x1122,0x2244) PVALUE(6,_a) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0x1122 0x2244 ;items: 2 ;param: (0x1122,0x2244) ;array1: >0x1122< ;array2: >0x2244< ;array3: >< ;array: 0x1122,0x2244 ;[8:42] 0x1122 0x2244 ( -- 0x1122 0x2244 ) push DE ; 1:11 0x1122 0x2244 push HL ; 1:11 0x1122 0x2244 ld DE, 0x1122 ; 3:10 0x1122 0x2244 ld HL, 0x2244 ; 3:10 0x1122 0x2244 ; p6value _a ld (_a), HL ; 3:16 p6value _a ex DE, HL ; 1:4 p6value _a ld (_a+2), HL ; 3:16 p6value _a pop HL ; 1:10 p6value _a ld (_a+4), HL ; 3:16 p6value _a pop HL ; 1:10 p6value _a pop DE ; 1:10 p6value _a VARIABLE_SECTION: ; The padding will fill if the following X bytes overflow the 256 byte segment. ; Any use of Allot with a negative value exceeding this address will result in undefined behavior. if ((($ + 6 - 1) / 256) != ($/256)) DEFS (($/256)+1)*256 - $ endif _a: ; dw 0x0000 dw 0x0000 dw 0x0000 ;[21:124] PS: Mam pocit jako bych stavel sam pyramidu, ale z dlazebnich kostek (protoze ty unesu). A uz si vubec nepamatuji, kde ktera kostka je. |
Autor: | _dworkin [ 14.11.2022, 17:15 ] |
Předmět příspěvku: | Re: Macro FORTH |
Zkousel jsem napsat jinou metodu pro ukladani dat na zasobnik. Dela to slovo PUSHS. Ta puvodni je jak jsem uz rikal ze to porovna tri hodnoty a vybere tu s nejmensi cenou. Prioritu ma pri shodne hodnote HL, pak DE a nakonec BC. Cena se pocita z ceny kolik stoji to ulozit do toho registru + cena za ulozeni predposledni hodnoty do DE a posledni hodnoty do HL (v tomhle poradi, ani jsem to nezkousel prohazovat coz muze byt nekdy vyhodnejsi). Problem ktery jsem tu neukazoval je, ze me to obcas nacetlo dost nestastne nejakou hodnotu do HL, kdyz by BC bylo vyhodnejsi. Takze se muze stat, ze to nacte do HL, potom do HL nacte neco bliz koncove a pak klidne do nevyuziteho BC nacte co bylo prvne v HL... Reseni co me napadlo bylo, udelat stinove makro co ma stejne pravdila a jen zjisti zda do BC neco nacitame a pokud ano tak to tam nacte a opusti stinovou funkci. Pak se vola normalni, ale uz s tim ze v BC mame nastavenou hodnotu. Ukazka BEZ a pak SE stinovou funkci. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0x3333,10,(10),0x3333,0,(10))' push DE ; 1:11 0x3333 10 (10) 0x3333 0 (10) push HL ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld HL, 0x3333 ; 3:10 0x3333 10 (10) 0x3333 0 (10) push HL ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld DE, 0x000A ; 3:10 0x3333 10 (10) 0x3333 0 (10) push DE ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld HL, (10) ; 3:16 0x3333 10 (10) 0x3333 0 (10) push HL ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld BC, 0x3333 ; 3:10 0x3333 10 (10) 0x3333 0 (10) push BC ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld E, D ; 1:4 0x3333 10 (10) 0x3333 0 (10) E = D = 0x00 ;[19:116] 0 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0x3333,10,(10),0x3333,0,(10))' push DE ; 1:11 0x3333 10 (10) 0x3333 0 (10) push HL ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld BC, 0x3333 ; 3:10 0x3333 10 (10) 0x3333 0 (10) push BC ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld DE, 0x000A ; 3:10 0x3333 10 (10) 0x3333 0 (10) push DE ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld HL, (10) ; 3:16 0x3333 10 (10) 0x3333 0 (10) push HL ; 1:11 0x3333 10 (10) 0x3333 0 (10) push BC ; 1:11 0x3333 10 (10) 0x3333 0 (10) ld E, D ; 1:4 0x3333 10 (10) 0x3333 0 (10) E = D = 0x00 ;[16:106] 0 seconds Pak jsem premyslel jak udelat v M4 bruteforce prohledavani... ale narazel jsem na problem s tim ze potrebuji lokalni promenne u rekurzivniho makra a nechtelo se mi delat jmena typu "hodnota_COUNTER". Pouzit zasobnik pushdef a popdef me nenapadlo hm... muzu zkusit zda to nebude rychlejsi... Vyresil jsem to tak ze jsou lokalni promenne ulozene jako vstupni parametry. Omezeni je ze jdou menit jen pri volani dalsi rekurze. Mam to jako FUNKCE(CENA,HL,DE,BC,pole_hodnot_co_se_uklada). Takze prvni polozka pole je az $5. Na konci se zjisti zda CENA je mensi nez __CHECK_PUSH_BEST a pokud ano, tak se __CHECK_PUSH_BEST aktualizuje. Ale vysledek byl fakt POMALY. Protoze se to exponencionalne zpomaluje. A navic vysledky byly stejne jako ma prvni funkce. A pokud oddelam predvypocet BC tak i horsi... Zkusil jsem to drobne upravit aby nepokracoval ve vypoctu kdyz $1 je vetsi nez __CHECK_PUSH_BEST a bylo to skoro 3x rychlejsi, ale stale to neni moc pouzitelne. Jen pro jiny zpusob jak resit vypocet pro mensi hloubku pro prvni metodu. Prvni je prvni metoda s BC a druhe je Bruteforce bez BC a treti to same s orezavanim. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,(10),0,10,10,0,10,0,(10))' push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld BC, 0x000A ; 3:10 0 (10) 0 10 10 0 10 0 (10) ld E, B ; 1:4 0 (10) 0 10 10 0 10 0 (10) E = B = 0x00 ld D, E ; 1:4 0 (10) 0 10 10 0 10 0 (10) D = E = 0x00 push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld HL, (10) ; 3:16 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) ;[17:133] 1 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,(10),0,10,10,0,10,0,(10))' push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld HL, (10) ; 3:16 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld BC, 0x000A ; 3:10 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) ;[18:135] 259 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSHS(0,(10),0,10,10,0,10,0,(10))' push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld HL, (10) ; 3:16 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld BC, 0x000A ; 3:10 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) ;[18:135] 90 seconds Zvonil me budik tak to dnes nedopisi... PS: Tak aspon jen poznamku ze i to BF s BC neumi byt optimalni, protoze zalezi i zda na zacatku to udela ld BC, neco ld DE, neco a nebo ld DE, neco ld BC, neco protoze to nekdy jde zapsat jako ld DE, 0x0010 ld B,E ld C,E nebo naopak. Pak neumi uprostred si vyhmatnout nejakou hodnotu co zrovna nepotrebuje, ale bude pozdeji a ted je nejlepsi cas ji odnekud vzit... jako napr. ld H,C PPS: Jsem fakt prekvapeny ze ta prvni metoda s dodatkem v BC je tak efektivni. Kód: define({__BRUTEFORCE_CHECK_PUSH_REC},{dnl
__{}ifelse(dnl __{}eval($1>=__CHECK_PUSH_BEST),1,{}, __{}$#,5,{dnl __{}__{}__LD_REG16({HL},$5,{HL},$2,{DE},$3,{BC},$4){}dnl __{}__{}ifelse(eval(__CHECK_PUSH_BEST>($1+__PRICE_16BIT)),1,{define({__CHECK_PUSH_BEST},eval($1+__PRICE_16BIT))}){}dnl __{}}, __{}$#,6,{dnl __{}__{}__RESET_ADD_LD_REG16{}dnl __{}__{}__ADD_LD_REG16({DE},$5,{HL},$2,{DE},$3,{BC},$4){}dnl __{}__{}__ADD_LD_REG16({HL},$6,{HL},$2,{DE},$5,{BC},$4){}dnl __{}__{}ifelse(eval(__CHECK_PUSH_BEST>($1+__SUM_PRICE_16BIT)),1,{define({__CHECK_PUSH_BEST},eval($1+__SUM_PRICE_16BIT))}){}dnl __{}}, __{}{dnl __{}__{}__LD_REG16({HL},$5,{HL},$2,{DE},$3,{BC},$4){}dnl __{}__{}$0(eval($1+__PRICE_16BIT),$5,$3,$4,shift(shift(shift(shift(shift($@)))))){}dnl __{}__{}__LD_REG16({DE},$5,{HL},$2,{DE},$3,{BC},$4){}dnl __{}__{}$0(eval($1+__PRICE_16BIT),$2,$5,$4,shift(shift(shift(shift(shift($@)))))){}dnl __{}__{}__LD_REG16({BC},$5,{HL},$2,{DE},$3,{BC},$4){}dnl __{}__{}$0(eval($1+__PRICE_16BIT),$2,$3,$5,shift(shift(shift(shift(shift($@)))))){}dnl __{}}){}dnl }){}dnl dnl dnl dnl define({__BRUTEFORCE_PUSHS_REC},{dnl __{}ifelse(dnl __{}$#,1,{dnl __{}__{}__LD_REG16({HL},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}__CODE_16BIT}, __{}$#,2,{dnl __{}__{}__LD_REG16({DE},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}__CODE_16BIT{}dnl __{}__{}__LD_REG16({HL},$2,{HL},__REG_HL,{DE}, $1,{BC},__REG_BC){}__CODE_16BIT}, __{}{dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__LD_REG16({HL},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC(__PRICE_16BIT, $1,__REG_DE,__REG_BC,shift($@)){}dnl __{}__{}define({__CHECK_PUSH_HL_BEST},__CHECK_PUSH_BEST){}dnl __{}__{}dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__LD_REG16({DE},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC(__PRICE_16BIT,__REG_HL, $1,__REG_BC,shift($@)){}dnl __{}__{}define({__CHECK_PUSH_DE_BEST},__CHECK_PUSH_BEST){}dnl __{}__{}dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__LD_REG16({BC},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC(__PRICE_16BIT,__REG_HL,__REG_DE, $1,shift($@)){}dnl __{}__{}define({__CHECK_PUSH_BC_BEST},__CHECK_PUSH_BEST){}dnl __{}__{}dnl __{}__{}ifelse(eval((__CHECK_PUSH_BC_BEST<__CHECK_PUSH_DE_BEST)&&(__CHECK_PUSH_BC_BEST<__CHECK_PUSH_HL_BEST)),1,{dnl __{}__{}__{}__LD_REG16({BC},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}__CODE_16BIT{}dnl __{}__{}__{}define({__REG_BC},$1) __{}__{}__{} push BC ; 1:11 __INFO}, __{}__{}eval(__CHECK_PUSH_DE_BEST<__CHECK_PUSH_HL_BEST),1,{dnl __{}__{}__{}__LD_REG16({DE},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}__CODE_16BIT{}dnl __{}__{}__{}define({__REG_DE},$1) __{}__{}__{} push DE ; 1:11 __INFO}, __{}__{}{dnl __{}__{}__{}__LD_REG16({HL},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}__CODE_16BIT{}dnl __{}__{}__{}define({__REG_HL},$1) __{}__{}__{} push HL ; 1:11 __INFO{}dnl __{}__{}}){}dnl __{}__{}$0(shift($@)){}dnl __{}}){}dnl }){}dnl |
Autor: | _dworkin [ 15.11.2022, 18:26 ] |
Předmět příspěvku: | Re: Macro FORTH |
Vyzkousel jsem prepsat tu BF rekurzi, abych mel v poli jen jednu polozku navic a registry si drzel ve vlastnich zasobnicich pomoci pushdef a popdef a na cas to nemelo zadny vliv. Predhodil jsem tomu trolovaci data kdy nalakam DE a HL na koncove hodnoty a pak prohazuji dve konstanty. Tohle odrovna ten jednoduchy algoritmus, protoze se nepokusi uvolnit DE a nebo HL a vytrvale bude znovu a znovu nacitat hodnoty do BC. BF to odhali, ale nevim proc uvolni HL misto DE, coz by melo byt o 6 taktu kratsi!!! Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;items: 8 ;param: (0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0x3333,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;[23:150] 43 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;items: 8 ;param: (0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0x3333,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;[23:144] 43 seconds Oh, ted vidim ze druha (nova) varianta to prece udelala spravne, nekde mam teda chybu v puvodnim kodu... Cas jit do prace. |
Autor: | _dworkin [ 16.11.2022, 03:20 ] |
Předmět příspěvku: | Re: Macro FORTH |
Hmm... zitra mam celodenni takze nemam cas se v tom moc vrtat. Dival jsem se na ten kod a nenasel jsem chybu. Tak jsem se dival na ten novy, zda to nedela lepsi kod protoze je blbe ten a ani tam jsem nenasel chybu. Vzhledem k tomu ze jsem to psal skoro cely copy+paste tak tomu fakt nerozumim. Puvodni ma vetsi sanci byt spatne (mohou byt oba), protoze ten algoritmus by to mel najit... Napsal jsem jeste kratsi verzi testu a zase si to prohodi i kdyz maji stejny vysledek. Mimochodem treti verze je psana rucne s jednim trikem co me napadl v pondeli v praci. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0 (10) ;items: 7 ;param: (0,(10),0x1431,0x3333,0x1431,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ;[22:133] 14 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0 (10) ;items: 7 ;param: (0,(10),0x1431,0x3333,0x1431,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) ;[22:133] 53 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ cat smaz.txt | ../count.sh push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) ex (SP),HL ; 1:19 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ;[20:142] Je o 2 bajty krasti, ale o 9 taktu pomalejsi. Novy kod vypada takto, muzete porovnat s tim co jsem ukazal predtim. Kód: define({__BRUTEFORCE_CHECK_PUSH_REC2},{dnl
__{}ifelse(dnl __{}eval($1>=__CHECK_PUSH_BEST),1,{}, __{}$#,2,{dnl __{}__{}__LD_REG16({HL},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}ifelse(eval(__CHECK_PUSH_BEST>($1+__PRICE_16BIT)),1,{define({__CHECK_PUSH_BEST},eval($1+__PRICE_16BIT))}){}dnl __{}}, __{}$#,3,{dnl __{}__{}__RESET_ADD_LD_REG16{}dnl __{}__{}__ADD_LD_REG16({DE},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__ADD_LD_REG16({HL},$3,{HL},__REG_HL,{DE}, $2,{BC},__REG_BC){}dnl __{}__{}ifelse(eval(__CHECK_PUSH_BEST>($1+__SUM_PRICE_16BIT)),1,{define({__CHECK_PUSH_BEST},eval($1+__SUM_PRICE_16BIT))}){}dnl __{}}, __{}{dnl __{}__{}__LD_REG16({HL},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}pushdef({__REG_HL}){}dnl __{}__{}define({__REG_HL},$2){}dnl __{}__{}$0(eval($1+__PRICE_16BIT),shift(shift($@))){}dnl __{}__{}popdef({__REG_HL}){}dnl __{}__{}dnl __{}__{}__LD_REG16({DE},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}pushdef({__REG_DE}){}dnl __{}__{}define({__REG_DE},$2){}dnl __{}__{}$0(eval($1+__PRICE_16BIT),shift(shift($@))){}dnl __{}__{}popdef({__REG_DE}){}dnl __{}__{}dnl __{}__{}__LD_REG16({BC},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}pushdef({__REG_BC}){}dnl __{}__{}define({__REG_BC},$2){}dnl __{}__{}$0(eval($1+__PRICE_16BIT),shift(shift($@))){}dnl __{}__{}popdef({__REG_BC}){}dnl __{}}){}dnl }){}dnl dnl dnl dnl define({__BRUTEFORCE_PUSHS_REC2},{dnl __{}ifelse(dnl __{}$#,1,{dnl __{}__{}__LD_REG16({HL},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}__CODE_16BIT}, __{}$#,2,{dnl __{}__{}__LD_REG16({DE},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}__CODE_16BIT{}dnl __{}__{}__LD_REG16({HL},$2,{HL},__REG_HL,{DE}, $1,{BC},__REG_BC){}__CODE_16BIT}, __{}{dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__LD_REG16({HL},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}pushdef({__REG_HL}){}dnl __{}__{}define({_REG_HL},$1){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC2(__PRICE_16BIT,shift($@)){}dnl __{}__{}popdef({__REG_HL}){}dnl __{}__{}define({__CHECK_PUSH_HL_BEST},__CHECK_PUSH_BEST){}dnl __{}__{}dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__LD_REG16({DE},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}pushdef({__REG_DE}){}dnl __{}__{}define({_REG_DE},$1){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC2(__PRICE_16BIT,shift($@)){}dnl __{}__{}popdef({__REG_DE}){}dnl __{}__{}define({__CHECK_PUSH_DE_BEST},__CHECK_PUSH_BEST){}dnl __{}__{}dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__LD_REG16({BC},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}pushdef({__REG_BC}){}dnl __{}__{}define({_REG_BC},$1){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC2(__PRICE_16BIT,shift($@)){}dnl __{}__{}popdef({__REG_BC}){}dnl __{}__{}define({__CHECK_PUSH_BC_BEST},__CHECK_PUSH_BEST){}dnl __{}__{}dnl __{}__{}ifelse(eval((__CHECK_PUSH_BC_BEST<__CHECK_PUSH_DE_BEST)&&(__CHECK_PUSH_BC_BEST<__CHECK_PUSH_HL_BEST)),1,{dnl __{}__{}__{}__LD_REG16({BC},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}__CODE_16BIT{}dnl __{}__{}__{}define({__REG_BC},$1) __{}__{}__{} push BC ; 1:11 __INFO}, __{}__{}eval(__CHECK_PUSH_DE_BEST<__CHECK_PUSH_HL_BEST),1,{dnl __{}__{}__{}__LD_REG16({DE},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}__CODE_16BIT{}dnl __{}__{}__{}define({__REG_DE},$1) __{}__{}__{} push DE ; 1:11 __INFO}, __{}__{}{dnl __{}__{}__{}__LD_REG16({HL},$1,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}__CODE_16BIT{}dnl __{}__{}__{}define({__REG_HL},$1) __{}__{}__{} push HL ; 1:11 __INFO{}dnl __{}__{}}){}dnl __{}__{}$0(shift($@)){}dnl __{}}){}dnl }){}dnl |
Autor: | _dworkin [ 17.11.2022, 15:16 ] |
Předmět příspěvku: | Re: Macro FORTH |
Napsal jsem jeste v noci treti verzi, kde jsem pouzil myslenku, ze nema cenu zjistovat (volat fci) pro kazdou hodnotu pole ktery ze tri registru HL,DE,BC se ma na tu hodnotu nastavit, kdyz uz u prvni hodnoty se to cele spocita az do konce. Takze pokud si nekam ulozim optimalni "cestu", tak usetrim cca 25% casu. Cestu ukladam jako retezec cisel kde "1" znaci HL, "2" znaci DE a "3" BC. Musel jsem pro to napsat rekurzivni makro co to prevede na kod, to jsem pozdeji upravil tak ze to tiskne jen do zarazky "-". Pomoci tisku toho retezce cesty jsem zjistil ze me v prubehu vypoctu najde nejlepsi reseni a pote ho zahodi a "cena" toho reseni je jina nez by mela byt. Takze jsem to postupne rucne krokoval, az nasel chybu mimo muj kod. Byla schovana v __LD_REG16(). Pokud je totiz pozadovano nacteni dat z pointeru tak to resi jina vetev kodu a tam jsem zapomel vynulovat __BYTES_16BIT a __CLOCKS_16BIT. Takze i kdyz to spravne generovalo kod tak pokud byl kod prazdny retezec, protoze registr uz drzel hodnotu tak cena byla stejna jako z predchoziho vypoctu... To me spravilo prvni funkci, uz generuje spravny kod, ale duvod proc se to lisilo od druhe stale nechapu. Mely byt chybne oba nebo ani jeden. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;items: 8 ;param: (0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0x3333,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;[23:144] 14 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0 (10) ;items: 7 ;param: (0,(10),0x1431,0x3333,0x1431,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) ;[22:133] 7 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ Protoze i pres zrychleni ten vypocet zpomaluje exponencialne tak jsem napsal ctvrtou variantu, kde pouzivam kombinaci BruteForce rekurze a puvodniho algoritmu kde se testuje jak to pak sedi na konci. Pro kazdou hodnotu se to vola se ctyrmi nasledujicimi parametry ke kterym se pridaji 2 koncove parametry a to co bylo mezitim se vynecha. Takove opakovane BF nad 6 hodnotama. Tim to dokaze odhalit to 0x1431, 0x3333, 0x1431, 0x3333, posledni_DE, posledni_HL. Proto jsem potreboval aby ta tisknouci funkce umela "-". Problem byl stale vstup typu 0,0,0,0,0,0,0, ... 0,0,0,0x8765,0x4321. Generovalo se to prilis dlouho. Nakonec jsem pridal do BruteForce kodu pred zjistovanim ktery ze tri registru je nejlepsi varianta test na kazdy registr, zda uz nedrzi vyslednou hodnotu. Kód: __{}__{}__REG_HL,$3,{$0($1,$2{}1,shift(shift(shift($@))))}, Pokud drzi nema cenu zjistovat rekurzivne ktery je nejlepsi a rovnou vybrat ten co uz tu hodnotu ma. (Ma to drobnou chybku ze to delam pres porovnani retezcu a ne hodnot, takze pokud je to cislo zapsane jinak tak to nepozna, a kdyz bych pridal zase ze porovnavam hodnoty tak se to zase spomali, ale mozna ne o tolik, musim vyzkouset. Hmm.. ale zase nemusim resit zda neporovnavam jablka s hruskama, hodnotu a odkaz nebo jmeno promenne)__{}__{}__REG_DE,$3,{$0($1,$2{}2,shift(shift(shift($@))))}, __{}__{}__REG_BC,$3,{$0($1,$2{}3,shift(shift(shift($@))))}, Tohle vylepseni me v podstate vygeneruje kod pro to cislo se spousty nul na zacatku okamzite a zrychli to i ten testovaci vypocet. Takze tam kde jsem mel cca 43 sekund puvodne, pak 14 sekund, to jsou ted 4 sekundy. (Je to shodne s verzi bez posledniho 0x3333) Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;items: 8 ;param: (0,(10),0x1431,0x3333,0x1431,0x3333,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0x3333,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0x3333 0 (10) ;[23:144] 4 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0x1431,0x3333,0x1431,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0x1431 0x3333 0x1431 0 (10) ;items: 7 ;param: (0,(10),0x1431,0x3333,0x1431,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0x1431< ;array: 0,(10),0x1431,0x3333,0x1431,0,(10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld HL, (10) ; 3:16 0 (10) 0x1431 0x3333 0x1431 0 (10) push HL ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x1431 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld BC, 0x3333 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) push BC ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) push DE ; 1:11 0 (10) 0x1431 0x3333 0x1431 0 (10) ld DE, 0x0000 ; 3:10 0 (10) 0x1431 0x3333 0x1431 0 (10) ;[22:133] 4 seconds PS: Kdyz uz mam tu cestu tak by stalo za uvahu tam nejak implementovat ten trik s tim BC co se predpocita dopredu a pak umisti na zacatek. Tady to mohu vytahnout z te cesty. A nejen BC. Kód: define({__BRUTEFORCE_CHECK_PUSH_REC3},{dnl
__{}ifelse(dnl __{}eval($1>=__CHECK_PUSH_BEST),1,{}, dnl __{}$#,3,{dnl dnl __{}__{}__LD_REG16({HL},$3,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl dnl __{}__{}ifelse(eval(__CHECK_PUSH_BEST>($1+__PRICE_16BIT)),1,{dnl dnl __{}__{}__{}define({__CHECK_PUSH_BEST},eval($1+__PRICE_16BIT)){}dnl dnl __{}__{}__{}define({__CHECK_PUSH_BEST_PATH},$2){}dnl dnl errprint({ dnl },__CHECK_PUSH_BEST:__CHECK_PUSH_BEST_PATH{}){}dnl dnl __{}__{}}){}dnl dnl __{}}, __{}$#,4,{dnl __{}__{}__RESET_ADD_LD_REG16{}dnl __{}__{}__ADD_LD_REG16({DE},$3,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__ADD_LD_REG16({HL},$4,{HL},__REG_HL,{DE}, $3,{BC},__REG_BC){}dnl __{}__{}ifelse(eval(__CHECK_PUSH_BEST>($1+__SUM_PRICE_16BIT)),1,{dnl __{}__{}__{}define({__CHECK_PUSH_BEST},eval($1+__SUM_PRICE_16BIT)){}dnl __{}__{}__{}define({__CHECK_PUSH_BEST_PATH},$2){}dnl __{}__{}}){}dnl __{}}, __{}{dnl __{}__{}ifelse(dnl __{}__{}__REG_HL,$3,{$0($1,$2{}1,shift(shift(shift($@))))}, __{}__{}__REG_DE,$3,{$0($1,$2{}2,shift(shift(shift($@))))}, __{}__{}__REG_BC,$3,{$0($1,$2{}3,shift(shift(shift($@))))}, __{}__{}{dnl __{}__{}__{}__LD_REG16({HL},$3,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}pushdef({__REG_HL}){}dnl __{}__{}__{}define({__REG_HL},$3){}dnl __{}__{}__{}$0(eval($1+__PRICE_16BIT),$2{}1,shift(shift(shift($@)))){}dnl __{}__{}__{}popdef({__REG_HL}){}dnl __{}__{}__{}dnl __{}__{}__{}__LD_REG16({DE},$3,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}pushdef({__REG_DE}){}dnl __{}__{}__{}define({__REG_DE},$3){}dnl __{}__{}__{}$0(eval($1+__PRICE_16BIT),$2{}2,shift(shift(shift($@)))){}dnl __{}__{}__{}popdef({__REG_DE}){}dnl __{}__{}__{}dnl __{}__{}__{}__LD_REG16({BC},$3,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__{}pushdef({__REG_BC}){}dnl __{}__{}__{}define({__REG_BC},$3){}dnl __{}__{}__{}$0(eval($1+__PRICE_16BIT),$2{}3,shift(shift(shift($@)))){}dnl __{}__{}__{}popdef({__REG_BC}){}dnl __{}__{}}){}dnl __{}}){}dnl }){}dnl dnl dnl dnl define({__PRINT_PUSH_REC3},{dnl __{}ifelse(dnl __{}$1,{},{dnl __{}__{}__LD_REG16({DE},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__CODE_16BIT{}dnl __{}__{}define({__REG_DE},$2){}dnl __{}__{}__LD_REG16({HL},$3,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__CODE_16BIT{}dnl __{}__{}define({__REG_HL},$3){}dnl __{}}, __{}substr($1,0,1),{-},{}, __{}substr($1,0,1),1,{dnl __{}__{}__LD_REG16({HL},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__CODE_16BIT{}dnl __{}__{}define({__REG_HL},$2) __{}__{} push HL ; 1:11 __INFO{}dnl __{}__{}$0(substr($1,1),shift(shift($@))){}dnl __{}}, __{}substr($1,0,1),2,{dnl __{}__{}__LD_REG16({DE},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__CODE_16BIT{}dnl __{}__{}define({__REG_DE},$2) __{}__{} push DE ; 1:11 __INFO{}dnl __{}__{}$0(substr($1,1),shift(shift($@))){}dnl __{}}, __{}substr($1,0,1),3,{dnl __{}__{}__LD_REG16({BC},$2,{HL},__REG_HL,{DE},__REG_DE,{BC},__REG_BC){}dnl __{}__{}__CODE_16BIT{}dnl __{}__{}define({__REG_BC},$2) __{}__{} push BC ; 1:11 __INFO{}dnl __{}__{}$0(substr($1,1),shift(shift($@))){}dnl __{}}){}dnl }){}dnl dnl dnl dnl define({__BRUTEFORCE_PUSHS_REC3},{dnl __{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__BRUTEFORCE_CHECK_PUSH_REC3(0,,$@){}dnl __{}__PRINT_PUSH_REC3(__CHECK_PUSH_BEST_PATH,$@){}dnl }){}dnl dnl dnl dnl define({__BRUTEFORCE_PUSHS_REC4},{dnl __{}ifelse($#,0,{}, __{}$#,1,{ __{}__{} .error {$0}($@)}, __{}$#,2,{__BRUTEFORCE_PUSHS_REC3($@)}, __{}$#,3,{__BRUTEFORCE_PUSHS_REC3($@)}, __{}$#,4,{__BRUTEFORCE_PUSHS_REC3($@)}, __{}$#,5,{__BRUTEFORCE_PUSHS_REC3($@)}, __{}$#,6,{__BRUTEFORCE_PUSHS_REC3($@)}, __{}{dnl __{}__{}define({__CHECK_PUSH_BEST},0x7FFFFFFF){}dnl __{}__{}__BRUTEFORCE_CHECK_PUSH_REC3(0,,$1,$2,$3,$4,__LAST_REG_DE,__LAST_REG_HL){}dnl __{}__{}__PRINT_PUSH_REC3(substr(__CHECK_PUSH_BEST_PATH,0,1){-},$@){}dnl __{}__{}$0(shift($@)){}dnl __{}}){}dnl }){}dnl |
Autor: | _dworkin [ 17.11.2022, 23:42 ] |
Předmět příspěvku: | Re: Macro FORTH |
Tak jsem to kompletne zase prepsal (musel jsem vytvorit promennou pro celou cestu a fci pro pocitani kolik stoji vypis te cesty) a promazal, aby byla jen jedna metoda. Ted to zkousi postupne pridat na zacatek nastaveni HL, pak DE a nakonec BC a pokud je to lepsi nez to bylo predtim tak to zapise. Ukazka vzdy dvou "inverznich" vstupu, kdy se jednou to vyplati prohodit a podruhe ne. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(80,(10),80,0,0,80,0,80,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 80 (10) 80 0 0 80 0 80 (10) ;items: 9 ;param: (80,(10),80,0,0,80,0,80,(10)) ;array1: >80< ;array2: >(10)< ;array3: >80< ;array: 80,(10),80,0,0,80,0,80,(10) push DE ; 1:11 80 (10) 80 0 0 80 0 80 (10) push HL ; 1:11 80 (10) 80 0 0 80 0 80 (10) ld DE, 0x0050 ; 3:10 80 (10) 80 0 0 80 0 80 (10) push DE ; 1:11 80 (10) 80 0 0 80 0 80 (10) ld HL, (10) ; 3:16 80 (10) 80 0 0 80 0 80 (10) push HL ; 1:11 80 (10) 80 0 0 80 0 80 (10) push DE ; 1:11 80 (10) 80 0 0 80 0 80 (10) ld C, D ; 1:4 80 (10) 80 0 0 80 0 80 (10) C = D = 0x00 ld B, C ; 1:4 80 (10) 80 0 0 80 0 80 (10) B = C = 0x00 push BC ; 1:11 80 (10) 80 0 0 80 0 80 (10) push BC ; 1:11 80 (10) 80 0 0 80 0 80 (10) push DE ; 1:11 80 (10) 80 0 0 80 0 80 (10) push BC ; 1:11 80 (10) 80 0 0 80 0 80 (10) ;[17:133] 1 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,(10),0,10,10,0,10,0,(10)) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 (10) 0 10 10 0 10 0 (10) ;items: 9 ;param: (0,(10),0,10,10,0,10,0,(10)) ;array1: >0< ;array2: >(10)< ;array3: >0< ;array: 0,(10),0,10,10,0,10,0,(10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld BC, 0x000A ; 3:10 0 (10) 0 10 10 0 10 0 (10) ld E, B ; 1:4 0 (10) 0 10 10 0 10 0 (10) E = B = 0x00 ld D, E ; 1:4 0 (10) 0 10 10 0 10 0 (10) D = E = 0x00 push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) ld HL, (10) ; 3:16 0 (10) 0 10 10 0 10 0 (10) push HL ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) push DE ; 1:11 0 (10) 0 10 10 0 10 0 (10) push BC ; 1:11 0 (10) 0 10 10 0 10 0 (10) ;[17:133] 1 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(0,10,0,0,0,0,0,0,10) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 10 0 0 0 0 0 0 10 ;items: 9 ;param: (0,10,0,0,0,0,0,0,10) ;array1: >0< ;array2: >10< ;array3: >0< ;array: 0,10,0,0,0,0,0,0,10 push DE ; 1:11 0 10 0 0 0 0 0 0 10 push HL ; 1:11 0 10 0 0 0 0 0 0 10 ld HL, 0x000A ; 3:10 0 10 0 0 0 0 0 0 10 ld E, H ; 1:4 0 10 0 0 0 0 0 0 10 E = H = 0x00 ld D, E ; 1:4 0 10 0 0 0 0 0 0 10 D = E = 0x00 push DE ; 1:11 0 10 0 0 0 0 0 0 10 push HL ; 1:11 0 10 0 0 0 0 0 0 10 push DE ; 1:11 0 10 0 0 0 0 0 0 10 push DE ; 1:11 0 10 0 0 0 0 0 0 10 push DE ; 1:11 0 10 0 0 0 0 0 0 10 push DE ; 1:11 0 10 0 0 0 0 0 0 10 push DE ; 1:11 0 10 0 0 0 0 0 0 10 ;[14:117] 1 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH4(10,0,10,10,10,10,10,10,0) __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 10 0 10 10 10 10 10 10 0 ;items: 9 ;param: (10,0,10,10,10,10,10,10,0) ;array1: >10< ;array2: >0< ;array3: >10< ;array: 10,0,10,10,10,10,10,10,0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 push HL ; 1:11 10 0 10 10 10 10 10 10 0 ld DE, 0x000A ; 3:10 10 0 10 10 10 10 10 10 0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 ld L, D ; 1:4 10 0 10 10 10 10 10 10 0 L = D = 0x00 ld H, L ; 1:4 10 0 10 10 10 10 10 10 0 H = L = 0x00 push HL ; 1:11 10 0 10 10 10 10 10 10 0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 push DE ; 1:11 10 0 10 10 10 10 10 10 0 ;[14:117] 1 seconds dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ Za me je tohle uz docela prijatelna fce a uz se me nechce v tom vice drbat, dokud nezjistim nejake chyby... PS: Mozna tak jedine pridat tam ten trik s EX (SP),HL. Ale ten bude efektivni jen pokud budou vstupy same pointery. PPS: A taky by to chtelo mozna trosku ocesat ten zivelny kod... .) |
Autor: | _dworkin [ 22.11.2022, 04:17 ] |
Předmět příspěvku: | Re: Macro FORTH |
Stale pracuji na tom prevodu PUSH,PUSH2,PUSH3,PUSH4 na PUSHS. Samostatne tokeny __TOKEN_PUSH,__TOKEN_PUSH2, atd uz nemam. Pri volani PUSH2(10,30) se rovnou vytvari token __TOKEN_PUSHS(10,30). Slova PUSH2, PUSH3 atd jsem nerusil, takze se nemusi menit zdrojaky, ale ciste reseni by bylo asi mit jen PUSH a PUSHS. Na __ASM_TOKEN_PUSH2 atd, coz je primo zdrojak pro to slovo se nic nemeni, vola ho primo __ASM_TOKEN_PUSHS pokud zrovna obsahuje 2 parametry. Problem co mam je spravit pravidla v tokenech, kde se to XXX+PUSH?+XXX jen hemzi. Rozdelil jsem to na dve varianty. PUSHS+XXX a XXX+PUSHS. Prvni varianta se zadava stejnym zpusobem jak dosud (proste se pridava do fronty jeden token za druhym, pripadne se edituje predposledni atd.), zato druha varianta kde se nejake slovo spojuje s PUSHS se musela udelat uplne nove. Tesne pred pocatkem vytvarenim zdrojaku pro frotnu tokenu se jeste jednou projede od prvniho tokenu cela fronta a porovnavaji se predchozi a nasledujici token a pokud to pasuje na XXX+PUSHS tak se predchozi token jen zmeni na __TOKEN_NOPE, ktery vyvari prazdny zdrojak. Je to skoro jako smazani tokenu, jen nemenim cislovani ani nedelam mezery. Hledam cestu nejmensiho odporu. A nasledujici se prejmenuje na __TOKEN_XXX_PUSHS. Proc to delam? Protoze prvne PUSHS+XXX slova maji mnohem lepsi optimalizace. Napriklad PUSHS(10,0) DO. Je mnohem vic dulezitejsi nez napriklad FETCH PUSHS(10,0). Obe kombinace se daji ale optimalizovat. Pokud udelam token pro FETCH_PUSHS, tak najednou musim vytvorit nasobne vic tokenu. Token pro FETCH_PUSHS_DO pravidlo pro FETCH_PUSHS_ADD pravidlo pro FETCH_PUSHS+PUSHS=FETCH_PUSHS proste pro vsechny tokeny typu PUSHS+XXX. Proto misto toho abych udelal sum(XXX+PUSHS)*sum(PUSHS+XXX) tokenu jsem to rozdelil. Jak ale rikam tech pravidel bylo hodne a je tam hodne pravidel jen pro jeden PUSH+XXX a musel jsem to upravovat na univerzalni PUSHS+XXX. Lepim to pomoci toho makra co jsem mel pro PUSHS, jen jsem zjistil ze obecny makro je vlastne "2DROP+PUSHS" a samotne PUSHS je uz specialni pripad kdy udelam push DE push HL volam makro pro 2DROP+PUSHS ktere uz ignoruje co bylo v DE a HL. Atd DUP+PUSHS je: push DE push HL push HL (to je to DUP) volam makro pro 2DROP+PUSHS... PS: Prejmenoval jsem pocitadlo tokenu z __TOKEN_COUNT na __CONT_TOKEN, protozeto bylo hloupe, kdyz __TOKEN_xxx je vyhrazeno pro slova, takze bych si blokoval slovo COUNT. Doslo me to az kdyz jsem vytvarel slovo __TOKEN_SUM, protoze COUNT protrebuji pouzit znovu jako index pro to druhe prochazeni fronty (nemusim pak menit pomocna makra) a __SUM_TOKEN drzi celkovy pocet. |
Autor: | _dworkin [ 22.11.2022, 05:34 ] |
Předmět příspěvku: | Re: Macro FORTH |
Lol, narazil jsem na tento kod a vypada to jako pekna divocina. Nedokazi zjistit zda je to dobre... Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'DUP PUSH(5,10) WITHIN IF __SHOW_TOKEN(1) __SHOW_TOKEN(2)' ; name: __TOKEN_DUP ; info: dup ;items: 0 ;param: () ;array1: >< ;array2: >< ;array3: >< ;array: ; name: __TOKEN_PUSH2_WITHIN_IF ; info: 5 10 within if ;items: 2 ;param: (5,10) ;array1: >5< ;array2: >10< ;array3: >< ;array: 5,10 ;[15:54] dup 5 10 within if ( x -- x ) true=(5<=x<10) ld A, L ; 1:4 dup 5 10 within if sub 0x05 ; 2:7 dup 5 10 within if ld B, H ; 1:4 dup 5 10 within if jr nc, $+3 ; 2:7/12 dup 5 10 within if dec B ; 1:4 dup 5 10 within if BA = TOS-(5) sub 0x05 ; 2:7 dup 5 10 within if ld A, B ; 1:4 dup 5 10 within if sbc A, 0x00 ; 2:7 dup 5 10 within if carry: BC - (10 - (5)) jp nc, else101 ; 3:10 dup 5 10 within if ;[15:54] 0 seconds Hmm... ale asi mozna je. Vypada to ze to resim pres (HL - 5) < (10-5) Asi bych to resil spis pomoci Kód: ld A, H ; 1:4 dup 5 10 within if or A ; 1:4 dup 5 10 within if jp nz, else101 ; 3:10 dup 5 10 within if ld A, L ; 1:4 dup 5 10 within if sub 0x05 ; 2:7 dup 5 10 within if sub 0x05 ; 2:7 dup 5 10 within if jp nc, else101 ; 3:10 dup 5 10 within if ;[13:46] Jen je to generovany pres ruzne vetveni a prvne se dela prvni polovina kodu, takze to nebude snadne to tam pridat... Hmm... navic to vraci carry protoze to posledni jp uz neni soucast kodu... takze by to vypadalo spis Kód: ld A, H ; 1:4 dup 5 10 within if
or A ; 1:4 dup 5 10 within if jr nz, $+7 ; 2:7/12 dup 5 10 within if ld A, L ; 1:4 dup 5 10 within if sub 0x05 ; 2:7 dup 5 10 within if sub 0x05 ; 2:7 dup 5 10 within if jp nc, else101 ; 3:10 dup 5 10 within if ;[12:43] |
Autor: | _dworkin [ 01.12.2022, 14:11 ] |
Předmět příspěvku: | Re: Macro FORTH |
Zjistil jsem ze nemam tokenova pravidla pro double + nejaka operace. Opravoval jsem kod pro pushdot_dand a kdyz jsem zadal "pushdot dand" tak se to nespojilo. Prvne jsem delal nova slova push2_dadd a push2_dsub, ktere jsem predelaval z pushdot_dadd a pushdot_dsub. Tohle me zjednodusilo dost pravidla. Protoze se snazim uplne zbavit tokenu pushdot a vse resit pres pushs. Pushdot se prevadi automaticky na pushs s dvema hodnotami. Nefunguje to jen u neznameho jmena. 32 bitovou hodnotu prevede M4 hned, odkaz se rozsekne na ((ptr)+2) a (ptr).Pokud se to misto pushdot zadava primo pres push2 tak to umoznuje i ruzne kombinace ukazatele a hodnoty pro jedno 32 bitove cislo. Udelal jsem proto i nova slova push2_dand, push2_dor a push2_dxor. Taky jednoduchym prevodem z pushdot_dand, ... Napsal jsem tokenova pravidla a zjistil ze je nemam uplne dobre. Prvne jsem treba zjistoval zda posledni 4 parametry v pushs jsou hodnoty a pokud ano volal funkci __EVAL_S32(). U and, or a xor jsem ale zjistil ze mi vlastne staci zjistit zda posledni 4 parametry v pushs nejsou ukazatele a volat dvakrat __EVAL_S16(), ktera to umi zpracovat i pro nezname 16 bitove hodnoty. Pak jsem to jeste vic zkomplikoval ze rovnou prvne testuji zda to pro kazdy par ta __EVAL_S16() dokaze spocitat. Napriklad "0 and (ukazatel)" je 0 a nebo "-1 and (ukazatel)" je (ukazatel). Opravil jsem __EVAL_S16() kdy neumel zpracovat "0 xor (ukazatel)" pripadne "(ukazatel) xor 0. Pak jsem resil ostatni pripady a doiteroval k dalsim pravidlum. Kdyz to nedokaze odchytit predchozi pravidla tak se tam nekde vyskytuje "(ukazatel1) operace (ukazatel2)" a nebo "(ukazatel1) operace spatna_hodnota", pripadne s prohozenyma parametrama. Takze prvne zjistim zda vyssi dvojslovo tu operaci zvladne a pokud ano tak mohu volat push_and, push_or nebo push_xor na nizsi 16 bitovou hodnotu. Tam to jeste upravuji tak ze do toho push_operace pokud to jde leze hodnota a ne ukazatel. Takze to pak vypada uvnitr nejak takto pushs(...,...,...,...,hi1 operace hi2,(lo1)) push_operace(lo2). Pokud je to naopak a mohu spocitat spodni 16 bitovou hodnotu, tak by me stacilo to prohodit parametry a nakonec volat jeden swap (ex DE,HL). Jenze to jde jeste lepe, takze jsem udelal slovo swap_push_operace_swap. A vysledek vypada jako kdyz jde spocitat hi. Radsi ukazi nejaky kod. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH2(0x33,0x0000,(656),(abc)) DAND __SHOW_TOKEN(1) __SHOW_TOKEN(2)' __eval_op_num_xxx_pasmo({&},{0x0000},{(abc)}) ; name: __TOKEN_PUSHS ; info: 0x33 0x0000 (656) (abc) dand ;items: 2 ;param: ((656), 0) ;array1: >(656)< ;array2: >0< ;array: (656),0 ; name: __TOKEN_SWAP_PUSH_AND_SWAP ; info: 0x33 0x0000 (656) (abc) dand ;items: 1 ;param: (0x33) ;array1: >0x33< ;array: 0x33 ;[9:52] 0x33 0x0000 (656) (abc) dand ( -- (656) 0 ) push DE ; 1:11 0x33 0x0000 (656) (abc) dand push HL ; 1:11 0x33 0x0000 (656) (abc) dand ld DE, (656) ; 4:20 0x33 0x0000 (656) (abc) dand ld HL, 0x0000 ; 3:10 0x33 0x0000 (656) (abc) dand ld A, 0x33 ; 2:7 0x33 0x0000 (656) (abc) dand and E ; 1:4 0x33 0x0000 (656) (abc) dand ld E, A ; 1:4 0x33 0x0000 (656) (abc) dand ld D, 0x00 ; 2:7 0x33 0x0000 (656) (abc) dand ; seconds: 0 ;[15:74] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH2(0,0x33,(656),(abc)) DAND __SHOW_TOKEN(1) __SHOW_TOKEN(2)' __eval_op_num_xxx_pasmo({&},{0},{(656)}) ; name: __TOKEN_PUSHS ; info: 0 0x33 (656) (abc) dand ;items: 2 ;param: ( 0,(abc)) ;array1: >0< ;array2: >(abc)< ;array: 0,(abc) ; name: __TOKEN_PUSH_AND ; info: 0 0x33 (656) (abc) dand ;items: 1 ;param: (0x33) ;array1: >0x33< ;array: 0x33 ;[8:48] 0 0x33 (656) (abc) dand ( -- 0 (abc) ) push DE ; 1:11 0 0x33 (656) (abc) dand push HL ; 1:11 0 0x33 (656) (abc) dand ld DE, 0x0000 ; 3:10 0 0x33 (656) (abc) dand ld HL, (abc) ; 3:16 0 0x33 (656) (abc) dand ld A, 0x33 ; 2:7 0 0x33 (656) (abc) dand and L ; 1:4 0 0x33 (656) (abc) dand ld L, A ; 1:4 0 0x33 (656) (abc) dand ld H, 0x00 ; 2:7 0 0x33 (656) (abc) dand ; seconds: 0 ;[14:70] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ Je to asi nejlepsi reseni, i kdyz to muze stale trochu drhnout. Treba u prvni ukazky nepotrebuji nacitat z pameti vyssi bajt. Kód: ld DE, (656) ; 4:20 0x33 0x0000 (656) (abc) dand stacilo by neco jako Kód: ld A, (656) ; 3:13 0x33 0x0000 (656) (abc) dand Ale tohle by bylo uz fakt moc komplexni.ld E, A ; 1:4 0x33 0x0000 (656) (abc) dand Posledni pripad je ze nedokazi spocitat ani jeden par. Pak zase nezavisle na vyssi a nizsi hodnote se do push2_operace snazim nacpat hodnotu, protoze je pak kod efektivnejsi. V teto ukazce je to videt ze se to jakoby provede vnitrne prvne 2swap a az pak vola dand. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH2(0x1100,0x33,(656),(abc)) DAND __SHOW_TOKEN(1) __SHOW_TOKEN(2)' ; name: __TOKEN_PUSHS ; info: 0x1100 0x33 (656) (abc) dand ;items: 2 ;param: ((656),(abc)) ;array1: >(656)< ;array2: >(abc)< ;array: (656),(abc) ; name: __TOKEN_PUSH2_DAND ; info: 0x1100 0x33 (656) (abc) dand ;items: 2 ;param: (0x1100,0x33) ;array1: >0x1100< ;array2: >0x33< ;array: 0x1100,0x33 ;[9:58] 0x1100 0x33 (656) (abc) dand ( -- (656) (abc) ) push DE ; 1:11 0x1100 0x33 (656) (abc) dand push HL ; 1:11 0x1100 0x33 (656) (abc) dand ld DE, (656) ; 4:20 0x1100 0x33 (656) (abc) dand ld HL, (abc) ; 3:16 0x1100 0x33 (656) (abc) dand ld A, 0x33 ; 2:7 0x1100 0x33 (656) (abc) dand and L ; 1:4 0x1100 0x33 (656) (abc) dand ld L, A ; 1:4 0x1100 0x33 (656) (abc) dand ld H, 0x00 ; 2:7 0x1100 0x33 (656) (abc) dand ld E, 0x00 ; 2:7 0x1100 0x33 (656) (abc) dand ld A, 0x11 ; 2:7 0x1100 0x33 (656) (abc) dand and D ; 1:4 0x1100 0x33 (656) (abc) dand ld D, A ; 1:4 0x1100 0x33 (656) (abc) dand ; seconds: 0 ;[21:102] Tohle se vola i v pripade ze pred dand jsou v pushs jen dva parametry Pripad pro 3 parametry a pak doperace jsem neresil. Docela zajimave hrani. |
Autor: | _dworkin [ 01.12.2022, 21:58 ] |
Předmět příspěvku: | Re: Macro FORTH |
Hmm... koukam v tom poslednim kodu je Kód: ld H, 0x00 ; 2:7 0x1100 0x33 (656) (abc) dand ld E, 0x00 ; 2:7 0x1100 0x33 (656) (abc) dand Protoze se HL a DE resi nezavisle pres __AND_REG16_16BIT() Kód: dnl # ( d1 -- d ) dnl # d = d1 & n define({PUSH2_DAND},{dnl __{}__ADD_TOKEN({__TOKEN_PUSH2_DAND},{$1 $2 d&},$@){}dnl }){}dnl dnl define({__ASM_TOKEN_PUSH2_DAND},{dnl __{}define({__INFO},__COMPILE_INFO){}dnl ifelse(eval($#<2),1,{ __{} .error {$0}($@): Missing address parameter!}, eval($#>2),{1},{ __{} .error {$0}($@): $# parameters found in macro!}, {dnl __{}__{}define({_TMP_INFO},__COMPILE_INFO){}dnl __{}__{}__AND_REG16_16BIT({HL},$2){}dnl __{}__{}__AND_REG16_16BIT({DE},$1){}dnl })}){}dnl __AND_REG16_16BIT({HL},0x0000) __AND_REG16_16BIT({DE},0x1234) __AND_REG16_16BIT({DE},0x1234) __AND_REG16_16BIT({HL},0x0000) __AND_REG16_16BIT({DE},0x1200) __AND_REG16_16BIT({HL},0x0000) __AND_REG16_16BIT({DE},0x0000) __AND_REG16_16BIT({HL},0x0034) __AND_REG16_16BIT({HL},0x0000) __AND_REG16_16BIT({DE},0x0000) Tech kombinaci muze byt docela dost, to abych konecne vyresil predavani konstant(znamych hodnot) v registrech a nebo udelal __AND_REG32_32BIT(). |
Autor: | _dworkin [ 01.12.2022, 23:31 ] |
Předmět příspěvku: | Re: Macro FORTH |
Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH2(0x1100,0x33,(656),(abc)) DAND __SHOW_TOKEN(1) __SHOW_TOKEN(2)' ; name: __TOKEN_PUSHS ; info: 0x1100 0x33 (656) (abc) dand ;items: 2 ;param: ((656),(abc)) ;array1: >(656)< ;array2: >(abc)< ;array: (656),(abc) ; name: __TOKEN_PUSH2_DAND ; info: 0x1100 0x33 (656) (abc) dand ;items: 2 ;param: (0x1100,0x33) ;array1: >0x1100< ;array2: >0x33< ;array: 0x1100,0x33 ;[9:58] 0x1100 0x33 (656) (abc) dand ( -- (656) (abc) ) push DE ; 1:11 0x1100 0x33 (656) (abc) dand push HL ; 1:11 0x1100 0x33 (656) (abc) dand ld DE, (656) ; 4:20 0x1100 0x33 (656) (abc) dand ld HL, (abc) ; 3:16 0x1100 0x33 (656) (abc) dand ld A, 0x33 ; 2:7 0x1100 0x33 (656) (abc) dand and L ; 1:4 0x1100 0x33 (656) (abc) dand ld L, A ; 1:4 0x1100 0x33 (656) (abc) dand ld H, 0x00 ; 2:7 0x1100 0x33 (656) (abc) dand ld E, H ; 1:4 0x1100 0x33 (656) (abc) dand ld A, 0x11 ; 2:7 0x1100 0x33 (656) (abc) dand and D ; 1:4 0x1100 0x33 (656) (abc) dand ld D, A ; 1:4 0x1100 0x33 (656) (abc) dand ; seconds: 0 ;[20:99] Pridal jsem dalsi parametry $3 a $4 do __AND_REG16_16BIT() Kód: define({__AND_REG16_16BIT},{dnl dnl # Input dnl # $1 name reg pair dnl # $2 16bit value dnl # $3 name reg dnl # $4 8bit value with hex form 0xNN, $3 = $4 ifelse(dnl __IS_MEM_REF($2),{1},{ __{} ld A,format({%-12s},$2); 3:13 _TMP_INFO __{} and substr($1,1,1) ; 1:4 _TMP_INFO __{} ld substr($1,1,1), A ; 1:4 _TMP_INFO __{} ld A,format({%-12s},($2+1)); 3:13 _TMP_INFO __{} and substr($1,0,1) ; 1:4 _TMP_INFO __{} ld substr($1,0,1), A ; 1:4 _TMP_INFO}, __IS_NUM($2),{0},{ __{} .warning {$0}($@): M4 does not know the "{$2}" value and therefore cannot optimize the code. __{} if (($2) = 0x0000) __{} ld $1, 0x0000 ; 3:10 _TMP_INFO __{} else{}dnl __{}__AND_REG8_8BIT(substr($1,1,1),0xFF & ($2)){}dnl __{}__AND_REG8_8BIT(substr($1,0,1),+($2) >> 8) __{} endif}, {dnl __{}ifelse(__HEX_HL($2),{0x0000},{ __{} ld $1, 0x0000 ; 3:10 _TMP_INFO}, __{}{dnl __{}__{}__AND_REG8_8BIT(substr($1,1,1),__HEX_L($2),$3,$4){}dnl __{}__{}__AND_REG8_8BIT(substr($1,0,1),__HEX_H($2),$3,$4){}dnl })})}){}dnl Takze jsem je musel pridat i do __AND_REG8_8BIT, a tam resi pripad kdy potrebujeme vlozit do registru nulu a tu nulu uz ma registr $3, pripadne to resi i pripad kdy potrebujeme Rx = Rx & const a Ry = const. Makro cast ktera je na zacatku jsem radsi nemenil... Kód: define({__AND_REG8_8BIT},{dnl dnl # Input dnl # $1 name reg dnl # $2 8bit value with hex form 0xNN dnl # $3 name reg dnl # $4 8bit value with hex form 0xNN, $3 = $4 dnl # Output dnl # code $1 = $1 and $2 ifelse(__IS_NUM($2),{0},{ __{} if (($2) = 0x00) __{} ld $1, 0x00 ; 2:7 _TMP_INFO __{} else __{} if (($2) = 0xFE) __{} res 0, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0xFD) __{} res 1, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0xFB) __{} res 2, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0xF7) __{} res 3, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0xEF) __{} res 4, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0xDF) __{} res 5, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0xBF) __{} res 6, $1 ; 2:8 _TMP_INFO __{} else __{} if (($2) = 0x7F) __{} res 7, $1 ; 2:8 _TMP_INFO __{} else __{} if ((($2) > 0x00) && (($2) <= 0xFF)) __{} ld A,format({%-12s},$2); 2:7 _TMP_INFO __{} and $1 ; 1:4 _TMP_INFO __{} ld $1, A ; 1:4 _TMP_INFO __{} endif __{} endif __{} endif __{} endif __{} endif __{} endif __{} endif __{} endif __{} endif __{} endif}, {dnl __{}ifelse(__HEX_L($2),{0xFF},{}, __{}$1:$2,$3:$4,{ __{}__{} ; _TMP_INFO $1 = $2}, __{}$2:$4,{0x00:0x00},{ __{}__{} ld $1, $3 ; 1:4 _TMP_INFO}, __{}__HEX_L($2),{0x00},{ __{}__{} ld $1, 0x00 ; 2:7 _TMP_INFO}, __{}__HEX_L($2),{0xFE},{ __{}__{} res 0, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0xFD},{ __{}__{} res 1, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0xFB},{ __{}__{} res 2, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0xF7},{ __{}__{} res 3, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0xEF},{ __{}__{} res 4, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0xDF},{ __{}__{} res 5, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0xBF},{ __{}__{} res 6, $1 ; 2:8 _TMP_INFO}, __{}__HEX_L($2),{0x7F},{ __{}__{} res 7, $1 ; 2:8 _TMP_INFO}, __{}$2,$4,{ __{}__{} ld A, $3 ; 1:4 _TMP_INFO __{}__{} and $1 ; 1:4 _TMP_INFO __{}__{} ld $1, A ; 1:4 _TMP_INFO}, __{}{ __{}__{} ld A, __HEX_L($2) ; 2:7 _TMP_INFO __{}__{} and $1 ; 1:4 _TMP_INFO __{}__{} ld $1, A ; 1:4 _TMP_INFO})})}){}dnl A to samotne __PUSH2_DAND vypada ted takto Kód: dnl # ( d1 -- d ) dnl # d = d1 & n define({PUSH2_DAND},{dnl __{}__ADD_TOKEN({__TOKEN_PUSH2_DAND},{$1 $2 d&},$@){}dnl }){}dnl dnl define({__ASM_TOKEN_PUSH2_DAND},{dnl __{}define({__INFO},__COMPILE_INFO){}dnl ifelse(eval($#<2),1,{ __{} .error {$0}($@): Missing address parameter!}, eval($#>2),{1},{ __{} .error {$0}($@): $# parameters found in macro!}, {dnl __{}define({_TMP_INFO},__COMPILE_INFO){}dnl __{}__AND_REG16_16BIT({HL},$2){}dnl __{}ifelse(dnl __{}__HEX_L($2),0x00,{__AND_REG16_16BIT({DE},$1,{L},0x00)}, __{}__HEX_H($2),0x00,{__AND_REG16_16BIT({DE},$1,{H},0x00)}, __{}{__AND_REG16_16BIT({DE},$1)}){}dnl })}){}dnl Vyuziva to triku, ze kdyz neni v kazdem 16bitovem slove 8 bitova nula tak se to stejne neda zlepsit, takze zadne prohozeni (nastesti) nepomaha. PS: Uz mam najednou 7 hvezdicek na githubu! Dlouho byly tri nedavno 5 a ted 7. Nekde se o tom musel nekdo zminit. Nebo ze by ty samotne hvezdicky to posouvaly v githubu vic dopredu ve vyhledavani neceho kde je FORTH Z80 ZX? https://github.com/DW0RKiN/M4_FORTH/stargazers PPS: Sakra mam tam chybu... pridal jsem do __AND_REG16_16BIT() atd podporu pro ukazatele a ty makra s tim nepocitaji. Ted me ukazuji ze se snazi zjistit zda Kód: if ((0xFF & (abc)) = 0x00) chjo...ld E, 0x00 ; 2:7 abc 0x33 (656) (abc) dand PPPS: Uf! Tak je to dobre. To abc v zavorce je prvni parametr... Kód: if ((0xFF & (xxx)) = 0x00) ld E, 0x00 ; 2:7 xxx 0x33 (656) (abc) dand PPPPS: Vetsina tech co mi davaji hvezdicky maji zajimave repozitare. Napriklad tohle dokaze skladat kod Z80 jako puzzle. https://github.com/haroldo-ok/blockly-z80 Příloha:
|
Autor: | _dworkin [ 02.12.2022, 03:27 ] |
Předmět příspěvku: | Re: Macro FORTH |
Opravena chyba v PUSH3. Nejak me to menilo "656" na "+(656)". Dival jsem se na kod a radsi jsem ho napsal cely znovu. Uploadnu to ale az v sobotu rano. U toho jsem zmenil poradi tokenovych pravidel pro XOR (AND,OR) takze to hned nevytvari PUSH_XOR pokud je jeden parametr pointer, kdyz je sance ze druhy bude nula. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0,0,(656),0) XOR __SHOW_TOKEN(1)' ; name: __TOKEN_PUSHS ; info: 0 0 (656) 0 xor ;items: 3 ;param: (0,0,(656)) ;array1: >0< ;array2: >0< ;array3: >(656)< ;array: 0,0,(656) push DE ; 1:11 0 0 (656) 0 xor ( -- 0 0 (656) ) push HL ; 1:11 0 0 (656) 0 xor ld DE, 0 ; 3:10 0 0 (656) 0 xor push DE ; 1:11 0 0 (656) 0 xor ld HL, +(656) ; 3:10 0 0 (656) 0 xor ; seconds: 1 ;[ 9:53] Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(0,0,(656),0) XOR __SHOW_TOKEN(1)'
; name: __TOKEN_PUSHS ; info: 0 0 (656) 0 xor ;items: 3 ;param: (0,0,(656)) ;array1: >0< ;array2: >0< ;array3: >(656)< ;array: 0,0,(656) push DE ; 1:11 0 0 (656) 0 xor ( -- 0 0 (656) ) push3.m3 push HL ; 1:11 0 0 (656) 0 xor ld DE, 0x0000 ; 3:10 0 0 (656) 0 xor push DE ; 1:11 0 0 (656) 0 xor ld HL, (656) ; 3:16 0 0 (656) 0 xor ; seconds: 0 ;[ 9:59] dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ |
Stránka 25 z 39 | Všechny časy jsou v UTC + 1 hodina [ Letní čas ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |