OldComp.cz

Komunitní diskuzní fórum pro fanoušky historických počítačů


Právě je 29.03.2024, 00:57

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]




Odeslat nové téma Odpovědět na téma  [ Příspěvků: 585 ]  Přejít na stránku Předchozí  1 ... 18, 19, 20, 21, 22, 23, 24 ... 39  Další
Autor Zpráva
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 18.09.2022, 17:02 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 02:32 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 08:12 
Offline
Profík

Registrován: 26.11.2018, 16:59
Příspěvky: 580
Bydliště: Holešov
Has thanked: 13 times
Been thanked: 90 times
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 ?


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 13:02 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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
    ld    C, A          ; 1:4       M+   d2 = d + CCHL
mozna to priste pochopim snaz.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 14:45 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
_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?

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 16:27 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
__{}__{}$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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 16:49 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 19.09.2022, 19:51 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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$

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 20.09.2022, 01:53 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 20.09.2022, 17:18 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 21.09.2022, 22:14 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 22.09.2022, 05:01 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 22.09.2022, 10:37 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3642
Bydliště: Bratislava
Has thanked: 371 times
Been thanked: 788 times
_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 ;)


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 24.09.2022, 04:44 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
 Předmět příspěvku: Re: Macro FORTH
PříspěvekNapsal: 26.09.2022, 04:39 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1100
Has thanked: 100 times
Been thanked: 157 times
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)
*16 mod n)
*16 mod n)
*16 mod n)
*16 mod n)
a pak k tomu pricte zase zbytek z nizsich 16 bitu cisla
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.

_________________
Z80 Forth compiler (ZX Spectrum 48kb): https://codeberg.org/DW0RKiN/M4_FORTH


Nahoru
 Profil  
 
Zobrazit příspěvky za předchozí:  Seřadit podle  
Odeslat nové téma Odpovědět na téma  [ Příspěvků: 585 ]  Přejít na stránku Předchozí  1 ... 18, 19, 20, 21, 22, 23, 24 ... 39  Další

Všechny časy jsou v UTC + 1 hodina [ Letní čas ]


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 3 návštevníků


Nemůžete zakládat nová témata v tomto fóru
Nemůžete odpovídat v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete přikládat soubory v tomto fóru

Hledat:
Přejít na:  
Založeno na phpBB® Forum Software © phpBB Group
Český překlad – phpBB.cz