OldComp.cz http://www.oldcomp.cz/ |
|
Macro FORTH http://www.oldcomp.cz/viewtopic.php?f=124&t=8564 |
Stránka 21 z 40 |
Autor: | _dworkin [ 18.09.2022, 17:02 ] |
Předmět příspěvku: | Re: Macro FORTH |
Tak jsem vytvoril tohle reseni Kód: define({__TEMP_A},1){}dnl define({__TEMP_B},65535){}dnl ; AAaa*BBbb = ((0x100*AA)+aa)*((0x100*BB)+bb) = 0x10000*AA*BB + 0x100*AA*bb + 0x100*aa*BB + aa*bb ld bc,__TEMP_A ld bc,__TEMP_B ld ix,+((high __TEMP_A)*(high __TEMP_B)) ld ix,+((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>15*0xFF00 + ((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>8 ld ix,+((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>15*0xFF00 + ((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>8 ld de,+((high __TEMP_A)*(high __TEMP_B))+((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>15*0xFF00 + ((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>8+((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>15*0xFF00 + ((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>8 ld bc,+(low((low __TEMP_A)*(high __TEMP_B))) ld bc,+(low((high __TEMP_A)*(low __TEMP_B))) ld bc,+(low __TEMP_A)*(low __TEMP_B)>>8 ld ix,+((low((low __TEMP_A)*(high __TEMP_B)))+(low((high __TEMP_A)*(low __TEMP_B)))+(low __TEMP_A)*(low __TEMP_B)>>8)>>8 ld de,+((high __TEMP_A)*(high __TEMP_B))+((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>15*0xFF00 + ((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>8+((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>15*0xFF00 + ((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>8+((low((low __TEMP_A)*(high __TEMP_B)))+(low((high __TEMP_A)*(low __TEMP_B)))+(low __TEMP_A)*(low __TEMP_B)>>8)>>8 ld hl,+__TEMP_A*__TEMP_B Dulezita je ta cast s ld ix,+((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>15*0xFF00 + ((low __TEMP_A)*(__TEMP_B>>15*0xFF00+__TEMP_B>>8))>>8 ld ix,+((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>15*0xFF00 + ((low __TEMP_B)*(__TEMP_A>>15*0xFF00+__TEMP_A>>8))>>8 To je rozdelene to 0x100*AA*bb --> 0x100*bb*AA 0x100*aa*BB protoze u carry to vypada ze nemusim nic resit, bud je to low a nebo kdyz tam vstupuje high tak se s vysledkem udela low. Viz tri casti pro carry pred posunutim ld bc,+(low((low __TEMP_A)*(high __TEMP_B))) ld bc,+(low((high __TEMP_A)*(low __TEMP_B))) ld bc,+(low __TEMP_A)*(low __TEMP_B)>>8 No a funguje to pro -1*1 nebo -1*1 Kód: 0000:010100 LD BC, 0001 0003:01FFFF LD BC, FFFF 0006:DD210000 LD IX, 0000 000A:DD21FFFF LD IX, FFFF 000E:DD210000 LD IX, 0000 0012:11FFFF LD DE, FFFF 0015:01FF00 LD BC, 00FF 0018:010000 LD BC, 0000 001B:010000 LD BC, 0000 001E:DD210000 LD IX, 0000 0022:11FFFF LD DE, FFFF 0025:21FFFF LD HL, FFFF ale zase to prestane fungovat pro -1*-1.... Kód: 0000:01FFFF LD BC, FFFF 0003:01FFFF LD BC, FFFF 0006:DD2101FE LD IX, FE01 000A:DD21FFFF LD IX, FFFF 000E:DD21FFFF LD IX, FFFF 0012:11FFFD LD DE, FDFF 0015:010100 LD BC, 0001 0018:010100 LD BC, 0001 001B:01FE00 LD BC, 00FE 001E:DD210100 LD IX, 0001 0022:1100FE LD DE, FE00 0025:210100 LD HL, 0001 vznikne FE01 + FFFF + FFFF + 0001 No nic musim do prace. |
Autor: | _dworkin [ 19.09.2022, 02:32 ] |
Předmět příspěvku: | Re: Macro FORTH |
Tak jsem zpet a koukam se na to znovu s odstupem a napada me, ze jsem byl asi jen zmateny. To beznamenkove nasobeni jsem mel predtim dobre... u32bit = u16bit * u16bit Pokud bude jedno z nich jakoby -1 a druhe 1 Tak vysledek bude 0x0000FFFF = 0xFFFF * 0x0001. Hotovo, zadna veda. Je to BEZNAMENKOVE. To ze potrebuji ted aby -1*1 = 0xFFFFFFFF kdyz mi ze vzorecku vypadnou pro high(1)=0 cleny a zbude jen -1*1 = 0x100*high(-1)*1 + -1*1 Bude spis problem s tim ze ten vzorec bude asi platit jen pro s32bit = s32bit * s32bit a ty vstupy teda pro zaporne hodnoty maji byt 0xFFFFFFFF = 0xFFFFFFFF * 0x0001 Asi... Dnes to uz necham plavat. PS: No aspon jsem napsal to unsigned znovu a trosku zkracene. misto (high xxx) je vsude (xxx>>8), je to o znak kratsi. Kde xxx = "(abc)" a nebo pokud to jde spocitat tak jen kladne "cislo" bez zavorek a znamenek. |
Autor: | l00k [ 19.09.2022, 08:12 ] |
Předmět příspěvku: | Re: Macro FORTH |
jenom se zeptám, to si to komplikuješ schválně 2 typy čísel? proč nenecháš jako třeba Pascal jen rozsah 0-32767? poslední bit na znaménko a je klid teď tu mícháš hrušky s jabkama, jak určuješ rozdíl mezi 65534 a -2 ? |
Autor: | _dworkin [ 19.09.2022, 13:02 ] |
Předmět příspěvku: | Re: Macro FORTH |
l00k píše: jenom se zeptám, to si to komplikuješ schválně 2 typy čísel? proč nenecháš jako třeba Pascal jen rozsah 0-32767? poslední bit na znaménko a je klid teď tu mícháš hrušky s jabkama, jak určuješ rozdíl mezi 65534 a -2 ? Tohle jsou operace ktere podporuje primo Forth standart. V podstate ta operace sama rika jake operandy chce, rosah bitu a jak jsou ty vstupni bity interpretovany. Jako signed nebo unsigned. > chce dve signed single cisla a vraci 0 nebo -1 u> chce 2 unsigned single cisla a vraci 0 nebo 0xFFFF (ve skutecnosti vraci -1, protoze je to lepsi definice nezavisla na sirce bunky) m* https://forth-standard.org/standard/core/MTimes um* https://forth-standard.org/standard/core/UMTimes Jeste k tomu Pascalu, Forth ma obecne vsechny cisla stejne (single) velikosti a to je rovno velikosti "bunky/cell". Byvalo to minimalne 16bitu, protoze ta bunka muze obsahovat i pointer a nebo "cislo slova" ve slovniku(nevim jiste). Pozdeji velikost bunky rostla jak rostl rozsah u procesoru. Pokud operace nerekne neco jinak tak je to signed, presne jako v Pascalu. Ale Forth muze mit i rozsirenou podporu pro double cisla. Kdy zacne interpetovat 2 bunky jako jedno cislo. Teda minimalne 32bitu. Ma pak k tomu nejake dalsi aritmeticke operace, kdy muze byt prvni operand 32 bitovy a druhy 16 bitovy. Napriklad deleni. Kdy se tim casto obchazela nutnost mit realna cisla. Tyhle slova s ruznymi sirkami casto obsahuji M v nazvu. fm/mod https://forth-standard.org/standard/core/FMDivMOD sm/rem https://forth-standard.org/standard/core/SMDivREM s>d https://forth-standard.org/standard/core/StoD A nadstandart uz je zbytek slov, co delaji da se rici to same co normalni slova, ale s double presnosrti (obsahuji D nebo 2 v nazvu) https://forth-standard.org/standard/double DABS D.R D= DMAX DMIN D- DNEGATE D+ D2/ D2* DU< D0= D0< D. D< D>S M+ M*/ 2CONSTANT 2LITERAL 2ROT 2VALUE 2VARIABLE PS: rozdíl mezi 65534 a -2 Dival jsem se a zadne UADD ani USUB nemam. Pri -1 = 0xFFFF neni UADD potreba. Presneji neni potreba znamenkovy ADD, protoze vnitrne to diky tomu formatu cisel zvladne spocitat procesor jako unsigned se spravnymi vysledky i pro signed. SUB z toho prikladu udela nulu. Protoze to nevidi jako 65534 a 2 ale oboje vidi jako %1111 1111 1111 1110. Protoze 65534 je slovo pro ulozeni %1111 1111 1111 1110 na zasobnik a -2 je slovo pro ulozeni %1111 1111 1111 1110 na zasobnik. SUB uz nic neresi a vyzvedne si ze zasobniku 2 hodnoty. Resit to musim jen ja, kdyz bych to v tokenech chtel zamenit za "0". Musel bych se na to divat stejne. Problem by nastal jen kdyby existovalo slovo MSUB. Kde prvni operand by byl double(signed) a druhy single(signed) a vysledek double(signed). Tak bych nedelal nic protoze jsi za 65534 nedal tecku. Kdyby to bylo s teckou 65534. -2 - tak uz by to slo vyhodnotit. Protoze tecka rika ze to prvni cislo je double a vysledek by mel byt 65536. Resit bych to musel bud asi ze bych -2 rozsiril na double. A nebo si zjistil znamenko druheho operandu a kdyz by bylo minus tak udelal absolutni hodnotu a tu pak prictial. Urcite bych vyzkousel oboji co je kratsi v Z80. To same by bylo i pri 0 65534 -2. Ale ne podle Forth standartu, protoze tam by to melo byt 65534 0 -2. Ja mam prohozeny high16 a low16 cast na zasobniku. Ale to uz asi dost odbiham. A da se rici ze si to urcite komplikuji schvalne, protoze neexistuje jediny duvod proc se bavit zrovna timhle. PPS: Vlastne existuje koukam MADD coz je v podstate to same... .) Dobra skleroza. Kód: push DE ; 1:11 65534. -2 ( -- 0x0000 0xFFFE -2 ) push HL ; 1:11 65534. -2 ld HL, 0x0000 ; 3:10 65534. -2 push HL ; 1:11 65534. -2 dec HL ; 1:6 65534. -2 dec L ; 1:4 65534. -2 ld D, H ; 1:4 65534. -2 D = H = 0xFF ld E, L ; 1:4 65534. -2 E = L = 0xFE ;[11:57] M+ ( d x -- d2 ) d2 = d + x ld A, H ; 1:4 M+ add A, A ; 1:4 M+ sbc A, A ; 1:4 M+ ld C, A ; 1:4 M+ CC = hi16(x) add HL, DE ; 1:11 M+ lo16(d)+x pop DE ; 1:10 M+ adc A, E ; 1:4 M+ ld E, A ; 1:4 M+ ld A, C ; 1:4 M+ adc A, D ; 1:4 M+ ld D, A ; 1:4 M+ hi16(d)+hi16(x) ;[21:118] Uf! Myslim ze jsem pochopil jak jsem to resil, jestli spravne netusim(ale vypada to dobre i s tim prvnim adc). To zahadne CC je ve skutecnosti mysleno tak ze ta operace je DEHL=(SP-1)(SP)DE + HL = (SP-1)(SP)DE + CCHL Kde registr C nastavim na 0xFF nebo 0x00 podle 7. bitu v H (znamenko). A koukam ze jsem to jeste neresil v tokenech. Ale ted mam prioritu to MMUL, a kdyz mi to nepujde (reseni 100% existuje) tak udelat v sjasmplus podporu pro FM/mod, to by mela byt taky vyzva. Zmenil jsem komentare na Kód: sbc A, A ; 1:4 M+ 0xFF or 0x00 mozna to priste pochopim snaz.
ld C, A ; 1:4 M+ d2 = d + CCHL |
Autor: | _dworkin [ 19.09.2022, 14:45 ] |
Předmět příspěvku: | Re: Macro FORTH |
_dworkin píše: Pracoval jsem na signed16 * signed16 = signed32 nasobeni pro Pasmo a dospel jsem k vzorci high16(signed32) = high16(u16_A*u16_B) - (u16_A>>15)*(u_16A) - (u16_B>>15)*(u_16_B) low16(signed32) = u16_A*u16_B tady se nic nemusi resit a mohu to nasobit unsigned Casem jsem ten vzorec opravil protoze misto - (u16_A>>15)*(u_16A) - (u16_B>>15)*(u_16_B) ma byt - (u16_B>>15)*(u_16A) - (u16_A>>15)*(u_16_B) protoze jak pisi jeste v tom samem prispevku nize _dworkin píše: +*- A*(B-16)=A*B-16*A 1*-2 = 1*14 -16*1 = 14 - 16 = -2 2*-3 = 2*13 -16*2 = 26 - 32 = -6 -*+ (A-16)*B=A*B-16*B -1*2 = 15*2 - 16*2 = 30 - 32 = -2 -2*3 = 14*3 - 16*3 = 42 - 48 = -6 Jak jsem ted vratil vzorec pro (unsigned) ummul zpet, tak jsem tam dal i tu spravnou variantu a ... -1*-1 mi ukazuje u high(16) 0 -1*1 mi ukazuje u high(16) -1 1*-1 mi ukazuje u high(16) -1 1*1 mi ukazuje u high(16) 0 Argh! Lol. Bude to chtit jeste nejake testy potom. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU -1 PUSH(abc) PUSH(1) MMUL' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(m*,abc,1) __TEMP_A:>< __TEMP_B:>0x0001< abc EQU FFFF 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11FFFF LD DE, FFFF 0005:21FFFF LD HL, FFFF Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU -1 PUSH(abc) PUSH(-1) MMUL' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(m*,abc,-1) __TEMP_A:>< __TEMP_B:>-1< abc EQU FFFF 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:110000 LD DE, 0000 0005:210100 LD HL, 0001 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 1 PUSH(abc) PUSH(-1) MMUL' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(m*,abc,-1) __TEMP_A:>< __TEMP_B:>-1< abc EQU 0001 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11FFFF LD DE, FFFF 0005:21FFFF LD HL, FFFF Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 1 PUSH(abc) PUSH(1) MMUL' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(m*,abc,1) __TEMP_A:>< __TEMP_B:>0x0001< abc EQU 0001 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:110000 LD DE, 0000 0005:210100 LD HL, 0001 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ cat -n smaz.asm 1 abc EQU 1 2 ;[8:42] abc 1 m* ( -- +((abc)>>8)*(1>>8)+(low (abc))*(1>>8)>>8+(low 1)*((abc)>>8)>>8+((low((low (abc))*(1>>8)))+(low(((abc)>>8)*(low 1)))+(low (abc))*(low 1)>>8)>>8-(((abc))>>15)*(1)-((1)>>15)*((abc)) +((abc))*(1) ) 3 push DE ; 1:11 abc 1 m* 4 push HL ; 1:11 abc 1 m* 5 ld DE, +((abc)>>8)*(1>>8)+(low (abc))*(1>>8)>>8+(low 1)*((abc)>>8)>>8+((low((low (abc))*(1>>8)))+(low(((abc)>>8)*(low 1)))+(low (abc))*(low 1)>>8)>>8-(((abc))>>15)*(1)-((1)>>15)*((abc)); 3:10 abc 1 m* 6 ld HL, +((abc))*(1); 3:10 abc 1 m* 7 ;[ 8:42] dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ PS: Hmm jak se na to divam tak muzu uestrit nejake znaky kdyz zmenim vstup z "cislo" nebo "(neznama)" na " cislo" nebo "(neznama)" a pak mohu za low zrusit mezeru. PPS: Ale to bych si pridal zbytecne mezeru zase u operaci jako & kde ji nepotrebuji. Takze jsem to vyresil jinak Kód: ... dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 1 PUSH(abc) PUSH(1) MMUL' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(m*,abc,1) __TEMP_A:>< __TEMP_B:>0x0001< abc EQU 0001 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:110000 LD DE, 0000 0005:210100 LD HL, 0001 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ cat -n smaz.asm 1 abc EQU 1 2 ;[8:42] abc 1 m* ( -- +((abc)>>8)*0+(low(abc))*0>>8+1*((abc)>>8)>>8+((low((low(abc))*0))+(low(((abc)>>8)*1))+(low(abc))*1>>8)>>8-((abc)>>15)*1-0*(abc) +(abc)*1 ) 3 push DE ; 1:11 abc 1 m* 4 push HL ; 1:11 abc 1 m* 5 ld DE, +((abc)>>8)*0+(low(abc))*0>>8+1*((abc)>>8)>>8+((low((low(abc))*0))+(low(((abc)>>8)*1))+(low(abc))*1>>8)>>8-((abc)>>15)*1-0*(abc); 3:10 abc 1 m* 6 ld HL, +(abc)*1 ; 3:10 abc 1 m* 7 ;[ 8:42 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ __{}ifelse(__HEX_HL($2),{},{define({__TEMP_A},{($2)})},{define({__TEMP_A},{eval(($2)&0xFFFF)})}){}dnl __{}ifelse(__HEX_HL($3),{},{define({__TEMP_B},{($3)})},{define({__TEMP_B},{eval(($3)&0xFFFF)})}){}dnl __{}ifelse(__HEX_HL($2),{},{define({__TEMP_LO_A},{(low($2))})},{define({__TEMP_LO_A},{eval(($2)&0xFF)})}){}dnl __{}ifelse(__HEX_HL($3),{},{define({__TEMP_LO_B},{(low($3))})},{define({__TEMP_LO_B},{eval(($3)&0xFF)})}){}dnl __{}ifelse(__HEX_HL($2),{},{define({__TEMP_HI_A},{(($2)>>8)})},{define({__TEMP_HI_A},{eval((($2)>>8)&0xFF)})}){}dnl __{}ifelse(__HEX_HL($3),{},{define({__TEMP_HI_B},{(($3)>>8)})},{define({__TEMP_HI_B},{eval((($3)>>8)&0xFF)})}){}dnl __{}ifelse(__HEX_HL($2),{},{define({__TEMP_SIGN_A},{(($2)>>15)})},{define({__TEMP_SIGN_A},{eval((($2)>>15)&0x01)})}){}dnl __{}ifelse(__HEX_HL($3),{},{define({__TEMP_SIGN_B},{(($3)>>15)})},{define({__TEMP_SIGN_B},{eval((($3)>>15)&0x01)})}){}dnl Trochu me zmatlo ze pravou(else) stranu musim resit jinak, protoze to vyhodnocuje M4 ale chybky odstraneny. Ted uz kdyz zna hodnotu tak misto vzorce rovnou spocita znamenko, hi, lo, nebo tu hodnotu. Opravena dokonce i leva strana kde me zase obcas chybela zavorka takze pokud by teoreticky byl vstup "abc+5" tak... Hm.. ze bych si to jeste vic zkomplikoval a resil i ze nasobim nulou nebo jednickou a odsrtanoval ty podvyrazy? |
Autor: | _dworkin [ 19.09.2022, 16:27 ] |
Předmět příspěvku: | Re: Macro FORTH |
__{}__{}$1, {m*},{ifelse(dnl __{}__{}__{}__TEMP_HI_A,0,0, __{}__{}__{}__TEMP_HI_B,0,0, __{}__{}__{}__TEMP_HI_A,1,+__TEMP_HI_B, __{}__{}__{}__TEMP_HI_B,1,+__TEMP_HI_A, __{}__{}__{}+__TEMP_HI_A*__TEMP_HI_B){}dnl __{}__{}__{}ifelse(dnl __{}__{}__{}__TEMP_LO_A,0,{}, __{}__{}__{}__TEMP_HI_B,0,{}, __{}__{}__{}__TEMP_LO_A,1,{}, __{}__{}__{}__TEMP_HI_B,1,{}, __{}__{}__{}+__TEMP_LO_A*__TEMP_HI_B>>8){}dnl __{}__{}__{}ifelse(dnl __{}__{}__{}__TEMP_HI_A,0,{}, __{}__{}__{}__TEMP_LO_B,0,{}, __{}__{}__{}__TEMP_HI_A,1,{}, __{}__{}__{}__TEMP_LO_B,1,{}, __{}__{}__{}+__TEMP_HI_A*__TEMP_LO_B>>8){}dnl __{}__{}__{}ifelse(dnl __{}__{}__{}__TEMP_LO_A,0,{}, __{}__{}__{}__TEMP_LO_B,0,{}, __{}__{}__{}__TEMP_HI_A:__TEMP_HI_B,0:0,{}, __{}__{}__{}__TEMP_A,1,{}, __{}__{}__{}__TEMP_B,1,{}, __{}__{}__{}__TEMP_HI_A,0,+((low(__TEMP_LO_A*__TEMP_HI_B))+__TEMP_LO_A*__TEMP_LO_B>>8)>>8, __{}__{}__{}__TEMP_HI_B,0,+((low(__TEMP_HI_A*__TEMP_LO_B))+__TEMP_LO_A*__TEMP_LO_B>>8)>>8, __{}__{}__{}+((low(__TEMP_LO_A*__TEMP_HI_B))+(low(__TEMP_HI_A*__TEMP_LO_B))+__TEMP_LO_A*__TEMP_LO_B>>8)>>8){}dnl __{}__{}__{}ifelse(dnl __{}__{}__{}__TEMP_SIGN_A,0,{}, __{}__{}__{}__TEMP_SIGN_A,1,-__TEMP_B, __{}__{}__{}-__TEMP_SIGN_A*__TEMP_B){}dnl __{}__{}__{}ifelse(dnl __{}__{}__{}__TEMP_SIGN_B,0,{}, __{}__{}__{}__TEMP_SIGN_B,1,-__TEMP_A, __{}__{}__{}-__TEMP_SIGN_B*__TEMP_A){}dnl __{}__{}__{},dnl __{}__{}__{}ifelse(dnl __{}__{}__{}__TEMP_A,0,0, __{}__{}__{}__TEMP_B,0,0, __{}__{}__{}__TEMP_A,1,+__TEMP_B, __{}__{}__{}__TEMP_B,1,+__TEMP_A, __{}__{}__{}+__TEMP_A*__TEMP_B)}, Vznikly me zajimave varianty, kdy sice cast kodu nebyla nulova, ale protoze se pocitala pro carry, tak nebylo s cim to pricist takze se nemusela pocitat. Uvodni pripadnou nulu jsem ponechal, abych se vyhnul problemum s pripadnym minuskem. To bude docela horor to pak testovat... .) Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU -1 PUSH(abc) PUSH(1) MMUL' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU -1 2 ;[8:42] abc 1 m* ( -- 0-((abc)>>15)*1 +(abc) ) 3 push DE ; 1:11 abc 1 m* 4 push HL ; 1:11 abc 1 m* 5 ld DE, 0-((abc)>>15)*1; 3:10 abc 1 m* 6 ld HL, +(abc) ; 3:10 abc 1 m* 7 ;[ 8:42] abc EQU FFFF 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11FFFF LD DE, FFFF 0005:21FFFF LD HL, FFFF Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU -1 PUSH(abc) PUSH(-1) MMUL' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU -1 2 ;[8:42] abc -1 m* ( -- +((abc)>>8)*255+(low(abc))*255>>8+((abc)>>8)*255>>8+((low((low(abc))*255))+(low(((abc)>>8)*255))+(low(abc))*255>>8)>>8-((abc)>>15)*65535-(abc) +(abc)*65535 ) 3 push DE ; 1:11 abc -1 m* 4 push HL ; 1:11 abc -1 m* 5 ld DE, +((abc)>>8)*255+(low(abc))*255>>8+((abc)>>8)*255>>8+((low((low(abc))*255))+(low(((abc)>>8)*255))+(low(abc))*255>>8)>>8-((abc)>>15)*65535-(abc); 3:10 abc -1 m* 6 ld HL, +(abc)*65535; 3:10 abc -1 m* 7 ;[ 8:42] abc EQU FFFF 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:110000 LD DE, 0000 0005:210100 LD HL, 0001 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 1 PUSH(abc) PUSH(-1) MMUL' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 1 2 ;[8:42] abc -1 m* ( -- +((abc)>>8)*255+(low(abc))*255>>8+((abc)>>8)*255>>8+((low((low(abc))*255))+(low(((abc)>>8)*255))+(low(abc))*255>>8)>>8-((abc)>>15)*65535-(abc) +(abc)*65535 ) 3 push DE ; 1:11 abc -1 m* 4 push HL ; 1:11 abc -1 m* 5 ld DE, +((abc)>>8)*255+(low(abc))*255>>8+((abc)>>8)*255>>8+((low((low(abc))*255))+(low(((abc)>>8)*255))+(low(abc))*255>>8)>>8-((abc)>>15)*65535-(abc); 3:10 abc -1 m* 6 ld HL, +(abc)*65535; 3:10 abc -1 m* 7 ;[ 8:42] abc EQU 0001 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11FFFF LD DE, FFFF 0005:21FFFF LD HL, FFFF Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 1 PUSH(abc) PUSH(1) MMUL' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 1 2 ;[8:42] abc 1 m* ( -- 0-((abc)>>15)*1 +(abc) ) 3 push DE ; 1:11 abc 1 m* 4 push HL ; 1:11 abc 1 m* 5 ld DE, 0-((abc)>>15)*1; 3:10 abc 1 m* 6 ld HL, +(abc) ; 3:10 abc 1 m* 7 ;[ 8:42] abc EQU 0001 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:110000 LD DE, 0000 0005:210100 LD HL, 0001 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ Asi bych mohl poresit i tu -1. Je to jako pest na oko ten rozdil. |
Autor: | _dworkin [ 19.09.2022, 16:49 ] |
Předmět příspěvku: | Re: Macro FORTH |
Ono to asi fakt funguje. 0x4444*128 = 2236928 = 0x222200 0x8888*128 = (0x8888-0x10000)*128 = 30584*128 = -3914752 --> 0x100000000 - 3914752 = 4291052544 = 0xFFC44400 Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0x4444 PUSH(abc) PUSH(128) MMUL' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 0x4444 2 ;[8:42] abc 128 m* ( -- 0+((abc)>>8)*128>>8+((low(((abc)>>8)*128))+(low(abc))*128>>8)>>8-((abc)>>15)*128 +(abc)*128 ) 3 push DE ; 1:11 abc 128 m* 4 push HL ; 1:11 abc 128 m* 5 ld DE, 0+((abc)>>8)*128>>8+((low(((abc)>>8)*128))+(low(abc))*128>>8)>>8-((abc)>>15)*128; 3:10 abc 128 m* 6 ld HL, +(abc)*128 ; 3:10 abc 128 m* 7 ;[ 8:42] abc EQU 4444 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:112200 LD DE, 0022 0005:210022 LD HL, 2200 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0x8888 PUSH(abc) PUSH(128) MMUL' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 0x8888 2 ;[8:42] abc 128 m* ( -- 0+((abc)>>8)*128>>8+((low(((abc)>>8)*128))+(low(abc))*128>>8)>>8-((abc)>>15)*128 +(abc)*128 ) 3 push DE ; 1:11 abc 128 m* 4 push HL ; 1:11 abc 128 m* 5 ld DE, 0+((abc)>>8)*128>>8+((low(((abc)>>8)*128))+(low(abc))*128>>8)>>8-((abc)>>15)*128; 3:10 abc 128 m* 6 ld HL, +(abc)*128 ; 3:10 abc 128 m* 7 ;[ 8:42] abc EQU 8888 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11C4FF LD DE, FFC4 0005:210044 LD HL, 4400 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ To je tak absurdni ze se musim smat. FORTH! -- co? proc? Z80! -- co? proc? Pasmo! -- co? proc? Nerez, divej! 0+((abc)>>8)*128>>8+((low(((abc)>>8)*128))+(low(abc))*128>>8)>>8-((abc)>>15)*128 -- ???????????? Nadhera co? -- !!!!!!!!!!! To je spravnym smerem usmerneny troling. Kdyby me tohle nekdo ukazal, tak bych si rekl ze je blazen. .) Ke vsemu je to kod, ktery je uz urcen pro linker... Ale stale se to snazim psat, aby to bylo citelne pro cloveka. I kdyz tenhle kousek je uz za hranou. PS: Podle tehle definice blaznostvi je blazen i Adam Ondra. Ale asi mensi, protoze ho to uzivi. |
Autor: | _dworkin [ 19.09.2022, 19:51 ] |
Předmět příspěvku: | Re: Macro FORTH |
Doplnil jsem podporu v tokenech pro pripad PUSH3 MADD. U toho jsem opravil chyby u ostatnich pravidel, ktere pozaduji PUSH3(chteji 3 hodnoty, pripadne jednu double), protoze jsem predtim mel spatnou kontrolu na detekci pointeru. Resil jsem jen posledni 2 parametry a ne tri. Musel jsem kvuli M4 pridat fci __32BIT_TO_SIGN, ktera dokaze prevest 0x87654321 na zaporne cislo. Je mi trochu zahadou jak to M4 dela protoze reseni co mi funguje pouziva -0x100000000 a to je vic jak 32bitu. SJASMPLUS byla hracka. U Pasma jsem se zapotil, ale po predchozim hrani s MMUL a UMMUL to nebylo tak hrozne, mozna to neni uplne nejsnazsi reseni a predpoklada ze prvni parametr NENI neznama. Asi budu muset prekopat jeste ty vstupy na 3 parametry, protoze je prevadim prvne na 2 parmetry pomoci $1 << 16 + $2, $3 (vypada to teda trosku jinak, ale tohle je pro predstavu) No a asi bude lepsi zmenit spis fci __EVAL_S16 tak aby brala o parametr vic. Protoze pak mohou byt $1 a $2 klidne abc,def a kdyz pak budu dolovat u m+ hornich 16 bitu tak nemusim uz nic resit. hmmm... A jeste jsem se kouknul jak prevadim PUSHDOT na PUSH2 a mel jsem to spatne, protoze jsem neresil ze vstup neni hodnota a rovnou delal __HEX_DE($1),HEX_HL($1) Takze to musim osetrit a bude me tam stale stasit PUSHDOT(xxx), ale s tim je tezke provadet nejake kejkle tak to nemusi vadit. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0xFFFE PUSHDOT(0x87654321) PUSH(0xFFFE) MADD' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin
1 abc EQU 0xFFFE 2 ;[8:42] 0x87654321. 0xFFFE m+ ( -- -30875 17183 ) 3 push DE ; 1:11 0x87654321. 0xFFFE m+ 4 push HL ; 1:11 0x87654321. 0xFFFE m+ 5 ld DE, 0x8765 ; 3:10 0x87654321. 0xFFFE m+ 6 ld HL, 0x431F ; 3:10 0x87654321. 0xFFFE m+ 7 ;[ 8:42] abc EQU FFFE 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:116587 LD DE, 8765 0005:211F43 LD HL, 431F WARNING: Var abc is never used on line 1 of file smaz.asm Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0xFFFE PUSHDOT(0x87654321) PUSH(abc) MADD' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 0xFFFE 2 ;[8:42] 0x87654321. abc m+ ( -- 0x8765+((abc)>>15)*0xFFFF+(67+((abc)>>8)+(33+(low(abc)))>>8)>>8 17185+(abc) ) 3 push DE ; 1:11 0x87654321. abc m+ 4 push HL ; 1:11 0x87654321. abc m+ 5 ld DE, 0x8765+((abc)>>15)*0xFFFF+(67+((abc)>>8)+(33+(low(abc)))>>8)>>8; 3:10 0x87654321. abc m+ 6 ld HL, 17185+(abc); 3:10 0x87654321. abc m+ 7 ;[ 8:42] abc EQU FFFE 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:116587 LD DE, 8765 0005:211F43 LD HL, 431F Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0xFFFE __ASM({define({__LINKER},sjasmplus)}) PUSHDOT(0x87654321) PUSH(abc) MADD' > smaz.asm && cat -n smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst (0x8765<<16)+0x4321 mh+ abc -2023406815 mh+ (abc) (0x8765<<16)+0x4321 ml+ abc -2023406815 ml+ (abc) 1 abc EQU 0xFFFE 2 3 ;[8:42] 0x87654321. abc m+ ( -- (-2023406815+(((abc)<<16)>>16))>>16 17185+(((abc)<<16)>>16) ) 4 push DE ; 1:11 0x87654321. abc m+ 5 push HL ; 1:11 0x87654321. abc m+ 6 ld DE, (-2023406815+(((abc)<<16)>>16))>>16; 3:10 0x87654321. abc m+ 7 ld HL, 17185+(((abc)<<16)>>16); 3:10 0x87654321. abc m+ 8 ;[ 8:42] SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 9 lines, work time: 0.000 seconds # file opened: smaz.asm 1 0000 abc EQU 0xFFFE 2 0000 3 0000 ;[8:42] 0x87654321. abc m+ ( -- (-2023406815+(((abc)<<16)>>16))>>16 17185+(((abc)<<16)>>16) ) 4 0000 D5 push DE ; 1:11 0x87654321. abc m+ 5 0001 E5 push HL ; 1:11 0x87654321. abc m+ 6 0002 11 65 87 ld DE, (-2023406815+(((abc)<<16)>>16))>>16; 3:10 0x87654321. abc m+ 7 0005 21 1F 43 ld HL, 17185+(((abc)<<16)>>16); 3:10 0x87654321. abc m+ 8 0008 ;[ 8:42] 9 0008 # file closed: smaz.asm dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0xFFFE PUSHDOT(0x11223344) PUSH(0xFFFE) MADD' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 0xFFFE 2 ;[8:42] 0x11223344. 0xFFFE m+ ( -- 4386 13122 ) 3 push DE ; 1:11 0x11223344. 0xFFFE m+ 4 push HL ; 1:11 0x11223344. 0xFFFE m+ 5 ld DE, 0x1122 ; 3:10 0x11223344. 0xFFFE m+ 6 ld HL, 0x3342 ; 3:10 0x11223344. 0xFFFE m+ 7 ;[ 8:42] abc EQU FFFE 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:112211 LD DE, 1122 0005:214233 LD HL, 3342 WARNING: Var abc is never used on line 1 of file smaz.asm Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0xFFFE PUSHDOT(0x11223344) PUSH(abc) MADD' > smaz.asm && cat -n smaz.asm && pasmo -d smaz.asm smaz.bin 1 abc EQU 0xFFFE 2 ;[8:42] 0x11223344. abc m+ ( -- 0x1122+((abc)>>15)*0xFFFF+(51+((abc)>>8)+(68+(low(abc)))>>8)>>8 13124+(abc) ) 3 push DE ; 1:11 0x11223344. abc m+ 4 push HL ; 1:11 0x11223344. abc m+ 5 ld DE, 0x1122+((abc)>>15)*0xFFFF+(51+((abc)>>8)+(68+(low(abc)))>>8)>>8; 3:10 0x11223344. abc m+ 6 ld HL, 13124+(abc); 3:10 0x11223344. abc m+ 7 ;[ 8:42] abc EQU FFFE 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:112211 LD DE, 1122 0005:214233 LD HL, 3342 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0xFFFE __ASM({define({__LINKER},sjasmplus)}) PUSHDOT(0x11223344) PUSH(abc) MADD' > smaz.asm && cat -n smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst (0x1122<<16)+0x3344 mh+ abc 287454020 mh+ (abc) (0x1122<<16)+0x3344 ml+ abc 287454020 ml+ (abc) 1 abc EQU 0xFFFE 2 3 ;[8:42] 0x11223344. abc m+ ( -- (287454020+(((abc)<<16)>>16))>>16 13124+(((abc)<<16)>>16) ) 4 push DE ; 1:11 0x11223344. abc m+ 5 push HL ; 1:11 0x11223344. abc m+ 6 ld DE, (287454020+(((abc)<<16)>>16))>>16; 3:10 0x11223344. abc m+ 7 ld HL, 13124+(((abc)<<16)>>16); 3:10 0x11223344. abc m+ 8 ;[ 8:42] SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 9 lines, work time: 0.000 seconds # file opened: smaz.asm 1 0000 abc EQU 0xFFFE 2 0000 3 0000 ;[8:42] 0x11223344. abc m+ ( -- (287454020+(((abc)<<16)>>16))>>16 13124+(((abc)<<16)>>16) ) 4 0000 D5 push DE ; 1:11 0x11223344. abc m+ 5 0001 E5 push HL ; 1:11 0x11223344. abc m+ 6 0002 11 22 11 ld DE, (287454020+(((abc)<<16)>>16))>>16; 3:10 0x11223344. abc m+ 7 0005 21 42 33 ld HL, 13124+(((abc)<<16)>>16); 3:10 0x11223344. abc m+ 8 0008 ;[ 8:42] 9 0008 # file closed: smaz.asm dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ |
Autor: | _dworkin [ 20.09.2022, 01:53 ] |
Předmět příspěvku: | Re: Macro FORTH |
Doplnil jsem do sjasmplus verze fm/mod deleni. Snazil jsem se to udelat pres ? : operator a sjasmplus porad kricel chyby, tak jsem se kouknul jak to maji udelane a nemaji to vubec. .) Takze jsem to resil jinak, nakonec i o trosku kratsim zpusobem. Neni to az tak hrozne... Vyuzil jsem toho, ze pri logicke operaci sjasmplus vraci -1 nebo 0. Takze se na to da pouzit binarni &. A zbytek jsem resil pomoci nasobeni 1 nebo nulou. __{}__{}$1,{sm/},{+__TEMP_CA/__TEMP_SB}, __{}__{}$1,{fm/},+__TEMP_CA/__TEMP_SB-(((__TEMP_CA%__TEMP_SB)!=0)&((((__TEMP_CA%__TEMP_SB)^__TEMP_B)>>15)&1)), __{}__{}$1,{sm%},{+__TEMP_CA%__TEMP_SB}, __{}__{}$1,{fm%},+((__TEMP_CA%__TEMP_SB)!=0)&(((((__TEMP_CA%__TEMP_SB)^__TEMP_B)>>15)&1)*__TEMP_SB+(__TEMP_CA%__TEMP_SB)), Radsi doplnim legendu: __TEMP_CA je 32bitovy delenec __TEMP_B je delitel __TEMP_SB je delitel upraveny tak ze ma znamenko Moc logiky to nema, jen me proste chodi ty parametry jako: operator,A,B,C Kde C neni vzdy a pokud je tak je to hornich 16bitu toho A. M4 reseni je trosku citelnejsi (z nej jsem odvozoval to pro sjasmplus) __{}__{}$1,{fm/}, {define({__TEMP},eval(__32BIT_TO_SIGN((($4)<<16)+$2) / __16BIT_TO_SIGN($3))){}dnl __{}__{}__{}__{}__{}__{}define({__REM},eval(__32BIT_TO_SIGN((($4)<<16)+$2) % __16BIT_TO_SIGN($3))){}dnl __{}__{}__{}__{}__{}__{}ifelse(__REM,0,{}, __{}__{}__{}__{}__{}__{}eval((__REM ^ ($3)) & 0x8000),{0},{}, __{}__{}__{}__{}__{}__{}{define({__TEMP},eval(__TEMP-1))})}, __{}__{}$1,{sm%}, {define({__TEMP},eval(__32BIT_TO_SIGN((($4)<<16)+$2) % __16BIT_TO_SIGN($3)))}, __{}__{}$1,{fm%}, {define({__TEMP},eval(__32BIT_TO_SIGN((($4)<<16)+$2) % __16BIT_TO_SIGN($3))){}dnl __{}__{}__{}__{}__{}__{}ifelse(__TEMP,0,{}, __{}__{}__{}__{}__{}__{}eval((__TEMP ^ ($3)) & 0x8000),{0},{}, __{}__{}__{}__{}__{}__{}{define({__TEMP},eval($3+__TEMP))})}, Kdybych to potreboval popsat slovy tak je to fm/ 1. Udelam to stejne jako pro sm/, tedy signed double deleno signed single 2. Musim si spocitat i to same pro modulo 3. Pokud je vysledek z mod nula nedelam uz nic 4. Pokud ma vysledek z mod stejne znamenko jak delitel nedelam uz nic 5. Odectu jednicku od vysledku z bodu 1 fm% 1. Udelam to stejne jako pro sm%, tedy signed double modulo signed single 2. Pokud je vysledek z mod nula nedelam uz nic (tohle krasne vyuziva to (s32%s16)!=0)&... 3. Pokud ma vysledek z mod stejne znamenko jak delitel nedelam uz nic 4. Prictu k vysledku delitele Viz tabulka kde ve sloupci je delitel a v radcich delenec. Prvni hodnota je deleni a druha mod. Kód: 4 4 -4 -4 fm/mod sm/rem fm/mod sm/rem -10 -3 2 -2 -2 2 -2 2 -2 -10 -9 -3 3 -2 -1 2 -1 2 -1 -9 -8 -2 0 -2 0 2 0 2 0 -8 -7 -2 1 -1 -3 1 -3 1 -3 -7 -6 -2 2 -1 -2 1 -2 1 -2 -6 -5 -2 3 -1 -1 1 -1 1 -1 -5 -4 -1 0 -1 0 1 0 1 0 -4 -3 -1 1 0 -3 0 -3 0 -3 -3 -2 -1 2 0 -2 0 -2 0 -2 -2 -1 -1 3 0 -1 0 -1 0 -1 -1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 -1 -3 0 1 1 2 0 2 0 2 -1 -2 0 2 2 3 0 3 0 3 -1 -1 0 3 3 4 1 0 1 0 -1 0 -1 0 4 5 1 1 1 1 -2 -3 -1 1 5 6 1 2 1 2 -2 -2 -1 2 6 7 1 3 1 3 -2 -1 -1 3 7 8 2 0 2 0 -2 0 -2 0 8 9 2 1 2 1 -3 -3 -2 1 9 10 2 2 2 2 -3 -2 -2 2 10 Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU -4 __ASM({define({__LINKER},sjasmplus)}) PUSHDOT(-10) PUSH(abc) FMDIVMOD' > smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 9 lines, work time: 0.000 seconds # file opened: smaz.asm 1 0000 abc EQU -4 2 0000 3 0000 ;[8:42] -10. abc fm/mod ( -- +((-10%(((abc)<<16)>>16))!=0)&(((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(-10%(((abc)<<16)>>16))) +-10/(((abc)<<16)>>16)-(((-10%(((abc)<<16)>>16))!=0)&((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)) ) 4 0000 D5 push DE ; 1:11 -10. abc fm/mod 5 0001 E5 push HL ; 1:11 -10. abc fm/mod 6 0002 11 FE FF ld DE, +((-10%(((abc)<<16)>>16))!=0)&(((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(-10%(((abc)<<16)>>16))); 3:10 -10. abc fm/mod 7 0005 21 02 00 ld HL, +-10/(((abc)<<16)>>16)-(((-10%(((abc)<<16)>>16))!=0)&((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)); 3:10 -10. abc fm/mod 8 0008 ;[ 8:42] 9 0008 # file closed: smaz.asm Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 4 __ASM({define({__LINKER},sjasmplus)}) PUSHDOT(-10) PUSH(abc) FMDIVMOD' > smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 9 lines, work time: 0.001 seconds # file opened: smaz.asm 1 0000 abc EQU 4 2 0000 3 0000 ;[8:42] -10. abc fm/mod ( -- +((-10%(((abc)<<16)>>16))!=0)&(((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(-10%(((abc)<<16)>>16))) +-10/(((abc)<<16)>>16)-(((-10%(((abc)<<16)>>16))!=0)&((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)) ) 4 0000 D5 push DE ; 1:11 -10. abc fm/mod 5 0001 E5 push HL ; 1:11 -10. abc fm/mod 6 0002 11 02 00 ld DE, +((-10%(((abc)<<16)>>16))!=0)&(((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(-10%(((abc)<<16)>>16))); 3:10 -10. abc fm/mod 7 0005 21 FD FF ld HL, +-10/(((abc)<<16)>>16)-(((-10%(((abc)<<16)>>16))!=0)&((((-10%(((abc)<<16)>>16))^(abc))>>15)&1)); 3:10 -10. abc fm/mod 8 0008 ;[ 8:42] 9 0008 # file closed: smaz.asm Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU -4 __ASM({define({__LINKER},sjasmplus)}) PUSHDOT(10) PUSH(abc) FMDIVMOD' > smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 9 lines, work time: 0.001 seconds # file opened: smaz.asm 1 0000 abc EQU -4 2 0000 3 0000 ;[8:42] 10. abc fm/mod ( -- +((10%(((abc)<<16)>>16))!=0)&(((((10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(10%(((abc)<<16)>>16))) +10/(((abc)<<16)>>16)-(((10%(((abc)<<16)>>16))!=0)&((((10%(((abc)<<16)>>16))^(abc))>>15)&1)) ) 4 0000 D5 push DE ; 1:11 10. abc fm/mod 5 0001 E5 push HL ; 1:11 10. abc fm/mod 6 0002 11 FE FF ld DE, +((10%(((abc)<<16)>>16))!=0)&(((((10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(10%(((abc)<<16)>>16))); 3:10 10. abc fm/mod 7 0005 21 FD FF ld HL, +10/(((abc)<<16)>>16)-(((10%(((abc)<<16)>>16))!=0)&((((10%(((abc)<<16)>>16))^(abc))>>15)&1)); 3:10 10. abc fm/mod 8 0008 ;[ 8:42] 9 0008 # file closed: smaz.asm Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 4 __ASM({define({__LINKER},sjasmplus)}) PUSHDOT(10) PUSH(abc) FMDIVMOD' > smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 9 lines, work time: 0.001 seconds # file opened: smaz.asm 1 0000 abc EQU 4 2 0000 3 0000 ;[8:42] 10. abc fm/mod ( -- +((10%(((abc)<<16)>>16))!=0)&(((((10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(10%(((abc)<<16)>>16))) +10/(((abc)<<16)>>16)-(((10%(((abc)<<16)>>16))!=0)&((((10%(((abc)<<16)>>16))^(abc))>>15)&1)) ) 4 0000 D5 push DE ; 1:11 10. abc fm/mod 5 0001 E5 push HL ; 1:11 10. abc fm/mod 6 0002 11 02 00 ld DE, +((10%(((abc)<<16)>>16))!=0)&(((((10%(((abc)<<16)>>16))^(abc))>>15)&1)*(((abc)<<16)>>16)+(10%(((abc)<<16)>>16))); 3:10 10. abc fm/mod 7 0005 21 02 00 ld HL, +10/(((abc)<<16)>>16)-(((10%(((abc)<<16)>>16))!=0)&((((10%(((abc)<<16)>>16))^(abc))>>15)&1)); 3:10 10. abc fm/mod 8 0008 ;[ 8:42] 9 0008 # file closed: smaz.asm dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ Docela me prekvapilo co mi generoval prekladac, protoze mam spravny vysledek, ktery bude mit ale jiny binarni kod[. Viz 10 4 varianta Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh '__ASM({define({__LINKER},sjasmplus)}) PUSHDOT(10) PUSH(4) FMDIVMOD' > smaz.asm && sjasmplus smaz.asm --lst=smaz.lst && cat smaz.lst SjASMPlus Z80 Cross-Assembler v1.20.1 (https://github.com/z00m128/sjasmplus) Pass 1 complete (0 errors) Pass 2 complete (0 errors) Pass 3 complete Errors: 0, warnings: 0, compiled: 10 lines, work time: 0.001 seconds # file opened: smaz.asm 1 0000 2 0000 3 0000 ;[7:40] 10. 4 fm/mod ( -- 2 2 ) 4 0000 D5 push DE ; 1:11 10. 4 fm/mod 5 0001 E5 push HL ; 1:11 10. 4 fm/mod 6 0002 11 02 00 ld DE, 0x0002 ; 3:10 10. 4 fm/mod 7 0005 6B ld L, E ; 1:4 10. 4 fm/mod L = E = 0x02 8 0006 62 ld H, D ; 1:4 10. 4 fm/mod H = D = 0x00 9 0007 ;[ 7:40] 10 0007 # file closed: smaz.asm Tohle me hazi vidle do meho napadu jak resit testy pro ruzne linkery. A aby to bylo jeste horsi tak mi presne stejny kod generoval i kdyz misto 0x0002 date nejaky retezec, vzorec co bude shodny s tim co poleze do HL, klidne i ukazatel. Protoze pochopi, ze kdyz je to do pismenka stejne tak ta hodnota bude taky stejna. PS: Tim by mel umet sjasmplus vse co spocita M4 v tokenech. Pasmo selze v fm/mod, sm/rem a um/mod a popravde me nenapada zadny zpusob jak to vyresit s 16 bitovym celociselnym delenim bez podpory carry. Protoze je to 32bit/16bit=16bit. Mozna to ani nejde. |
Autor: | _dworkin [ 20.09.2022, 17:18 ] |
Předmět příspěvku: | Re: Macro FORTH |
Musim bezet do prace, tak jen v rychlosti. 32bit/16bit s 16bity bez carry a bez promennych jen pomoci vzorce asi fakt nejde. Ale... zkousel jsem... tohle asi rozepisi pozdeji. Ted jen ukazky 32bit/12bit. V podstate je to 28bit/12bit protoze FORTH bere pripad kdy se vysledek nevleze to 16bit jako nedefinovane chovani. Teoreticky by melo jit 32bit/15bit. Ale me roste velikost vzorce asi exponencialne. A uz ted je to silene dlouhe pro 4 cleny. /14bit by to melo 8 clenu /15bit by to melo 16 clenu Pokud neexistuje nejaky trik s ?: co by to linearizoval. Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0x333 PUSHDOT(0x123456) PUSH(abc) UMDIVMOD __SHOW_TOKEN(1)' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(um/mod,0x0012,0x3456,abc) IS_NUM __TEMP_A: 1 >(0x0012)< IS_NUM __TEMP_B: 1 >(0x3456)< IS_NUM __TEMP_C: 0 > (abc)< __LINKER:>__LINKER< __eval_op_num_xxx_pasmo({um%},{0x3456},{abc},{0x0012}) __eval_op_num_xxx_pasmo({um/},{0x3456},{abc},{0x0012}) abc EQU 0333 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:114602 LD DE, 0246 0005:21B005 LD HL, 05B0 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0x333 PUSHDOT(0x423456) PUSH(abc) UMDIVMOD __SHOW_TOKEN(1)' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(um/mod,0x0042,0x3456,abc) IS_NUM __TEMP_A: 1 >(0x0042)< IS_NUM __TEMP_B: 1 >(0x3456)< IS_NUM __TEMP_C: 0 > (abc)< __LINKER:>__LINKER< __eval_op_num_xxx_pasmo({um%},{0x3456},{abc},{0x0042}) __eval_op_num_xxx_pasmo({um/},{0x3456},{abc},{0x0042}) abc EQU 0333 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:111302 LD DE, 0213 0005:21B114 LD HL, 14B1 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0x876 PUSHDOT(0x423456) PUSH(abc) UMDIVMOD __SHOW_TOKEN(1)' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(um/mod,0x0042,0x3456,abc) IS_NUM __TEMP_A: 1 >(0x0042)< IS_NUM __TEMP_B: 1 >(0x3456)< IS_NUM __TEMP_C: 0 > (abc)< __LINKER:>__LINKER< __eval_op_num_xxx_pasmo({um%},{0x3456},{abc},{0x0042}) __eval_op_num_xxx_pasmo({um/},{0x3456},{abc},{0x0042}) abc EQU 0876 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:111401 LD DE, 0114 0005:21D307 LD HL, 07D3 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ ../check_word.sh 'abc EQU 0x876 PUSHDOT(0x5423456) PUSH(abc) UMDIVMOD __SHOW_TOKEN(1)' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(um/mod,0x0542,0x3456,abc) IS_NUM __TEMP_A: 1 >(0x0542)< IS_NUM __TEMP_B: 1 >(0x3456)< IS_NUM __TEMP_C: 0 > (abc)< __LINKER:>__LINKER< __eval_op_num_xxx_pasmo({um%},{0x3456},{abc},{0x0542}) __eval_op_num_xxx_pasmo({um/},{0x3456},{abc},{0x0542}) abc EQU 0876 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11E405 LD DE, 05E4 0005:211B9F LD HL, 9F1B Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ Posledni soubor smaz.asm vypada takto: Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Pasmo_test$ cat -n smaz.asm 1 abc EQU 0x876 2 ; name: __TOKEN_PUSH2 3 ; info: 0x5423456. abc um/mod 4 ;param: (+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398)) mod (abc),+(1346 mod (abc)*16+13398>>12)/(abc)<<12+((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8))/(abc)<<8+(((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4))/(abc)<<4+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398))/(abc)) 5 ;array1: >+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398)) mod (abc)< 6 ;array2: >+(1346 mod (abc)*16+13398>>12)/(abc)<<12+((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8))/(abc)<<8+(((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4))/(abc)<<4+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398))/(abc)< 7 ;array3: >< 8 ;array: +((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398)) mod (abc),+(1346 mod (abc)*16+13398>>12)/(abc)<<12+((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8))/(abc)<<8+(((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4))/(abc)<<4+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398))/(abc) 9 ;[8:42] 0x5423456. abc um/mod ( -- +((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398)) mod (abc) +(1346 mod (abc)*16+13398>>12)/(abc)<<12+((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8))/(abc)<<8+(((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4))/(abc)<<4+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398))/(abc) ) 10 push DE ; 1:11 0x5423456. abc um/mod 11 push HL ; 1:11 0x5423456. abc um/mod 12 ld DE, +((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398)) mod (abc); 3:10 0x5423456. abc um/mod 13 ld HL, +(1346 mod (abc)*16+13398>>12)/(abc)<<12+((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8))/(abc)<<8+(((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4))/(abc)<<4+((((1346 mod (abc)*16+13398>>12) mod (abc)*16+(15& 13398>>8)) mod (abc)*16+(15& 13398>>4)) mod (abc)*16+(15& 13398))/(abc); 3:10 0x5423456. abc um/mod 14 ;[ 8:42] PS: Pasmu vadi kdyz neni ZA "&" mezera. Zvlastni. Pise to pak ze je cislo mimo rozsah. |
Autor: | _dworkin [ 21.09.2022, 22:14 ] |
Předmět příspěvku: | Re: Macro FORTH |
Jak jsem slibil ze rozepisu me reseni tak tady je. Zkousel jsem ruzne napady a vsechny vedly do slepe ulicky. Ale pro pochopeni jsou nektere napady uzitecne. Zacal jsem naivne, ze se pokusim rozdelit 16bit=32bit/16bit na dva 16bit/16bit (% je operator pro zbytek po deleni(mod)) Kód: x_hi * 65536 + x_lo x_hi ( x_hi % y ) * 65536 + x_lo div = ------------------- = ------ * 65536 + ----------------------------- y y y Tady jsem si uvedomil ze prvni clen vzdy pretece, takze neresit. Co je horsi on pretece i ten zbytek po deleni ( x_hi % y ) * 65536 Takze reseni by mohlo byt to jeste vic rozdelit, abych pracoval vzdy v 16 bitech. Treba na bajty. Takze 4x 16bit/16bit. Ale nejvyssi dva se daji spojit do jednoho, tak je to jen 3x. (Protoze prvni by byl 00??/y a druhy je ((zbytek po prvnim)*256+??)/y a to uz to rovnu mohu udelat jako x_hi/y. Kód: 0x123456 0x12 ( 0x12 % 0x333) * 256 + 0x34 ((( 0x12 % 0x333) * 256 + 0x34 ) % 0x333) * 256 + 0x56 -------- = -------- * 65536 + ----------------------------- * 256 + --------------------------------------------------------- 0x333 0x333 0x333 0x333 0x1234 0x235 * 256 + 0x56 = 0 + ------- * 256 + -------------------- = 0x333 0x333 = 0 + 0x05 * 256 + 0xB0 = 0x05B0 To by mohlo fungovat, ale zase me to preteka u 0x235*256 = 0x23500. Ke vsemu me doslo ze to bude fungovat jen diky tomu ze delitel ma nejvyssi 4 bity nulove. Takze je zaruceno, ze zbytek po deleni bude mit taky horni bity nulove a nepretece me to. Reseni by melo byt to rozdelit na 8 souctu 16bit/16bit. Pricem se to musi delit 12 bitem takze pokud nejvyssi 4 bity x_hi nejsou nula tak to stejne pretece a pokud jsou nula tak mohu jedno deleni ignorovat a prvni 4 spojit do jednoho x_hi/y. Takze to jsou ctyri deleni 16bit/16bit. Kód: 0x123456/0x333 = 0x0012/0x333 --> 0x0 0x0012 (0x0120 + 0x03)/0x333 --> 0x0 0x0123 (0x1230 + 0x04)/0x333 --> 0x5 0x0235 (0x2350 + 0x05)/0x333 --> 0xB 0x0024 (0x0240 + 0x06)/0x333 --> 0x0 0x0246 = 0x05B0 0x0246 x/y= (x_hi%y*16+x_lo>>12)/y<<12+ ((x_hi%y*16+x_lo>>12)%y*16+(15& x_lo>>8))/y<<8+ (((x_hi%y*16+x_lo>>12)%y*16+(15& x_lo>>8))%y*16+(15& x_lo>>4))/y<<4+ ((((x_hi%y*16+x_lo>>12)%y*16+(15& x_lo>>8))%y*16+(15& x_lo>>4))%y*16+(15& x_lo))/y x%y= ((((x_hi%y*16+x_lo>>12)%y*16+(15& x_lo>>8))%y*16+(15& x_lo>>4))%y*16+(15& x_lo))%y Tohle jsou zakladni vzorce pro beznamenkove 28bit/12bit. Hmm.. & vyhodnocuje Pasmo pozdeji nez scitani, ale kdybych napsal misto +(15& x_lo>>8) tohle +x_lo<<4>>12 tak usetrim zavorky, asi... 0x0123 4567 / Y Prvni radek u deleni vydeli 0x1234/Y a vynasobi to pres bitovy posun <<12 Druhy zopakuje prvni ale nedeli to ale ziskava zbytek a ten posune o 4 bity, protoze dalsi 4 bity nacte, nakonec to zase vydeli / Treti zopkauje druhy, ale ... Snazil jsem se dal, treba pomoci tohoto vzorce nastavit nejvyssi bity na nula u delitele s tim ze zeslozitim vypocet. Kód: (c+d)*(c-d)=cc-cd+dc-dd=cc-dd A+B c-d (A+B)*(c-d) --- * --- = ----------- c+d c-d cc-dd Ale to se jen zhorsuje, protoze c*c je pak mnohem vetsi jak 16 bit. Takze co kdybych to otocil a chapal y jako = cc-dd. To teoreticky muze fungovat Kód: 0xAD40=44352=211*211-13*13=0xD3**2-0x0B**2 c+d=211+13=224=0xE0 c-d=211-13=198=0xC6 X X / 0xC6 ------ = --------- = X / (0xC6 * 0xE0) = X / 0xAD40 0xAD40 0xE0 Ale podstatnejsi je, ze se pres tohle dostanete k reseni, ktere ale neni presne X/Y = (X/hi8(Y))>>8 pokud si ohlidate ze nedelite nulou. Nepresne reseni ale nepotrebuji. PS: Na netu nedokazi k tomuto tematu nic sehnat. Ale taky nevim jak spravne napsat anglicky klicove slova. Vetsina co naleznu je jak rucne delit (long division), nebo algoritmus deleni pro nejaky procesor co to neumi, ten taky nepotrebuji. https://groups.google.com/g/comp.theory/c/UULm1qzMqi8 Tady nekdo navrhuje pouzit rutinu 64bit/16bit ze to prepsat na 32bit/16bit bude hracka. Ale nejak opomel ze ta rutina pouziva vnitrne 32bit/32bit Takze hracka by to s pouzitim 16bit/16bit bylo prepsat na 32bit/8bit Protoze vzdy je problem ze ten delitel musi byt kratsi, a o kolik bitu je to kratsi o tolik bitu se to da postupne posuvat. PPS: Jak jsem psal ze reseni mozna neexistuje tak vlastne teoreticky existuje vzdy, protoze se to da rozespat do tabulky 32bit*16bit a pres tuhle obri tabulku dat vysledek. To by melo narazit na limit delky radku v Pasmu nebo tak neco. Ale ten algoritmus deleni by mel jit rozepsat i jako vzorec a to ze nemam carry se da testovat nejakym vetvenim bud pomoci nasobeni nulou nebo 1, pripadne pres test ?: vzdy pred bitovym posunem a podle toho vetvit reseni. To by bylo ale fakt dlouhe, ale do toho limitu proveditelne. PPPS: Hmmm.. jeste jsem nepremyslel nad tim prvnim vzorcem, ze ja delim x_hi. Lepe receno (x_hi * 65536 + x_lo) / y = 65536*(x_hi/y) + ((x_hi%x_lo)*65536 + x_lo)/y Ale plati i = x_hi*(65536/y) + ((65536%y)*x_hi + x_lo)/y To bych mel jistotu ze vzdy vydelim. 0x123456 / 0x333 = 0x12*0x50 + ((0x10)*0x12 + 0x3456)/0x333 = 0x05A0 + (0x0120 + 0x3456)/0x333 = 0x05A0 + 0x3576/0x333 = 0x05A0 + 0x10 = 0x05B0 0x12345678 / 0x8888 = 1*0x1234 + (0x7778*0x1234 + 0x5678)/0x8888 = 0x1234 + (0x087EB460 + 0x5678)/0x8888 = 0x1234 + 0x087F0AD8/0x8888 =0x1234 + 0x0FEE = 0x2222 Ok takze pretikam, jinak vyleze spatny vysledek a za druhe nevim jak vydelit 0x10000/Y u Pasma, protoze je to vic ja 16bitu. |
Autor: | _dworkin [ 22.09.2022, 05:01 ] |
Předmět příspěvku: | Re: Macro FORTH |
Opravil jsem chybu v kodu pro Pasmo pri pocitani MOD kde jsem mel jen kod z UMOD. Pridal jsem podporu v Pasmu pro SMDIVREM a FMDIVMOD, ale oboje pouze pro 16bit/16bit, protoze uz i tak je to slozite, protoze pasmo umi jen unsigned nasobeni, deleni a mod. Napriklad nefunguje (nejaky_vypocet_co_je_nakonec_nula_nebo_jedna...>>15)*(-1)*... pro otoceni znamenka. Otocit znamenko proste musi byt natvrdo v kodu a jeste ohlidane ze nebude brano jako unarni. Takze tohle jen zduplikovanim kodu za ? : 16bit/16bit je mysleno tak, ze to sebere vstup jako pro 32bit/16bit, ale hornich 16 bitu MUSI byt 0x0000 a nebo 0xFFFF. U UMDIVMOD, SMDIVREM a FMDIVMOD se generuje varovani, ze Pasmo umi jen 16bit a ten kod nekontroluje rozsah. Vypisuje to ale jen na stderr, protoze je to ve funkci a co se pise na stdout je vystup funkce. Takze pri presmerovani do souboru to ve vyslednem souboru nebude. PS: Rano jdu do prace a treti noc jsem poradne nespal a mam celodenni a pak uz je zase narocny vikend, takze si dam pauzu. |
Autor: | Busy [ 22.09.2022, 10:37 ] |
Předmět příspěvku: | Re: Macro FORTH |
_dworkin píše: Vypisuje to ale jen na stderr, protoze je to ve funkci a co se pise na stdout je vystup funkce. Takze pri presmerovani do souboru to ve vyslednem souboru nebude. Ved presmeruj do suboru aj strerr
|
Autor: | _dworkin [ 24.09.2022, 04:44 ] |
Předmět příspěvku: | Re: Macro FORTH |
Podarilo se mi rozsirit u Pasma sm/rem z 16bit/16bit na 28bit/12bit! Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Automatic$ ../check_word.sh 'abc equ 0x789 PUSHDOT(0x1234567) PUSH(abc) SMDIVREM' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(sm/rem,0x0123,0x4567,abc) IS_NUM __TEMP_A: 1 >(0x0123)< IS_NUM __TEMP_B: 1 >(0x4567)< IS_NUM __TEMP_C: 0 > (abc)< __LINKER:>__LINKER< __eval_op_num_xxx_pasmo({sm%},{0x4567},{abc},{0x0123}) __eval_op_num_xxx_pasmo({sm/},{0x4567},{abc},{0x0123}) .warning: Pasmo does not support 32 bit numbers and M4 does not know all values(They can only emulate 16bit/16bit without checking the range): "0x0123<<16+0x4567 abc sm/rem" abc EQU 0789 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:110805 LD DE, 0508 0005:21A726 LD HL, 26A7 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Automatic$ ../check_word.sh 'abc equ 0x789 PUSHDOT(-0x1234567) PUSH(abc) SMDIVREM' > smaz.asm && pasmo -d smaz.asm smaz.bin __EVAL_S16(sm/rem,0xFEDC,0xBA99,abc) IS_NUM __TEMP_A: 1 >(0xFEDC)< IS_NUM __TEMP_B: 1 >(0xBA99)< IS_NUM __TEMP_C: 0 > (abc)< __LINKER:>__LINKER< __eval_op_num_xxx_pasmo({sm%},{0xBA99},{abc},{0xFEDC}) __eval_op_num_xxx_pasmo({sm/},{0xBA99},{abc},{0xFEDC}) .warning: Pasmo does not support 32 bit numbers and M4 does not know all values(They can only emulate 16bit/16bit without checking the range): "0xFEDC<<16+0xBA99 abc sm/rem" abc EQU 0789 0000:D5 PUSH DE 0001:E5 PUSH HL 0002:11F8FA LD DE, FAF8 0005:2159D9 LD HL, D959 Emiting raw binary from 0000 to 0007 dworkin@dw-A15:~/Programovani/ZX/Forth/Automatic$ Vyzadalo si to hodne premysleni. Prvne jsem musel vyresit jak udelat obycejne ABS u 32bitove hodnoty, pokud mate jen 16 bitovou aritmetiku bez carry a jinych priznaku. Zni to jednoduse, ale musite si uvedomit, ze vysledek horniho slova je zavisly i na spodnim slovu a naopak. Nakonec jsem prisel na reseni, kdy mam 2 funkce/makra podle toho zda chci vratit ve vysledku horni nebo spodni slovo v absolutni hodnote. ABS_HI(HI,LO) = (HI>>15?~(HI+(LO=0)):HI) kde (LO=0) je 0 pokud je spodni slovo nenulove, jinak je -1, takze i kdyz je pred tim plus tak se odcita 0 nebo 1. Jedna se o postup kdy prevratime vsechny bity vstupu pokud ma sign nastaveny na jedna a pokud byl spodni dvoubajt nula, tak jeste odectu od horniho dvoubajtu jednicku (protoze jsme dole pretekli). ABS_LO(HI,LO) = (HI>>15?-LO:LO) tady me chvilku unikalo, ze znamenko je ulozene v hornim slove a resil jsem to pres __16BIT_TO_ABS. Horsi problem byl, ze i kdyz pouziji tyhle makra na muj vzorec pro um/mod, tak potrebuji jeste nastavit spravne znamenka pro vysledky. Napriklad to deleni ma byt zaporne, kdyz delitel a delenec maji rozdilne znamenka. A i kdyz pasmo ma ? operator tak ten me nepomuze protoze ho musim obalit do zavorek, takze tim unarni minusko neudelam. Mohl bych vygenerovat -1, ale Pasmo nasobi jen unsigned, takze misto otoceni znamenka vysledku bych udelal jen 0xFFFF*X. Takze me zbyva mit vzorec 2x delsi jen kvuli jedinemu minusku? Ne! Kdyz to nemohu nasobit -1, tak to stale mohu "ze zavorky" xorovat! ((U_A/U_B) xor (0xFFFF)) + 1 ((U_A/U_B) xor (0x0000)) + 0 0xFFFF nebo 0x0000 se udela uz snadno pres (((A xor B)>>15)*0xFFFF) a 1 nebo 0 se udela obdobne ((A xor B)>>15) U mod casti je to jen zavisle na A, takze tam ani neni "A xor B" ale jen "A". PS: Ty funkce jsem musel trosku vice testovat, protoze jsem to napsal dost neprehledne, snazil jsem se zjistovat zda zname nejaky vstup a podle toho nektere casti uz predpocita pomoci M4. A to se resi proste jinak, misto -1 u logickeho porovnani to dela 1, ma to jiny poradi vyhodnoceni atd. Ani ty makra radsi nebudu ukazovat... .) Jen test pro: __ABS20BIT_SHR_4 ...tohle melo byt pouzito pro pripad ze hornich 12 bitu je 0 nebo -1, v podstate to dela ABS(0x54321)>>4 = 0x5432 __ABS32BIT_SHR16 __ABS32BIT_AND_0xFFFF ...tohle je zaiimave tim, ze je to jediny nazev makra s malym pismenem (x). Kód: dworkin@dw-A15:~/Programovani/ZX/Forth/Automatic$ ./abs32_28_24_20.sh 1 2 ORG 0x8000 3 4 5 ;---- 0xFFFABCE0 --> 0x54320 --> 0x5432 6 hi1 equ 0xFFFA 7 lo1 equ 0xBCE0 8 9 ld bc,+((hi1)>>15?~((hi1)<<12+(lo1)>>4+((15& (lo1))=0)):(hi1)<<12+(lo1)>>4) 10 ld bc,+((hi1)>>15?~((hi1)<<12+3022-1):(hi1)<<12+3022) 11 ld bc,+(~(0xA000+(lo1)>>4+((15& (lo1))=0))) 12 ld bc,+21554 13 14 ;---- 0xFFFABCE0 --> 0x00054320 15 16 ld de,+((hi1)>>15?~((hi1)+((lo1)=0)):hi1) 17 ld de,+((hi1)>>15?~(hi1):hi1) 18 ld de,+(5-((lo1)=0)) 19 ld de,+5 20 21 ld hl,+((hi1)>>15?-(lo1):lo1) 22 ld hl,+((hi1)>>15? 17184:48352) 23 ld hl,+(-(lo1)) 24 ld hl,+17184 25 26 hi2 equ -6 27 lo2 equ -17184 28 29 ld bc,+((hi2)>>15?~((hi2)<<12+(lo2)>>4+((15& (lo2))=0)):(hi2)<<12+(lo2)>>4) 30 ld bc,+((hi2)>>15?~((hi2)<<12+3022-1):(hi2)<<12+3022) 31 ld bc,+(~(0xA000+(lo2)>>4+((15& (lo2))=0))) 32 ld bc,+21554 33 34 ld de,+((hi2)>>15?~((hi2)+((lo2)=0)):hi2) 35 ld de,+((hi2)>>15?~(hi2):hi2) 36 ld de,+(5-((lo2)=0)) 37 ld de,+5 38 39 ld hl,+((hi2)>>15?-(lo2):lo2) 40 ld hl,+((hi2)>>15? 17184:48352) 41 ld hl,+(-(lo2)) 42 ld hl,+17184 43 44 45 ;---- 0xFFFABCE1 --> 0x5431F --> 0x5431 46 47 hi3 equ 0xFFFA 48 lo3 equ 0xBCE1 49 50 ld bc,+((hi3)>>15?~((hi3)<<12+(lo3)>>4+((15& (lo3))=0)):(hi3)<<12+(lo3)>>4) 51 ld bc,+((hi3)>>15?~((hi3)<<12+3022):(hi3)<<12+3022) 52 ld bc,+(~(0xA000+(lo3)>>4+((15& (lo3))=0))) 53 ld bc,+21553 54 55 ld de,+((hi3)>>15?~((hi3)+((lo3)=0)):hi3) 56 ld de,+((hi3)>>15?~(hi3):hi3) 57 ld de,+(5-((lo3)=0)) 58 ld de,+5 59 60 ld hl,+((hi3)>>15?-(lo3):lo3) 61 ld hl,+((hi3)>>15? 17183:48353) 62 ld hl,+(-(lo3)) 63 ld hl,+17183 64 65 ;---- 0x54310 --> 0x5431 66 67 hi4 equ 0x5 68 lo4 equ 0x4310 69 70 ld bc,+((hi4)>>15?~((hi4)<<12+(lo4)>>4+((15& (lo4))=0)):(hi4)<<12+(lo4)>>4) 71 ld bc,+((hi4)>>15?~((hi4)<<12+1073-1):(hi4)<<12+1073) 72 ld bc,+(0x5000+(lo4)>>4) 73 ld bc,+21553 74 75 ld de,+((hi4)>>15?~((hi4)+((lo4)=0)):hi4) 76 ld de,+((hi4)>>15?~(hi4):hi4) 77 ld de,+5 78 ld de,+5 79 80 ld hl,+((hi4)>>15?-(lo4):lo4) 81 ld hl,+((hi4)>>15? 48368:17168) 82 ld hl,+lo4 83 ld hl,+17168 84 85 ;========================================= ORG 8000 hi1 EQU FFFA lo1 EQU BCE0 8000:013254 LD BC, 5432 8003:013254 LD BC, 5432 8006:013254 LD BC, 5432 8009:013254 LD BC, 5432 800C:110500 LD DE, 0005 800F:110500 LD DE, 0005 8012:110500 LD DE, 0005 8015:110500 LD DE, 0005 8018:212043 LD HL, 4320 801B:212043 LD HL, 4320 801E:212043 LD HL, 4320 8021:212043 LD HL, 4320 hi2 EQU FFFA lo2 EQU BCE0 8024:013254 LD BC, 5432 8027:013254 LD BC, 5432 802A:013254 LD BC, 5432 802D:013254 LD BC, 5432 8030:110500 LD DE, 0005 8033:110500 LD DE, 0005 8036:110500 LD DE, 0005 8039:110500 LD DE, 0005 803C:212043 LD HL, 4320 803F:212043 LD HL, 4320 8042:212043 LD HL, 4320 8045:212043 LD HL, 4320 hi3 EQU FFFA lo3 EQU BCE1 8048:013154 LD BC, 5431 804B:013154 LD BC, 5431 804E:013154 LD BC, 5431 8051:013154 LD BC, 5431 8054:110500 LD DE, 0005 8057:110500 LD DE, 0005 805A:110500 LD DE, 0005 805D:110500 LD DE, 0005 8060:211F43 LD HL, 431F 8063:211F43 LD HL, 431F 8066:211F43 LD HL, 431F 8069:211F43 LD HL, 431F hi4 EQU 0005 lo4 EQU 4310 806C:013154 LD BC, 5431 806F:013154 LD BC, 5431 8072:013154 LD BC, 5431 8075:013154 LD BC, 5431 8078:110500 LD DE, 0005 807B:110500 LD DE, 0005 807E:110500 LD DE, 0005 8081:110500 LD DE, 0005 8084:211043 LD HL, 4310 8087:211043 LD HL, 4310 808A:211043 LD HL, 4310 808D:211043 LD HL, 4310 Emiting raw binary from 8000 to 808F dworkin@dw-A15:~/Programovani/ZX/Forth/Automatic$ Jsou tu videt ruzne variace, vzdy 4x jakoby to same pro ;---- 0xFFFABCE0 --> 0x54320 --> 0x5432 hi1 equ 0xFFFA lo1 equ 0xBCE0 ld bc,+__ABS20BIT_SHR_4(hi1,lo1) ld bc,+__ABS20BIT_SHR_4(hi1,0xBCE0) ld bc,+__ABS20BIT_SHR_4(0xFFFA,lo1) ld bc,+__ABS20BIT_SHR_4(0xFFFA,0xBCE0) ;---- 0xFFFABCE0 --> 0x00054320 ld de,+__ABS32BIT_SHR_16(hi1,lo1) ld de,+__ABS32BIT_SHR_16(hi1,0xBCE0) ld de,+__ABS32BIT_SHR_16(0xFFFA,lo1) ld de,+__ABS32BIT_SHR_16(0xFFFA,0xBCE0) ld hl,+__ABS32BIT_AND_0xFFFF(hi1,lo1) ld hl,+__ABS32BIT_AND_0xFFFF(hi1,0xBCE0) ld hl,+__ABS32BIT_AND_0xFFFF(0xFFFA,lo1) ld hl,+__ABS32BIT_AND_0xFFFF(0xFFFA,0xBCE0) hi2 equ -6 lo2 equ -17184 atd. |
Autor: | _dworkin [ 26.09.2022, 04:39 ] |
Předmět příspěvku: | Re: Macro FORTH |
Snazil jsem se hledat na netu nejake rady pro deleni a modulo a nic uzitecneho jsem v podstate nenasel. Pouzitelne byly jen tyto dva vzorce. Kód: (a+b)%n = (a%n + b%n) % n (a*b)%n = (a%n * b%n) % n z nich se da odvodit Kód: hilo mod n ≡ ((hi mod n)*65536 + (lo mod n)) mod n To nasobeni 65536 se musi nejak odstranit, protoze mame limit maximalne 16 bitu na cislo. Kód: +((((((hi mod n)*16 mod n)*16 mod n)*16 mod n)*16 mod n)+(lo mod n))mod n = +((((((((((hi mod n)*4 mod n)*4 mod n)*4 mod n)*4 mod n)*4 mod n)*4 mod n)*4 mod n)*4 mod n)+(lo mod n))mod n = +((((((((((((((((((hi mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)*2 mod n)+(lo mod n))mod n Ten prvni radek se da pouzit kdyz je "n" 12 bitove. Druhy radek kdyz je "n" az 14 bitove a posledni pro 15 bitove "n". Tady me zajimal prvni radek, protoze je to v podstate to co jsem delal. V tomhle bode jsem musel jit do prace a v hlave me vrtalo ze to dela ctyrykrat (prvni "hi mod n" by ani nemusel, protoze jinak pretece v deleni, u modula je dulezite jen ze delitel je 12 bitovy, takhle to aspon pocita korektne) Kód: +((((((hi mod n) a pak k tomu pricte zase zbytek z nizsich 16 bitu cisla*16 mod n) *16 mod n) *16 mod n) *16 mod n) Kód: +(lo mod n) a ze souctu zase udela zbytek Kód: )mod n No a ja tolikrat mod nepouzival. Tak uz jsem se bal, ze jsem nejak neosetril preteceni a uz premyslel jake spravne cislo zvolit aby to preteklo. Ale pak jsem si postupne z hlavy vybavil, ze ten postup mam trosku jinak. Ja tech nizsich 16 bitu pricitam postupne. Pomoci modula si vycistim nejvyssi 4 bity, vysledek posunu doleva o ty 4 bity (*16 nebo <<4) a k tomu prictu 4 bity z nizsiho slova. Takze me nikdy nic nepretece, dole jsou same nuly, klidne bych misto + mohl pouzivat XOR nebo OR, mit spravnou masku. Ale to postupne pricitani ma nejakou rezii (mysleno v delce vzorce, efektivitu neresim, v asm bych intuitivne pouzil presne tuhle metodu). Doma jsem to vyzkousel a mohlo by to vypadat nejak takto: Kód: ld DE, +(((((291 mod (n)<<4)mod (n)<<4)mod (n)<<4)mod (n)<<4)mod (n)+17767 mod (n))mod (n); 3:10 0x01234567. n um/mod ld DE, +((((291 mod (n)<<4+17767>>12)mod (n)<<4+17767<<4>>12)mod (n)<<4+17767<<8>>12)mod (n)<<4+(15& 17767))mod (n); 3:10 0x01234567. n um/mod Nova metoda s dvema moduly navic je kratsi. Ale kdyz znam hodnotu spodnich 16 bitu deleneho cisla, tak to lze zapsat efektivneji. Kód: ld DE, +((((291 mod (n)<<4+4)mod (n)<<4+5)mod (n)<<4+6)mod (n)<<4+7)mod (n); 3:10 0x01234567. n um/mod Takze pouzivam obe metody. |
Stránka 21 z 40 | Všechny časy jsou v UTC + 1 hodina [ Letní čas ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |