OldComp.cz https://www.oldcomp.cz/ |
|
Macro FORTH https://www.oldcomp.cz/viewtopic.php?f=124&t=8564 |
Stránka 12 z 40 |
Autor: | _dworkin [ 09.03.2022, 21:54 ] |
Předmět příspěvku: | Re: Macro FORTH |
Kód: S_STK_LST 274C PUSH DE Stack the 'last' values briefly. 274D CALL SYNTAX_Z Do not perform the actual operation if syntax is being checked. 2750 JR Z,S_SYNTEST 2752 LD A,E The 'last' operation code. 2753 AND $3F Strip off bits 6 and 7 to convert the operation code to a calculator offset. 2755 LD B,A 2756 RST $28 Now use the calculator. 2757 DEFB $3B fp_calc_2: (perform the actual operation) 2758 DEFB $38 end_calc 2759 JR S_RUNTEST Jump forward. Urcite #2755? Protoze to pak pokracuje S_RUNTEST a pak to udela S_LOOP na 0x2734. Nemyslel jsi taky https://skoolkid.github.io/rom/asm/353B.html? |
Autor: | Busy [ 09.03.2022, 22:12 ] |
Předmět příspěvku: | Re: Macro FORTH |
_dworkin píše: Kód: ... Urcite #2755? Protoze to pak pokracuje S_RUNTEST a pak to udela S_LOOP na 0x2734.2755 LD B,A 2756 RST $28 Now use the calculator. 2757 DEFB $3B fp_calc_2: (perform the actual operation) 2758 DEFB $38 end_calc ... Uvadzal som to len ako priklad kde v romke a preco sa to pouziva. Ze kod za tym pokracuje dalsimi cinnostami, nie je podstatne. |
Autor: | _dworkin [ 09.03.2022, 22:38 ] |
Předmět příspěvku: | Re: Macro FORTH |
Busy píše: _dworkin píše: Kód: ... Urcite #2755? Protoze to pak pokracuje S_RUNTEST a pak to udela S_LOOP na 0x2734.2755 LD B,A 2756 RST $28 Now use the calculator. 2757 DEFB $3B fp_calc_2: (perform the actual operation) 2758 DEFB $38 end_calc ... Uvadzal som to len ako priklad kde v romke a preco sa to pouziva. Ze kod za tym pokracuje dalsimi cinnostami, nie je podstatne. Aha uz me doslo jak to myslis. Protoze ja narazel na to ze kdyz budu volat call #2755 tak se mi program nikdy nevrati do meho kodu a ty jsi to myslel jen jako ukazku kterou mam zkopirovat do me rutiny. Edit profiler me ukazuje ze pokud je po RST 0x28 byte s 0x3B tak to trva 2033356 taktu a pokud je tam 0x0D tak o trosku mene 2029202 taktu. Oboje vraci spravne vysledky. Kód: Pouze rozdilne pruchody
0x0D t-clock 0x3B t-clock diff t-clock 0x0a4f 475 0x0a4f 483 8 0x0adc 7984 0x0adc 8046 62 0x0ae2 7667 0x0ae2 7700 33 0x0ae8 7839 0x0ae8 7905 66 0x0aec 6445 0x0aec 6471 26 0x0b03 7309 0x0b03 7291 -18 0x0b09 7488 0x0b09 7506 18 0x0b0d 6199 0x0b0d 6220 21 0x0b10 7756 0x0b10 7820 64 0x0b66 6417 0x0b66 6335 -82 0x0b6e 4814 0x0b6e 4841 27 0x0b74 1375 0x0b74 1366 -9 0x0b9b 4214 0x0b9b 4195 -19 0x0bab 6643 0x0bab 6615 -28 0x0bb8 17088 0x0bb8 17074 -14 0x0bbc 18254 0x0bbc 18276 22 0x0be4 6496 0x0be4 6531 35 0x0be8 2157 0x0be8 2153 -4 0x0bec 6369 0x0bec 6392 23 0x0bfa 6792 0x0bfa 6823 31 0x0c08 2186 0x0c08 2183 -3 0x0c55 917 0x0c55 913 -4 0x0c5f 893 0x0c5f 879 -14 0x0c66 834 0x0c66 824 -10 0x0ddc 1381 0x0ddc 1369 -12 0x0de3 1436 0x0de3 1452 16 0x15f4 5971 0x15f4 6055 84 0x15f7 2315 0x15f7 2301 -14 0x15f9 2489 0x15f9 2483 -6 0x1f05 11237 0x1f05 11177 -60 0x2abb 39 0x2abb 42 3 0x2e8a 15631 0x2e8a 15666 35 0x2e8d 14461 0x2e8d 14442 -19 0x2e9d 1311 0x2e9d 1365 54 0x2ea1 10265 0x2ea1 9887 -378 0x2ea9 751 0x2ea9 791 40 0x2eab 2271 0x2eab 2250 -21 0x2eae 2339 0x2eae 2338 -1 0x2eba 691 0x2eba 675 -16 0x2edf 6394 0x2edf 6386 -8 0x2f02 5703 0x2f02 5684 -19 0x2f06 2521 0x2f06 2473 -48 0x2f07 7414 0x2f07 7428 14 0x2f10 964 0x2f10 973 9 0x2f19 2521 0x2f19 2523 2 0x2f1c 2246 0x2f1c 2255 9 0x2f2d 950 0x2f2d 959 9 0x2f36 997 0x2f36 989 -8 0x2f56 982 0x2f56 999 17 0x335f 4060 0x335f 4033 -27 0x3365 36180 0x3365 36415 235 0x336c 17743 0x336c 17941 198 0x336d 6452 0x336d 6524 72 0x336e 16130 0x336e 16310 180 0x3380 8659 0x3380 8785 126 0x3382 12484 0x3382 12700 216 0x338c 4948 0x338c 5020 72 0x338d 4948 0x338d 5020 72 0x338e 16130 0x338e 16310 180 0x3391 11291 0x3391 11417 126 0x3393 17743 0x3393 17941 198 0x3394 11291 0x3394 11417 126 0x3395 9678 0x3395 9786 108 0x3396 11291 0x3396 11417 126 0x3397 16130 0x3397 16310 180 0x339a 30647 0x339a 30989 342 0x339b 17743 0x339b 17941 198 0x339c 6452 0x339c 6524 72 0x339d 37617 0x339d 38340 723 0x33a1 18130 0x33a1 18310 180 0x33a2 180 180 0x33a3 236 236 0x33a6 72 72 0x33a7 216 216 0x33c3 61606 0x33c3 61677 71 0x3410 1642 0x3410 1594 -48 0x342f 4543 0x342f 4487 -56 0x35bf 6472 0x35bf 6335 -137 0x8148 1024 0x8148 1039 15 0x817f 1020 0x817f 987 -33 0x818c 1175 0x818c 1197 22 2029202 2033356 |
Autor: | _dworkin [ 10.03.2022, 14:28 ] |
Předmět příspěvku: | Re: Macro FORTH |
Jen pro zajimavost jak muze byt programovani matouci. Overoval jsem si jak vlastne presne uklada ROM cela cisla dovnitr floating-point. Na netu toho moc neni a neco je dokonce spatne. Slo mi hlavne o zaporna cisla, kvuli testu zda je cislo mensi nez nula. Zda mi staci overovat pouze nevyssi bit druheho bajtu. Zmatlo me ze mi nedoslo ze treti bajt je NIZSI a ctvrty VYSSI cisla, ne jak to ma mantisa. Tak jsem si napsal slovo pro vypis cisel v hex forme, abych rychle videl co je fyzicky v pameti a co se tiskne za cislo. No a tohle me vylezlo, prvne jsem si toho nevsiml a pak jen ziral: Příloha: negate.png [ 3.31 KiB | Zobrazeno 3932 krát ] Vidite to taky? Co to ma byt? Problem psani kompilatoru je ze chyba muze byt uplne kdekoliv. I v casti kterou uz pouzivate a zatim se chyba neprojevila. Takze jsem tam pridal jiny zpusob ukladani cisel na float zasobnik. Kopirovani z pameti z konstanty. Problem stejny. Prohlizim ZX48FHEXDOT a nechapu, vzdyt tam jen ctu a nic neukladam! Prohlizim jiny program kde nepouzivam ZX48FHEXDOT a ten funguje. Divam se do asm zdrojaku a nic nevidim. Tisknu cislo pred ZX48FHEXDOT a je to spravne a po nem spatne. Tisknu pomoci ZX48FHEXDOT 2x a uz je to spavne! Ale druhy hex vypis tiskne jine cislo. Nektere bity otoci, nektere ne. Presne tak aby ten float byl zaporny. Jak je to sakra mozny, az takhle komplexne. Oh! Je zapomel ukoncit fci pomoci RET... A pod tim je ZX48FNEGATE... lol |
Autor: | _dworkin [ 10.03.2022, 19:12 ] |
Předmět příspěvku: | Re: Macro FORTH |
Zmenil jsem nacitani celych cisel z Forth zasobniku do floating zasobniku. Kód: _ZX48U_TO_F: push DE ; 1:11 _zx48u>f ( c ret . b a -- ret . c b ) ld B, H ; 1:4 _zx48u>f ld C, L ; 1:4 _zx48u>f call 0x2D2B ; 3:17 _zx48u>f call ZX ROM stack BC routine pop HL ; 1:10 _zx48u>f pop BC ; 1:10 _zx48u>f ret pop DE ; 1:10 _zx48u>f push BC ; 1:11 _zx48u>f ret ret ; 1:10 _zx48u>f ;[11:87] _ZX48BC_TO_F: push DE ; 1:11 _zx48bc_to_f push HL ; 1:11 _zx48bc_to_f call 0x2D2B ; 3:17 _zx48bc_to_f call ZX ROM stack BC routine pop HL ; 1:10 _zx48bc_to_f pop DE ; 1:10 _zx48bc_to_f ret ; 1:10 _zx48bc_to_f ;[ 8:69] _ZX48FNEGATE: push DE ; 1:11 _zx48fnegate push HL ; 1:11 _zx48fnegate rst 0x28 ; 1:11 Use the calculator db 0x1B ; 1: calc-negate db 0x38 ; 1: calc-end Pollutes: AF, BC, BC', DE'(=DE) pop HL ; 1:10 _zx48fnegate pop DE ; 1:10 _zx48fnegate ret ; 1:10 _zx48fnegate ;[ 8:63+?] Mam na mysli variantu kdy vlozite konstantu do Forthu a tu hned presouvate do float zasobniku. Predtim jsem pouzival ZX ROM fci "BC_TO_F". Ta byla super kratoucka. Ale nacita cisla jakou unsigned. Takze zaporna jsem nacital tak, ze jsem je po prevedeni na kladna nacetl a zavolal fci FNEGATE. To fungovalo pekne, jen to u vsech zapornych hodnot bylo o 3 bajty delsi a kod celkem pomaly. Ted kdyz jsem pochopil jak ma ZX ulozeny ty celociselne konstanty jsem udelal fce: Kód: _ZX48S_TO_F: ; _zx48s>f ( num ret . de hl -- ret . num de ) Ktera jsou o dost vetsi nez puvodni osmibajtova BC_TO_F. Ale vypadla dalsi osmibajtova fce FNEGATE, protoze ji nemusim pouzivat pro zaporne konstanty.ld B, H ; 1:4 _zx48s>f ld C, L ; 1:4 _zx48s>f pop HL ; 1:10 _zx48s>f ( num . de ret ) ex (SP),HL ; 1:19 _zx48s>f ( ret . de num ) ex DE, HL ; 1:4 _zx48s>f ( ret . num de ) ; fall to _zx48bbc_to_f _ZX48BBC_TO_F: ;[3:12] _zx48bbc_to_f ld A, B ; 1:4 _zx48bbc_to_f add A, A ; 1:4 _zx48bbc_to_f sbc A, A ; 1:4 _zx48bbc_to_f ; fall to _zx48abc_to_f _ZX48ABC_TO_F: ;[21:134] _zx48abc_to_f push HL ; 1:11 _zx48abc_to_f ld HL,(0x5C65) ; 3:16 _zx48abc_to_f load STKEND ld (HL),0x00 ; 2:10 _zx48abc_to_f inc HL ; 1:6 _zx48abc_to_f ld (HL), A ; 1:7 _zx48abc_to_f inc HL ; 1:6 _zx48abc_to_f ld (HL), C ; 1:7 _zx48abc_to_f inc HL ; 1:6 _zx48abc_to_f ld (HL), B ; 1:7 _zx48abc_to_f inc HL ; 1:6 _zx48abc_to_f ld (HL),0x00 ; 2:10 _zx48abc_to_f inc HL ; 1:6 _zx48abc_to_f ld (0x5C65),HL ; 3:16 _zx48abc_to_f save STKEND+5 pop HL ; 1:10 _zx48abc_to_f ret ; 1:10 _zx48abc_to_f A pokud volam cislo v rozsahu 16 bitoveho integeru staci me volat vzdy BBC_TO_F. Protoze znamenko do druheho bajtu si najde. Pokud bych volal kladne cislo vetsi nez 0x7FFF tak mi to vygeneruje xor A call ABC_TO_F Coz je o jeden bajt delsi nez puvodni varianta. Pokud bych volal zaporne cislo, ktere je zaporne pouze jako 17 bitove. Teda ma nejvyssi bajt nulovy tak mi to vygeneruje ld A, 0xFF call ABC_TO_F Na kazdem volani bych tak usetril 1 bajt oproti puvodni variante. Zda je to lepsi zalezi hodne na konkretnim programu, ale prijde mi, ze to stoji za zmenu. Puvodni slovo jsem radsi ponechal s novym jmenem ZX48U_TO_S ( == u>s) a PUSH_ZX48U_S(123) ( == 123 s>f ) PS: Hmm, mohl jsem vtvorit rutinu pro zaporna cisla s volanim BC_TO_HL a pak negate. Takze by pak volani bylo vzdy 3 bajty. Ale to je mi stale proti srsti, delat to tak zbytecne pomalu a slozite. |
Autor: | _dworkin [ 11.03.2022, 03:48 ] |
Předmět příspěvku: | Re: Macro FORTH |
Ukazalo se vyhodnejsi pouzit misto parametru "reg A + reg BC" pouze "carry + reg BC". Mezi rutinami jsem jen presunul instrukci "sbc A,A" a ted usetrim pokazde jeden bajt kdyz misto "ld A, 0xFF" pouziji "scf". Dalsich 8 bajtu se usetrilo kdyz volam 0x2ABB. Viz Kód: _ZX48S_TO_F: ; _zx48s>f ( num ret . de hl -- ret . num de ) ld B, H ; 1:4 _zx48s>f ld C, L ; 1:4 _zx48s>f pop HL ; 1:10 _zx48s>f ( num . de ret ) ex (SP),HL ; 1:19 _zx48s>f ( ret . de num ) ex DE, HL ; 1:4 _zx48s>f ( ret . num de ) ; fall to _zx48bbc_to_f _ZX48BBC_TO_F: ;[2:8] _zx48bbc_to_f ld A, B ; 1:4 _zx48bbc_to_f add A, A ; 1:4 _zx48bbc_to_f ; fall to _zx48cfbc_to_f if 1 _ZX48CFBC_TO_F: ;[14:200] _zx48cfbc_to_f sbc A, A ; 1:4 _zx48cfbc_to_f 0x00 or 0xff push HL ; 1:11 _zx48cfbc_to_f push DE ; 1:11 _zx48cfbc_to_f ld E, A ; 1:4 _zx48cfbc_to_f ld D, C ; 1:4 _zx48cfbc_to_f ld C, B ; 1:4 _zx48cfbc_to_f xor A ; 1:4 _zx48cfbc_to_f ld B, A ; 1:4 _zx48cfbc_to_f call 0x2ABB ; 3:124 _zx48cfbc_to_f new float = a,e,d,c,b = 0,0-sign,lo,hi,0 pop DE ; 1:10 _zx48cfbc_to_f else _ZX48CFBC_TO_F: ;[22:138] _zx48cfbc_to_f sbc A, A ; 1:4 _zx48cfbc_to_f 0x00 or 0xff push HL ; 1:11 _zx48cfbc_to_f ld HL,(0x5C65) ; 3:16 _zx48cfbc_to_f load STKEND ld (HL),0x00 ; 2:10 _zx48cfbc_to_f inc HL ; 1:6 _zx48cfbc_to_f ld (HL), A ; 1:7 _zx48cfbc_to_f inc HL ; 1:6 _zx48cfbc_to_f ld (HL), C ; 1:7 _zx48cfbc_to_f inc HL ; 1:6 _zx48cfbc_to_f ld (HL), B ; 1:7 _zx48cfbc_to_f inc HL ; 1:6 _zx48cfbc_to_f ld (HL),0x00 ; 2:10 _zx48cfbc_to_f inc HL ; 1:6 _zx48cfbc_to_f ld (0x5C65),HL ; 3:16 _zx48cfbc_to_f save STKEND+5 endif pop HL ; 1:10 _zx48cfbc_to_f ret ; 1:10 _zx48cfbc_to_f Kód: 2ABB LD HL,($5C65) Fetch the address of the first location above the present stack (STKEND).
2ABE LD (HL),A Transfer the first byte. 2ABF INC HL Step on. 2AC0 LD (HL),E Transfer the second and third bytes; for a string these will be the 'start'. 2AC1 INC HL 2AC2 LD (HL),D 2AC3 INC HL Step on. 2AC4 LD (HL),C Transfer the fourth and fifth bytes; for a string these will be the 'length'. 2AC5 INC HL 2AC6 LD (HL),B 2AC7 INC HL Step on so as to point to the location above the stack. 2AC8 LD ($5C65),HL Save this address in STKEND and return. 2ACB RET |
Autor: | _dworkin [ 17.03.2022, 15:57 ] |
Předmět příspěvku: | Re: Macro FORTH |
Mensi odbocka od floating point. Dodelal jsem si optimalizaci pro bitove posuny. Mel jsem univerzalni funkce co ctou parametry ze zasobniku (RSHIFT & LSHIFT) a pak pro pripad posunu o jeden bit (_1RSHIFT & _1LSHIFT). Pridal jsem zbytek, kdyz je znamo v dobe prekladu o kolik bitu se to ma posouvat. V podstate je to skoro stejne jako na strance https://www.chilliant.com/z80shift.html, jen tam chybi v posunu >> 6 optimalni varianta. Takhle to vypada v testech pro LSHIFT Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ echo "10 lshift" | ../forth2m4.sh
include(`../M4/FIRST.M4')dnl ORG 0x8000 INIT(60000) ... STOP PUSH_LSHIFT(10) include({../M4/LAST.M4})dnl dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ echo "+10 lshift" | ../forth2m4.sh include(`../M4/FIRST.M4')dnl ORG 0x8000 INIT(60000) ... STOP PUSH_LSHIFT(+10) include({../M4/LAST.M4})dnl dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ echo "-10 lshift" | ../forth2m4.sh include(`../M4/FIRST.M4')dnl ORG 0x8000 INIT(60000) ... STOP PUSH_RSHIFT(10) include({../M4/LAST.M4})dnl dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT()" ; vvv ; ^^^ .error PUSH_LSHIFT(): Missing address parameter! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(1,2)" ; vvv ; ^^^ .error PUSH_LSHIFT(1,2): 2 parameters found in macro! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(xxx)" m4:stdin:3: bad expression in eval: xxx ; vvv ; ^^^ .error PUSH_LSHIFT(xxx): M4 does not know the "xxx" value and therefore cannot create the code! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT((0x8080))" ; vvv ; ^^^ .error PUSH_LSHIFT((0x8080)): Pointer as parameter is not supported! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(0)" ; vvv ; ^^^ ; 0 lshift ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(17)" ; vvv ; ^^^ ; 17 lshift --> 16 lshift ld HL, 0x0000 ; 3:10 16 lshift ( u -- u<<16 ) ;[ 3:10] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(1)" ; vvv ; ^^^ add HL, HL ; 1:11 1 lshift ( u -- u<<1 ) ;[ 1:11] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(2)" ; vvv ; ^^^ add HL, HL ; 1:11 2 lshift ( u -- u<<2 ) add HL, HL ; 1:11 2 lshift ;[ 2:22] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(3)" ; vvv ; ^^^ add HL, HL ; 1:11 3 lshift ( u -- u<<3 ) add HL, HL ; 1:11 3 lshift add HL, HL ; 1:11 3 lshift ;[ 3:33] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(4)" ; vvv ; ^^^ add HL, HL ; 1:11 4 lshift ( u -- u<<4 ) add HL, HL ; 1:11 4 lshift add HL, HL ; 1:11 4 lshift add HL, HL ; 1:11 4 lshift ;[ 4:44] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(5)" ; vvv ; ^^^ add HL, HL ; 1:11 5 lshift ( u -- u<<5 ) add HL, HL ; 1:11 5 lshift add HL, HL ; 1:11 5 lshift add HL, HL ; 1:11 5 lshift add HL, HL ; 1:11 5 lshift ;[ 5:55] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(6)" ; vvv ; ^^^ ;[12:47] 6 lshift ( u -- u<<6 ) ld A, H ; 1:4 6 lshift and 0x03 ; 2:7 6 lshift .... ..98 7654 3210 rra ; 1:4 6 lshift .... ...9 8 7654 3210 rr L ; 2:8 6 lshift .... ...9 8765 4321 0 rra ; 1:4 6 lshift 0... .... 9 8765 4321 rr L ; 2:8 6 lshift 0... .... 9876 5432 1 rra ; 1:4 6 lshift 10.. .... . 9876 5432 ld H, L ; 1:4 6 lshift ld L, A ; 1:4 6 lshift ;[12:47] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(7)" ; vvv ; ^^^ xor A ; 1:4 7 lshift ( u -- u<<7 ) srl H ; 2:8 7 lshift rr L ; 2:8 7 lshift ld H, L ; 1:4 7 lshift rra ; 1:4 7 lshift ld L, A ; 1:4 7 lshift ;[ 8:32] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(8)" ; vvv ; ^^^ ld H, L ; 1:4 8 lshift ( u -- u<<8 ) ld L, 0x00 ; 2:7 8 lshift ;[ 3:11] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(9)" ; vvv ; ^^^ sla L ; 2:8 9 lshift ( u -- u<<9 ) ld H, L ; 1:4 9 lshift ld L, 0x00 ; 2:7 9 lshift ;[ 5:19] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(10)" ; vvv ; ^^^ ld A, L ; 1:4 10 lshift ( u -- u<<10 ) add A, A ; 1:4 10 lshift add A, A ; 1:4 10 lshift ld H, A ; 1:4 10 lshift ld L, 0x00 ; 2:7 10 lshift ;[ 6:23] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(11)" ; vvv ; ^^^ ld A, L ; 1:4 11 lshift ( u -- u<<11 ) add A, A ; 1:4 11 lshift add A, A ; 1:4 11 lshift add A, A ; 1:4 11 lshift ld H, A ; 1:4 11 lshift ld L, 0x00 ; 2:7 11 lshift ;[ 7:27] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(12)" ; vvv ; ^^^ ld A, L ; 1:4 12 lshift ( u -- u<<12 ) add A, A ; 1:4 12 lshift add A, A ; 1:4 12 lshift add A, A ; 1:4 12 lshift add A, A ; 1:4 12 lshift ld H, A ; 1:4 12 lshift ld L, 0x00 ; 2:7 12 lshift ;[ 8:31] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(13)" ; vvv ; ^^^ ld A, L ; 1:4 13 lshift ( u -- u<<13 ) rrca ; 1:4 13 lshift rrca ; 1:4 13 lshift rrca ; 1:4 13 lshift and 0xE0 ; 2:7 13 lshift ld H, A ; 1:4 13 lshift ld L, 0x00 ; 2:7 13 lshift ;[ 9:34] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(14)" ; vvv ; ^^^ ld A, L ; 1:4 14 lshift ( u -- u<<14 ) rrca ; 1:4 14 lshift rrca ; 1:4 14 lshift and 0xC0 ; 2:7 14 lshift ld H, A ; 1:4 14 lshift ld L, 0x00 ; 2:7 14 lshift ;[ 8:30] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_LSHIFT(15)" ; vvv ; ^^^ xor A ; 1:4 15 lshift ( u -- u<<15 ) rr L ; 2:8 15 lshift ld L, A ; 1:4 15 lshift rra ; 1:4 15 lshift ld H, A ; 1:4 15 lshift ;[ 6:24] |
Autor: | _dworkin [ 17.03.2022, 16:03 ] |
Předmět příspěvku: | Re: Macro FORTH |
A tohle ukazi testy pro RSHIFT Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ echo "10 rshift" | ../forth2m4.sh include(`../M4/FIRST.M4')dnl ORG 0x8000 INIT(60000) ... STOP PUSH_RSHIFT(10) include({../M4/LAST.M4})dnl dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ echo "+11 rshift" | ../forth2m4.sh include(`../M4/FIRST.M4')dnl ORG 0x8000 INIT(60000) ... STOP PUSH_RSHIFT(+11) include({../M4/LAST.M4})dnl dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ echo "-11 rshift" | ../forth2m4.sh include(`../M4/FIRST.M4')dnl ORG 0x8000 INIT(60000) ... STOP PUSH_LSHIFT(11) include({../M4/LAST.M4})dnl dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(xxx)" m4:stdin:3: bad expression in eval: xxx ; vvv ; ^^^ .error PUSH_RSHIFT(xxx): M4 does not know the "xxx" value and therefore cannot create the code! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "CONSTANT(xxx,8)PUSH_RSHIFT(xxx)" ; vvv ; ^^^ xxx EQU 8 ld L, H ; 1:4 8 rshift ( u -- u>>8 ) ld H, 0x00 ; 2:7 8 rshift ;[ 3:11] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT((0x8000))" ; vvv ; ^^^ .error PUSH_RSHIFT((0x8000)): Pointer as parameter is not supported! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT()" ; vvv ; ^^^ .error PUSH_RSHIFT(): Missing address parameter! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(1,2)" ; vvv ; ^^^ .error PUSH_RSHIFT(1,2): 2 parameters found in macro! ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(0)" ; vvv ; ^^^ ; 0 rshift ;[ 0:0] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(1)" ; vvv ; ^^^ srl H ; 2:8 1 rshift ( u -- u>>1 ) rr L ; 2:8 1 rshift ;[ 4:16] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(2)" ; vvv ; ^^^ srl H ; 2:8 2 rshift ( u -- u>>2 ) rr L ; 2:8 2 rshift srl H ; 2:8 2 rshift rr L ; 2:8 2 rshift ;[ 8:32] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(3)" ; vvv ; ^^^ ld A, L ; 1:4 3 rshift ( u -- u>>3 ) srl H ; 2:8 3 rshift rra ; 1:4 3 rshift srl H ; 2:8 3 rshift rra ; 1:4 3 rshift srl H ; 2:8 3 rshift rra ; 1:4 3 rshift ld L, A ; 1:4 3 rshift ;[11:44] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(4)" ; vvv ; ^^^ ld A, L ; 1:4 4 rshift ( u -- u>>4 ) srl H ; 2:8 4 rshift rra ; 1:4 4 rshift srl H ; 2:8 4 rshift rra ; 1:4 4 rshift srl H ; 2:8 4 rshift rra ; 1:4 4 rshift srl H ; 2:8 4 rshift rra ; 1:4 4 rshift ld L, A ; 1:4 4 rshift ;[14:56] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(5)" ; vvv ; ^^^ xor A ; 1:4 5 rshift ( u -- u>>5 ) add HL, HL ; 1:11 5 rshift adc A, A ; 1:4 5 rshift add HL, HL ; 1:11 5 rshift adc A, A ; 1:4 5 rshift add HL, HL ; 1:11 5 rshift adc A, A ; 1:4 5 rshift ld L, H ; 1:4 5 rshift ld H, A ; 1:4 5 rshift ;[ 9:57] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(6)" ; vvv ; ^^^ xor A ; 1:4 6 rshift ( u -- u>>6 ) add HL, HL ; 1:11 6 rshift adc A, A ; 1:4 6 rshift add HL, HL ; 1:11 6 rshift adc A, A ; 1:4 6 rshift ld L, H ; 1:4 6 rshift ld H, A ; 1:4 6 rshift ;[ 7:42] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(7)" ; vvv ; ^^^ xor A ; 1:4 7 rshift ( u -- u>>7 ) add HL, HL ; 1:11 7 rshift adc A, A ; 1:4 7 rshift ld L, H ; 1:4 7 rshift ld H, A ; 1:4 7 rshift ;[ 5:27] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(8)" ; vvv ; ^^^ ld L, H ; 1:4 8 rshift ( u -- u>>8 ) ld H, 0x00 ; 2:7 8 rshift ;[ 3:11] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(9)" ; vvv ; ^^^ srl H ; 2:8 9 rshift ( u -- u>>9 ) ld L, H ; 1:4 9 rshift ld H, 0x00 ; 2:7 9 rshift ;[ 5:19] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(10)" ; vvv ; ^^^ srl H ; 2:8 10 rshift ( u -- u>>10 ) srl H ; 2:8 10 rshift ld L, H ; 1:4 10 rshift ld H, 0x00 ; 2:7 10 rshift ;[ 7:27] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(11)" ; vvv ; ^^^ ld A, H ; 1:4 11 rshift ( u -- u>>11 ) and 0xF8 ; 2:7 11 rshift rrca ; 1:4 11 rshift rrca ; 1:4 11 rshift rrca ; 1:4 11 rshift ld L, A ; 1:4 11 rshift ld H, 0x00 ; 2:7 11 rshift ;[ 9:34] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(12)" ; vvv ; ^^^ ld A, H ; 1:4 12 rshift ( u -- u>>12 ) and 0xF0 ; 2:7 12 rshift rrca ; 1:4 12 rshift rrca ; 1:4 12 rshift rrca ; 1:4 12 rshift rrca ; 1:4 12 rshift ld L, A ; 1:4 12 rshift ld H, 0x00 ; 2:7 12 rshift ;[10:38] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(13)" ; vvv ; ^^^ ld A, H ; 1:4 13 rshift ( u -- u>>13 ) and 0xE0 ; 2:7 13 rshift rlca ; 1:4 13 rshift rlca ; 1:4 13 rshift rlca ; 1:4 13 rshift ld L, A ; 1:4 13 rshift ld H, 0x00 ; 2:7 13 rshift ;[ 9:34] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(14)" ; vvv ; ^^^ ld A, H ; 1:4 14 rshift ( u -- u>>14 ) and 0xC0 ; 2:7 14 rshift rlca ; 1:4 14 rshift rlca ; 1:4 14 rshift ld L, A ; 1:4 14 rshift ld H, 0x00 ; 2:7 14 rshift ;[ 8:30] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(15)" ; vvv ; ^^^ xor A ; 1:4 15 rshift ( u -- u>>15 ) rl H ; 2:8 15 rshift ld H, A ; 1:4 15 rshift rra ; 1:4 15 rshift ld L, A ; 1:4 15 rshift ;[ 6:24] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(16)" ; vvv ; ^^^ ld HL, 0x0000 ; 3:10 16 rshift ( u -- u>>16 ) ;[ 3:10] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(17)" ; vvv ; ^^^ ; 17 rshift --> 16 rshift ld HL, 0x0000 ; 3:10 16 rshift ( u -- u>>16 ) ;[ 3:10] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(-1)" ; vvv ; ^^^ .error PUSH_RSHIFT(-1): negative parameters found in macro! Use PUSH_LSHIFT(1). ;[ 0:0] V emulatoru jsem to jeste netestoval. Mimochodem mel jsem celou dobu pocit, ze jsem to prece uz jednou delal... a taky ano, resil jsem to v nasobeni, jen jsem na to jako sklerotik uz zapomnel. Jinak uplne mimo tema jsem sehnal novou praci, nebo mi spis uplne spadla do klina, protoze jsem byl bez anglictiny uplne bezradny, ale napsal me po mesici byvaly sef zda neshanim praci. A taky jsem zoufale shanel a i zaroven neshanel, podle toho jak se na to podivate. Takze budu mit mene casu a budu mene spamovat. "Delam" s jednou symptatickou brazilkou (co byla v Brazilii profesorkou hry na akustickou kytaru, ale neumi poradne anglicky, takze dela tuhle hroznou praci) a jeste rumunem. Ta restaurace je celkem mala, je to prace jen pro jednoho, takze se vidime jen pri stridani smen. |
Autor: | _dworkin [ 17.03.2022, 20:19 ] |
Předmět příspěvku: | Re: Macro FORTH |
Tak uz by to melo byt spravne, nasel jsem jen chybu v ">> 15" kdy jsem 15. bit presouval do 7. bitu a ne do nulteho. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(15)"
; vvv ; ^^^ xor A ; 1:4 15 rshift ( u -- u>>15 ) rl H ; 2:8 15 rshift ld H, A ; 1:4 15 rshift rra ; 1:4 15 rshift ld L, A ; 1:4 15 rshift ;[ 6:24] dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../compile.sh shift old: -rw-rw-r-- 1 dworkin dworkin 1865 Mar 17 18:14 shift.bin new: -rw-rw-r-- 1 dworkin dworkin 1865 Mar 17 18:17 shift.bin dworkin@dw-A15:~/Programovani/ZX/Forth/new2$ ../check_word.sh "PUSH_RSHIFT(15)" ; vvv ; ^^^ xor A ; 1:4 15 rshift ( u -- u>>15 ) rl H ; 2:8 15 rshift ld H, A ; 1:4 15 rshift adc A, A ; 1:4 15 rshift ld L, A ; 1:4 15 rshift ;[ 6:24] |
Autor: | _dworkin [ 22.06.2022, 22:10 ] |
Předmět příspěvku: | Re: Macro FORTH |
Po delsi dobe sem zase neco napisi. Pridaval jsem podporu 32 bitovych cisel a dostal se do casti kdy pracuji s konstantama. Proste kdyz vlozim cislo a s nim a dalsim pro prekladac uz neznamym cislem v zasobniku provedu matematickou operaci. Kupodivu nejnarocnejsi je operace zjisteni zda jsou cisla shodne nebo ruzne, protoze u vseho ostatniho to bud spocteme a nebo nam pomuze priznak carry. Tady ale ne, musime se spolehnout na priznak nuly a ten se neda prakticky prenaset mezi bajty. S tim jak neni Z80 ortgonalni byla tohle docela velka vyzva a zaroven zabava. Protoze u techto operaci se mnohokrat opakuje kod u ruznych slov, nebo kombinaci slov, jako je: 123456789 = 123456789 = if 123456789 = while 2dup 123456789 = 2dup 123456789 = if 2dup 123456789 = while 123456789 <> 123456789 <> if 123456789 <> while 2dup 123456789 <> 2dup 123456789 <> if 2dup 123456789 <> while jsem se rozhodl ze se pokusim udelat nejakou makro funkci, ktera by zakladni shodny kod sama vygenerova, a zbytek co se lisi se obalil pak zvlast. M4 Forth uklada 32 bitove cislo v zasobniku tak, ze HL obsahuje nizsich 16 bajtu a DE obsahuje vyssich 16 bajtu. Coz je mimochodem presne naopak nez je v standartu, ale pro nektere funkce to bylo vyhodnejsi tak jsem to tak zvolil. A Z80 nema podporu pro 32 bitove cisla takze endianitu si stejne musite resit softwarove. A protoze podporuji operace typu "2dup constant = if" tak si v te makro funkci nesmim znicit hodnoty v registru. Vcetne HL. Takze jsem v podstate odkazany na akumulator A, protoze to skoro vzdy vychazi rychleji nez schovavat HL na zasobnik. Zakladni kod vypada nejak takto Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x45352515)' ;[21:75/23,41,59,75] 2dup 0x45352515 D<> if ( d1 -- d1 ) 0x45352515 <> DEHL ld A, 0x15 ; 2:7 2dup 0x45352515 D<> if cp L ; 1:4 2dup 0x45352515 D<> if x[1] = 0x15 jr nz, $+18 ; 2:7/12 2dup 0x45352515 D<> if ld A, 0x25 ; 2:7 2dup 0x45352515 D<> if cp H ; 1:4 2dup 0x45352515 D<> if x[2] = 0x25 jr nz, $+13 ; 2:7/12 2dup 0x45352515 D<> if ld A, 0x35 ; 2:7 2dup 0x45352515 D<> if cp E ; 1:4 2dup 0x45352515 D<> if x[3] = 0x35 jr nz, $+8 ; 2:7/12 2dup 0x45352515 D<> if ld A, 0x45 ; 2:7 2dup 0x45352515 D<> if xor D ; 1:4 2dup 0x45352515 D<> if x[4] = 0x45 jp z, else101 ; 3:10 2dup 0x45352515 D<> if ;[21:75] Pokud jsou bajty shodne tak kod vypada nejak takto Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x33333333)' ;[15:54/20,31,42,54] 2dup 0x33333333 D<> if ( d1 -- d1 ) 0x33333333 <> DEHL ld A, L ; 1:4 2dup 0x33333333 D<> if the beginning of identical values cp H ; 1:4 2dup 0x33333333 D<> if x[1] = x[2] jr nz, $+13 ; 2:7/12 2dup 0x33333333 D<> if cp D ; 1:4 2dup 0x33333333 D<> if x[2] = x[3] continuation of identical values jr nz, $+10 ; 2:7/12 2dup 0x33333333 D<> if cp E ; 1:4 2dup 0x33333333 D<> if x[3] = x[4] continuation of identical values jr nz, $+7 ; 2:7/12 2dup 0x33333333 D<> if xor 0x33 ; 2:7 2dup 0x33333333 D<> if x[4] = 0x33 termination of identical values jp z, else101 ; 3:10 2dup 0x33333333 D<> if ;[15:54] Pokud cislo obsahuje nejake nulove bajty tak je to stale snadne, proste se jen daji nakonec, a predchozi testovani musi vynulovat akumulator. Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x45002500)' ;[13:47/23,47,47,47] 2dup 0x45002500 D<> if ( d1 -- d1 ) 0x45002500 <> DEHL ld A, 0x25 ; 2:7 2dup 0x45002500 D<> if cp H ; 1:4 2dup 0x45002500 D<> if x[1] = 0x25 jr nz, $+10 ; 2:7/12 2dup 0x45002500 D<> if ld A, 0x45 ; 2:7 2dup 0x45002500 D<> if xor D ; 1:4 2dup 0x45002500 D<> if x[2] = 0x45 or E ; 1:4 2dup 0x45002500 D<> if x[3] = 0 or L ; 1:4 2dup 0x45002500 D<> if x[4] = 0 jp z, else101 ; 3:10 2dup 0x45002500 D<> if ;[13:47] Vylepseni oproti 16 bitove verzi co jsem uz resil je v tom, ze me doslo ze ty jednotlive bajty mohu chapat jako nejakou posloupnost, kdy mezi nema mohou existovat i nejake vztahy. Napriklad kazde dalsi cislo je dvounasobkem predchoziho, zde konkretne vidite zradnost preteceni, kdy polovina cisla 0x2A muze byt jak 0x15 tak 0x95. V tomto kodu pouzivam jednoduse pro overeni uz overene hodnoty. Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0xA8542A95)' ;[18:66/23,38,53,66] 2dup 0xA8542A95 D<> if ( d1 -- d1 ) 0xA8542A95 <> DEHL ld A, 0x95 ; 2:7 2dup 0xA8542A95 D<> if cp L ; 1:4 2dup 0xA8542A95 D<> if x[1] = 0x95 jr nz, $+15 ; 2:7/12 2dup 0xA8542A95 D<> if add A, L ; 1:4 2dup 0xA8542A95 D<> if cp H ; 1:4 2dup 0xA8542A95 D<> if x[2] = x[1] + x[1] jr nz, $+11 ; 2:7/12 2dup 0xA8542A95 D<> if add A, H ; 1:4 2dup 0xA8542A95 D<> if cp E ; 1:4 2dup 0xA8542A95 D<> if x[3] = x[2] + x[2] jr nz, $+7 ; 2:7/12 2dup 0xA8542A95 D<> if add A, E ; 1:4 2dup 0xA8542A95 D<> if xor D ; 1:4 2dup 0xA8542A95 D<> if x[4] = x[3] + x[3] jp z, else101 ; 3:10 2dup 0xA8542A95 D<> if ;[18:66] Nebo jiny matematicky vztah, nebo jejich kombinace Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x3f1f2010)' ;[18:66/23,38,53,66] 2dup 0x3f1f2010 D<> if ( d1 -- d1 ) 0x3F1F2010 <> DEHL ld A, 0x10 ; 2:7 2dup 0x3f1f2010 D<> if cp L ; 1:4 2dup 0x3f1f2010 D<> if x[1] = 0x10 jr nz, $+15 ; 2:7/12 2dup 0x3f1f2010 D<> if add A, L ; 1:4 2dup 0x3f1f2010 D<> if cp H ; 1:4 2dup 0x3f1f2010 D<> if x[2] = x[1] + x[1] jr nz, $+11 ; 2:7/12 2dup 0x3f1f2010 D<> if dec A ; 1:4 2dup 0x3f1f2010 D<> if cp E ; 1:4 2dup 0x3f1f2010 D<> if x[3] = x[2] - 1 jr nz, $+7 ; 2:7/12 2dup 0x3f1f2010 D<> if add A, H ; 1:4 2dup 0x3f1f2010 D<> if xor D ; 1:4 2dup 0x3f1f2010 D<> if x[4] = x[3] + x[2] jp z, else101 ; 3:10 2dup 0x3f1f2010 D<> if ;[18:66] U bajtu s hodnotu 0xFF jsem prisel na to, ze ten vztah nemusim prevadet na nulu, ale na hodnotu 0xFF a misto OR pouzivat instrukci AND. Tohle je jedna z mala veci, kdy mohu spojit test bajtu bezpecne dohromady. Dalsim trikem ktery jsem objevil je, ze predchozi vztah, ktery jsem nuloval a pak pomoci "dec A" nastavoval na 0xFF mohu udelat jeste efektivnejsi kdyz misto Kód: ld A, 0x45 pouziji xor D dec A Kód: ld A, (0x45 ^ 0xFF) Vysledny kod vypada podobne jak s nulama takto, jen o jeden bajt delsi pro ukoncujici instrukci "inc A". 0xFF bajty jsou vzdy na konci, popripade hned pred nulovymi bajty.xor D Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x45FF25FF)' ;[14:51/23,51,51,51] 2dup 0x45FF25FF D<> if ( d1 -- d1 ) 0x45FF25FF <> DEHL ld A, 0x25 ; 2:7 2dup 0x45FF25FF D<> if cp H ; 1:4 2dup 0x45FF25FF D<> if x[1] = 0x25 jr nz, $+11 ; 2:7/12 2dup 0x45FF25FF D<> if ld A, D ; 1:4 2dup 0x45FF25FF D<> if xor 0xBA ; 2:7 2dup 0x45FF25FF D<> if x[2] = 0x45 = 0xFF ^ 0xBA and E ; 1:4 2dup 0x45FF25FF D<> if x[3] = 0xFF and L ; 1:4 2dup 0x45FF25FF D<> if x[4] = 0xFF inc A ; 1:4 2dup 0x45FF25FF D<> if jp z, else101 ; 3:10 2dup 0x45FF25FF D<> if ;[14:51] Drobne optimalizace jsou pokud pred 0xFF je 0xFE Kód: ./check_word.sh '_2DUP_PUSHDOT_DNE_IF(0xFEFF25FF)' ;[13:48/23,48,48,48] 2dup 0xFEFF25FF D<> if ( d1 -- d1 ) 0xFEFF25FF <> DEHL ld A, 0x25 ; 2:7 2dup 0xFEFF25FF D<> if cp H ; 1:4 2dup 0xFEFF25FF D<> if x[1] = 0x25 jr nz, $+10 ; 2:7/12 2dup 0xFEFF25FF D<> if ld A, D ; 1:4 2dup 0xFEFF25FF D<> if inc A ; 1:4 2dup 0xFEFF25FF D<> if x[2] + 1 = 0xFF and E ; 1:4 2dup 0xFEFF25FF D<> if x[3] = 0xFF and L ; 1:4 2dup 0xFEFF25FF D<> if x[4] = 0xFF inc A ; 1:4 2dup 0xFEFF25FF D<> if jp z, else101 ; 3:10 2dup 0xFEFF25FF D<> if ;[13:48] Posledni odlisnou cislici jsou jednicky, ty mohou byt obcas rychlejsi kdyz se s nema zachazi odlisne. Zde jen podobne vylepseni jako u 254 Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0xFEFF01FF)' ;[12:45/20,45,45,45] 2dup 0xFEFF01FF D<> if ( d1 -- d1 ) 0xFEFF01FF <> DEHL ld A, H ; 1:4 2dup 0xFEFF01FF D<> if dec A ; 1:4 2dup 0xFEFF01FF D<> if x[1] = 1 jr nz, $+10 ; 2:7/12 2dup 0xFEFF01FF D<> if ld A, D ; 1:4 2dup 0xFEFF01FF D<> if inc A ; 1:4 2dup 0xFEFF01FF D<> if x[2] + 1 = 0xFF and E ; 1:4 2dup 0xFEFF01FF D<> if x[3] = 0xFF and L ; 1:4 2dup 0xFEFF01FF D<> if x[4] = 0xFF inc A ; 1:4 2dup 0xFEFF01FF D<> if jp z, else101 ; 3:10 2dup 0xFEFF01FF D<> if ;[12:45] A tady je uz videt ze pomoci pouziti volneho registru C, dokazi spojit bajty v jeden test Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x00443333)' ;[15:54/20,34,54,54] 2dup 0x00443333 D<> if ( d1 -- d1 ) 0x00443333 <> DEHL ld A, L ; 1:4 2dup 0x00443333 D<> if the beginning of identical values cp H ; 1:4 2dup 0x00443333 D<> if x[1] = x[2] jr nz, $+13 ; 2:7/12 2dup 0x00443333 D<> if cp 0x33 ; 2:7 2dup 0x00443333 D<> if x[2] = 0x33 termination of identical values jr nz, $+9 ; 2:7/12 2dup 0x00443333 D<> if ld A, 0x44 ; 2:7 2dup 0x00443333 D<> if xor E ; 1:4 2dup 0x00443333 D<> if x[3] = 0x44 or D ; 1:4 2dup 0x00443333 D<> if x[4] = 0 jp z, else101 ; 3:10 2dup 0x00443333 D<> if ;[15:54] ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x00013333)' ;[13:48/20,48,48,48] 2dup 0x00013333 D<> if ( d1 -- d1 ) 0x00013333 <> DEHL ld A, L ; 1:4 2dup 0x00013333 D<> if the beginning of identical values cp H ; 1:4 2dup 0x00013333 D<> if x[1] = x[2] jr nz, $+11 ; 2:7/12 2dup 0x00013333 D<> if xor 0x33 ; 2:7 2dup 0x00013333 D<> if x[2] = 0x33 termination of identical values ld C, E ; 1:4 2dup 0x00013333 D<> if dec C ; 1:4 2dup 0x00013333 D<> if or C ; 1:4 2dup 0x00013333 D<> if x[3] = 1 or D ; 1:4 2dup 0x00013333 D<> if x[4] = 0 jp z, else101 ; 3:10 2dup 0x00013333 D<> if ;[13:48] U tech testu jsem dospel k zaveru, ze pokud jsou v nich vic jak jeden xor na test, tak je ten kod vadny. Musel jsem si to overit v excelu, kde jsem si zkratil cislo na 3 bity a dival se co to udela. Problem je ze kobinaci chyb u vice cisel bude test ukazovat obcas spatne vysledky. Proste pokud mam v cisle jednicku a pokusim se to spojit tak ze Kód: ... inc A xor A dec A ... Tak to pri soubehu chyb selze. Zpetne pouzivani jeste neoverenych hodnot funguje jen u pripadu kdy mame cisla 4,3,2,1 a budou se testovat jako Kód: ld A,D dec A cp E x[3] = x[4]-1 jr nz,... dec A cp H x[2] = x[3]-1 jr nz,... dec A cp L x[1] = x[2]-1 jr nz,... dec A x[4] = 4 Protoze tady nakonec opravdu tu x[4] nezavisle overime na nulu. Ale tento kod neni rychlejsi nez generovany Kód: ../check_word.sh '_2DUP_PUSHDOT_DNE_IF(0x04030201)' ;[17:63/23,38,63,63] 2dup 0x04030201 D<> if ( d1 -- d1 ) 0x04030201 <> DEHL ld A, 0x03 ; 2:7 2dup 0x04030201 D<> if cp E ; 1:4 2dup 0x04030201 D<> if x[1] = 0x03 jr nz, $+14 ; 2:7/12 2dup 0x04030201 D<> if dec A ; 1:4 2dup 0x04030201 D<> if cp H ; 1:4 2dup 0x04030201 D<> if x[2] = x[1] - 1 jr nz, $+10 ; 2:7/12 2dup 0x04030201 D<> if add A, H ; 1:4 2dup 0x04030201 D<> if xor D ; 1:4 2dup 0x04030201 D<> if x[3] = x[2] + x[2] ld C, L ; 1:4 2dup 0x04030201 D<> if dec C ; 1:4 2dup 0x04030201 D<> if or C ; 1:4 2dup 0x04030201 D<> if x[4] = 1 jp z, else101 ; 3:10 2dup 0x04030201 D<> if ;[17:63] Puvodne jsem ten kod psal tak, ze jsem si tu posloupnost 4 cisel seradil a nepouzival odcitani, ale pak mi doslo ze cislo 0x3F201F10 ma kratsi zapis jako x, 2*x, 2*x-1, 2*x-1+2*x. Po case jsem dospel k reseni kdy delam variace te rady, jen ignoruji bajty 255 a 0 (nuly mam vnitrne jako 256, kvuli razeni). Jak napsat v makru variace? No rozepsal jsem si to na "papir" a je to snadne. Udelame vic maker. Mame cisla 1,2,3,4. Posledni jen vola generovani kodu (pokud je lepsi co mame tak ho nahradi) a pokud je cislo na pozici 3 mensi jak 255 tak ho prohodi s cislem na pozici 4 (a s nema prohodi i jmena registru). Pokud prohazoval tak znovu vola generovani kodu (pokud je lepsi co mame tak ho nahradi). Dalsi makro vola posledni makro, pak pokud je cislo na pozici 3 mensi jak 255 tak to zameni s cislem na pozici 2 a pokud prohazoval tak znovu vola posledni makro a udela opet prohozeni 3 a 2 pozice a znovu vola posleni makro. Posledni makro totiz vzdy vymeni cislo na 2 pozici tak to pekne navazuje. Prvni (main) makro nastavi pocatecni hodnoty kodu na nejhorsi a pak vola prostredni makro. Pokud je cislo na 4 pozici mensi nez 255 tak prohodi hodnotu na 4 pozici s hodnotou na 3 pozici a znovu vola prostredni makro, tohle jednou zopakuje a nakonec prohazuje cislo na pozici 4 s cislem na pozici 1 (takove preteceni misto cisla na 5. pozici) a vola naposledy prostredni makro. Posledni makro generuje 2 kody. Prostredni generuje az 6 kodu. Prvni generuje az 24 kodu, coz je variace 4 hodnot kdy zalezi na poradi. Vlastne je to podobne nejakemu kodovani kdy nasledujici cislice se vzdy lisi jen jednim bitem. Zapomel jsem nazev, protoze jsem sklerotik. Takze jsem vedel ze to nejak pujde kdyz se do toho opru. Vaše zpráva obsahuje 18813 znaků. Maximální povolený počet znaků je 17000. |
Autor: | _dworkin [ 22.06.2022, 22:10 ] |
Předmět příspěvku: | Re: Macro FORTH |
Mozna snazi bude ukazat kod Kód: dnl define({____DEQ_VARIATION_21},{dnl __{}dnl debug: __{}dnl format({0x%02X},_TMP_N4)-format({0x%02X},_TMP_N3)-format({0x%02X},_TMP_N2)-format({0x%02X},_TMP_N1) __{}dnl __{}____DEQ_MAKE_CODE($1,$2,$3,$4,$5){}dnl __{}__{}ifelse(____CHEAPER,{1},{dnl __{}__{}__{}define({_TMP_BEST_P},____DEQ_PRICE){}dnl __{}__{}__{}define({_TMP_BEST_B},____DEQ_BYTES){}dnl __{}__{}__{}define({_TMP_BEST_C},____DEQ_CLOCKS){}dnl __{}__{}__{}define({_TMP_BEST_CODE},____DEQ_CODE)}){}dnl __{}ifelse(eval(_TMP_N2<255),{1},{dnl __{}____SWAP2DEF({_TMP_N2},{_TMP_N1}){}dnl __{}____SWAP2DEF({_TMP_R2},{_TMP_R1}){}dnl __{}dnl debug: __{}dnl format({0x%02X},_TMP_N4)-format({0x%02X},_TMP_N3)-format({0x%02X},_TMP_N2)-format({0x%02X},_TMP_N1) __{}dnl __{}____DEQ_MAKE_CODE($1,$2,$3,$4,$5){}dnl __{}__{}ifelse(____CHEAPER,{1},{dnl __{}__{}__{}define({_TMP_BEST_P},____DEQ_PRICE){}dnl __{}__{}__{}define({_TMP_BEST_B},____DEQ_BYTES){}dnl __{}__{}__{}define({_TMP_BEST_C},____DEQ_CLOCKS){}dnl __{}__{}__{}define({_TMP_BEST_CODE},____DEQ_CODE)})})}){}dnl dnl dnl dnl define({____DEQ_VARIATION_32},{dnl __{}____DEQ_VARIATION_21($1,$2,$3,$4,$5){}dnl __{}ifelse(eval(_TMP_N3<255),{1},{dnl __{}____SWAP2DEF({_TMP_N3},{_TMP_N2}){}dnl __{}____SWAP2DEF({_TMP_R3},{_TMP_R2}){}dnl __{}____DEQ_VARIATION_21($1,$2,$3,$4,$5){}dnl __{}____SWAP2DEF({_TMP_N3},{_TMP_N2}){}dnl __{}____SWAP2DEF({_TMP_R3},{_TMP_R2}){}dnl __{}____DEQ_VARIATION_21($1,$2,$3,$4,$5)})}){}dnl dnl dnl dnl define({____DEQ_MAKE_BEST_CODE},{dnl ____DEQ_INIT_CODE($1){}dnl __{}define({_TMP_BEST_P},10000000){}dnl __{}define({_TMP_BEST_B},10000000){}dnl __{}define({_TMP_BEST_C},10000000){}dnl __{}____DEQ_VARIATION_32($1,$2,$3,$4,$5){}dnl __{}ifelse(eval(_TMP_N4<255),{1},{dnl __{}____SWAP2DEF({_TMP_N4},{_TMP_N3}){}dnl __{}____SWAP2DEF({_TMP_R4},{_TMP_R3}){}dnl __{}____DEQ_VARIATION_32($1,$2,$3,$4,$5){}dnl __{}____SWAP2DEF({_TMP_N4},{_TMP_N3}){}dnl __{}____SWAP2DEF({_TMP_R4},{_TMP_R3}){}dnl __{}____DEQ_VARIATION_32($1,$2,$3,$4,$5){}dnl __{}____SWAP2DEF({_TMP_N4},{_TMP_N1}){}dnl __{}____SWAP2DEF({_TMP_R4},{_TMP_R1}){}dnl __{}____DEQ_VARIATION_32($1,$2,$3,$4,$5)})}){}dnl dnl dnl To poradi vypada takto: 0x44-0x33-0x22-0x11 0x44-0x33-0x11-0x22 0x44-0x11-0x33-0x22 0x44-0x11-0x22-0x33 0x44-0x22-0x11-0x33 0x44-0x22-0x33-0x11 0x22-0x44-0x33-0x11 0x22-0x44-0x11-0x33 0x22-0x11-0x44-0x33 0x22-0x11-0x33-0x44 0x22-0x33-0x11-0x44 0x22-0x33-0x44-0x11 0x33-0x22-0x44-0x11 0x33-0x22-0x11-0x44 0x33-0x11-0x22-0x44 0x33-0x11-0x44-0x22 0x33-0x44-0x11-0x22 0x33-0x44-0x22-0x11 0x11-0x44-0x22-0x33 0x11-0x44-0x33-0x22 0x11-0x33-0x44-0x22 0x11-0x33-0x22-0x44 0x11-0x22-0x33-0x44 0x11-0x22-0x44-0x33 nebo takto: 0xFF-0x33-0x22-0x11 0xFF-0x33-0x11-0x22 0xFF-0x11-0x33-0x22 0xFF-0x11-0x22-0x33 0xFF-0x22-0x11-0x33 0xFF-0x22-0x33-0x11 nebo takto: 0xFF-0xFF-0x22-0x11 0xFF-0xFF-0x11-0x22 popripade: 0xFF-0xFF-0xFF-0x11 PS: Nemůžete vytvořit příspěvek tak brzo po předešlém. |
Autor: | _dworkin [ 22.06.2022, 23:01 ] |
Předmět příspěvku: | Re: Macro FORTH |
Ohledne toho generovani kodu, vyvstava jeden problem ze neexistuje a nebo ho neznam zadne kriterium jak porovnat dva kody. Na prvni pohled se to muze zdat jednoduche a vetsinou i je pokud vime co ten kod dela a jak je pouzit. Proste dame urcite vahy na velikost a na rychlost kodu. Ja to ted mam tak ze spocitam CENU kodu a levnejsi vitezi. CENA = 8*(takty+4*bajty). Vynasobene osmi je to kvuli tomu ze makra pocitaji jen s celymi cisly a vy mate kod ktery vapada takto Kód: ../check_word.sh '_2DUP_PUSHDOT_DEQ_IF(0x45352515)' ;[21:75/33,51,69,75] 2dup 0x45352515 D= if ( d1 -- d1 ) 0x45352515 == DEHL ld A, 0x15 ; 2:7 2dup 0x45352515 D= if cp L ; 1:4 2dup 0x45352515 D= if x[1] = 0x15 jr nz, $+15 ; 2:7/12 2dup 0x45352515 D= if ld A, 0x25 ; 2:7 2dup 0x45352515 D= if cp H ; 1:4 2dup 0x45352515 D= if x[2] = 0x25 jr nz, $+10 ; 2:7/12 2dup 0x45352515 D= if ld A, 0x35 ; 2:7 2dup 0x45352515 D= if cp E ; 1:4 2dup 0x45352515 D= if x[3] = 0x35 jr nz, $+5 ; 2:7/12 2dup 0x45352515 D= if ld A, 0x45 ; 2:7 2dup 0x45352515 D= if xor D ; 1:4 2dup 0x45352515 D= if x[4] = 0x45 jp nz, else101 ; 3:10 2dup 0x45352515 D= if ;[21:75] Tady narazim na to ze proste nemam "dynamickou analyzu kodu", nebo jak se tomu nadava, a zpusoby jak naslepo pocitat takty muze byt vice. Ja jsem nakonec zvolil ze jedna vetev je TRUE a ty dalsi 4 jsou FALSE. A obema jsem dal stejnou vahu takze muj prumer byl (75+(33+51+69+75)/4)/2 = (75+57)/2 = 66. Ale ne vzdy to vychazi celociselne tak proto to nasobim osmi. Teda vlastne je to spis: 4*75 + (33+51+69+75). A bajtu jsem zvolil vahu 4 taktu. Pocet bajtu jsou jedine absolutni kriterium, u tech na nic dalsim nezalezi. Jen na jejich vaze oproti rychlosti. Ale to muze byt cele uplne spatne! Co kdyz to cislo pouzivam ve smycce pro ukonceni a ty cisla postupuji kontinualne! Pak je nejefektivnejsi prvni testovat registr "L", protoze kazdy dalsi test se provede 256x mene. Takze kdyz pak spojim test "HL" do jednoho testu a kod vypada kratsi a celkove rychlejsi tak je leda tak kratsi a 256x pomalejsi o kazdy takt navic, kdy srovnam jen takty za "L" test oproti "HL" testu... Proto jsem taky pridal do ceny jeden jediny bod navic pokud neni "L" jako prvni testovany registr. Bez ohledu zda je teda ten test spojeny a ma to nejaky vyznam. To me aspon kdy je to mozny uprednostni kod, ktery ma "L" v testech vepredu. U tech stejnych vah pro TRUE a FALSE jsem to bral tak ze nevim jak ten kod vypada (i kdyz ho budu mit cely k dispozici, ale to chce proste uz nejake AI a ne makro) a co dela. A i kdyz by se mohlo zdat ze tady napriklad u TRUE bude pravdepodobnost 1/(256*256*256*256-1) oproti FALSE kde bude temer rovna jedne, tak to tak proste v kodu normalne nebyva. Jestli na to existuje nejake kriterium (nebo metrika? To by melo byt neco jineho) fakt netusim. Nevite to nekdo? Kod me ted generuje obcas vice variant a vypada to pak nejak takto: Kód: if 0 ; price: 1038 ;[15:71/60,71,71,71] 2dup 0x66330000 D<> ( d1 -- d1 flag ) 0x66330000 <> DEHL ld A, 0x33 ; 2:7 2dup 0x66330000 D<> cp E ; 1:4 2dup 0x66330000 D<> x[1] = 0x33 jr nz, $+6 ; 2:7/12 2dup 0x66330000 D<> add A, E ; 1:4 2dup 0x66330000 D<> xor D ; 1:4 2dup 0x66330000 D<> x[2] = x[1] + x[1] or H ; 1:4 2dup 0x66330000 D<> x[3] = 0 or L ; 1:4 2dup 0x66330000 D<> x[4] = 0 add A, 0xFF ; 2:7 2dup 0x66330000 D<> ex DE, HL ; 1:4 2dup 0x66330000 D<> push HL ; 1:11 2dup 0x66330000 D<> sbc HL, HL ; 2:15 2dup 0x66330000 D<> set flag d1==0x66330000 else ; price: 1014 ;[16:45,72/67] 2dup 0x66330000 D<> ( d1 -- d1 flag ) # default version with 0x????0000 ex DE, HL ; 1:4 2dup 0x66330000 D<> push HL ; 1:11 2dup 0x66330000 D<> ld A, E ; 1:4 2dup 0x66330000 D<> or D ; 1:4 2dup 0x66330000 D<> jr nz, $+9 ; 2:7/12 2dup 0x66330000 D<> ld BC, 0x6633 ; 3:10 2dup 0x66330000 D<> hi16(0x66330000) sbc HL, BC ; 2:15 2dup 0x66330000 D<> HL-hi16(d1) jr z, $+5 ; 2:7/12 2dup 0x66330000 D<> ld HL, 0xFFFF ; 3:10 2dup 0x66330000 D<> set flag d1<>0x66330000 endif Kdy kratsi kod je jen ukazan, ale nepouzit, protoze si makro mysli ze ten defaultni kod je lepsi. A vy si to muzete prohodit, kdyz prepisete nulu na nenulove cislo. |
Autor: | Busy [ 23.06.2022, 12:09 ] |
Předmět příspěvku: | Re: Macro FORTH |
_dworkin píše: Kód: jr nz, $+18 ; 2:7/12 2dup 0x45352515 D<> if (vnutri makra samozrejme lokalne labely, ktore dnes uz vie kazdy poriadny asembler) |
Autor: | Busy [ 23.06.2022, 12:19 ] |
Předmět příspěvku: | Re: Macro FORTH |
_dworkin píše: Proste pokud mam v cisle jednicku a pokusim se to spojit tak ze Obavam sa ze toto zlyha vzdy, pretoze je uplne jedno ci v A je predtym jednicka alebo nie, instrukcia XOR A totalne zvalcuje cele AF...
Kód: ... Tak to pri soubehu chyb selze.inc A xor A dec A ... |
Autor: | _dworkin [ 23.06.2022, 12:45 ] |
Předmět příspěvku: | Re: Macro FORTH |
Busy píše: _dworkin píše: Proste pokud mam v cisle jednicku a pokusim se to spojit tak ze Obavam sa ze toto zlyha vzdy, pretoze je uplne jedno ci v A je predtym jednicka alebo nie, instrukcia XOR A totalne zvalcuje cele AF...Kód: ... Tak to pri soubehu chyb selze.inc A xor A dec A ... Dobry postreh, melo tam byt jakykoliv registr z DEHL, napr. "xor L". |
Stránka 12 z 40 | Všechny časy jsou v UTC + 1 hodina [ Letní čas ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |