OldComp.cz

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


Právě je 10.12.2024, 18:53

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




Odeslat nové téma Odpovědět na téma  [ Příspěvků: 25 ]  Přejít na stránku 1, 2  Další
Autor Zpráva
PříspěvekNapsal: 29.08.2024, 15:37 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1335
Has thanked: 102 times
Been thanked: 195 times
Tohle tema nemam kam poradne zaradit, protoze je to spojeni mezi Z80 a 6502.
Z meho pohledu je to tak, ze relativne znam Z80 a 6502 zbezne dokazu obcas precist co ten kod dela.
Az do ted... kdy jsem narazil na neco co neni na prvni pohled zrejme.

Z logiky algoritmu me doslo ze

CPM se od CP musi lisit v nastaveni carry. Mezi procesory je hodnota carry INVERTOVANA.
V konkretnim algoritmu byla 6502 varianta vyhodnejsi protoze mela 1 kde ve vysledku potrebuji 1.

Jak ale muze 6502 s takovym carry zit?

Pokud vezmu priklad odcitani dvou 16 bitovych hodnot od sebe a provedu to 8 bitove na Z80 to vypada takto...

Mam obe hodnoty z hlediska Z80 nesmyslne v pameti, aby se to dalo lepe porovnat mezi procesory, protoze pro 6502 je to prirozeny stav.

res=num1-num2
Kód:
ld bc,(num2) ; 4:20
ld a,(num1)  ; 3:13
sub c        ; 1:4
ld (res),a   ; 3:13
ld a,(num1+1); 3:13
sbc a,b      ; 1:4
ld (res+1),a ; 3:13
            ;[18:80]

ld bc,(num2) ; 4:20
ld a,(num1)  ; 3:13
sub c        ; 1:4
ld c,a       ; 1:4
ld a,(num1+1); 3:13
sbc a,b      ; 1:4
ld b,a       ; 1:4
ld bc,(res)  ; 4:20
            ;[18:82]

ld hl,(num2) ; 3:16
ld a,(num1)  ; 3:13
sub l        ; 1:4
ld l,a       ; 1:4
ld a,(num1+1); 3:13
sbc a,h      ; 1:4
ld h,a       ; 1:4
ld hl,(res)  ; 3:16
            ;[16:74]

ld hl,num2   ; 3:10 adresa
ld a,(num1)  ; 3:13
sub (hl)     ; 1:7
ld (res),a   ; 3:13
inc hl       ; 1:6  (je mozne mit i 2 takty rychlejsi za dodrzeni jedne podminky)
ld a,(num1+1); 3:13
sbc a,(hl)   ; 1:7
ld (res+1),a ; 3:13
            ;[18:82] nebo 18:80

dodatecna podminka res == num2, tzn num2 = num1-num2
ld hl,num2   ; 3:10 adresa
ld a,(num1)  ; 3:13
sub (hl)     ; 1:7
ld (hl),a    ; 1:7
inc hl       ; 1:6  (je mozne mit i 4 za dodrzeni jedne podminky)
ld a,(num1+1); 3:13
sbc a,(hl)   ; 1:7
ld (hl),a    ; 1:7
            ;[14:70]

ld hl,(num1) ; 3:16
ld bc,(num2) ; 4:20
or a         ; 1:4 pokud nevim ze carry je vynulovane
sbc hl, bc   ; 2:15
ld (res),hl  ; 3:16
            ;[13:71] omlouvam se, nemohl jsem si pomoct zkusit jednu 16 bitovou variantu

Pro Z80 je to chaos, kde neni na prvni pohled patrne jakym smerem se vydat.
Casem si muzete vypestovat urcity cit pro slibne varianty.
To muze byt na programovani pro Z80 desive a nebo zabavne.
Ale zase diky mnoha moznym variantam existuje spousta optimalizaci pokud pro tu variantu splnite nejakou podminku a drobne zmenite zadani napriklad ze ty hodnoty nelezi v pameti nahodne, ale v urcitem poradi...

Jedno to ma spolecne. Carry nastavuje na 1 pokud si musel vypujcit neco z horniho bajtu.

6502
Kód:
sub   sec ; set carry for borrow purpose
lda num1lo
sbc num2lo ; perform subtraction on the LSBs
sta reslo
lda num1hi ; do the same for the MSBs, with carry
sbc num2hi ; set according to the previous result
sta reshi
rts


lda num1lo je "load A from num1lo" == "ld A,(num1lo)"
sta reshi je "store A to reshi" == "ld (reshi),A" == "ld (res+1),A"


Pokud jste si vsimli ze Z80 v 16 bitove variante jsem musel vynulovat carry protoze Z80 neumi SUB HL,BC tak tady to vypada ze 6502 neumi SUB ani v 8 bitove variante.
A jeste misto vynulovni carry ho nastavuje na 1.
Protoze 6502 ma invertovanou hodnotu carry oprotu Z80.
V podstate to znamena, je tam 1? Nemusis nic delat.

A aby to fungovalo tak nastavuje u CMP a SBC 0 pokud si musel vypujcit neco z horniho bajtu a 1 kdyz nemusel.
A zaroven u SBC odcita invertovanou hodnotu carry.

Aby to nebylo tak nesmyslne tak ve skutecnosti provadi SBC to same co ADC jen invertuje odcitanou hodnotu.

NEG = (0xFF xor num)+1 ; ok, dodatecna podminka je ze je to dvojkovy doplnek, tzn -1 = 0xFF
NEG = 0xFF xor (num-1)

A - num = A + NEG(num) = A + (0xFF xor num) + 1

kde tu 1 na konci zamenite za hodnotu carry.
Takze kdyz bude 1 tak se to odecte.
A kdyz bude 0 tak vysledek bude evidentne o 1 nizsi, takze to bude odecteni a jeste -1.


A aby to bylo komplikovanejsi tak to vypada ze

ADC u obou procesoru delaji to same, prictou k A nejakou hodnotu a OBSAH carry. S tim ze stale plati ze carry je interpretovano invertovane. Ale tady fakt pricte 1 pokud bylo carry 1.
A zaroven pokud doslo k preteceni nastaci carry na 1.
V NICEM SE TO NELISI OD Z80.
Takze ta interpretace ze je carry opacne vlastne neplati.
Kód:
clc        ; clear carry
lda num1lo
adc num2lo
sta reslo  ; store sum of LSBs
lda num1hi
adc num2hi ; add the MSBs using carry from
sta reshi  ; the previous calculation

Krome toho ze Z80 umi ADD takze nemusi nulovat na zacatku carry.

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


Nahoru
 Profil  
 
PříspěvekNapsal: 29.08.2024, 16:33 
Offline
Pan Generální
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 2119
Bydliště: Most, Praha
Has thanked: 955 times
Been thanked: 757 times
Mnoho procesorů používá invertovaný carry při borrow, včetně ARM a původních Microchip. Protože je to pro procesor přirozený stav - odčítání realizuje jako sčítání s invertovanou hodnotou.

Když jsem emuloval 6502, tak mě docela příjemně překvapil svou instrukční sadou - je to sice málo instrukcí, ale jsou zajímavé těmi stránkovými módy (jako zero page), výsledně pro malá zařízení může být kód dost rychlý.

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
PříspěvekNapsal: 29.08.2024, 21:16 
Offline
Pan Generální
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 2119
Bydliště: Most, Praha
Has thanked: 955 times
Been thanked: 757 times
Studuji teď RISC-V Hazard3 v RP2350 (Pico 2), a on vůbec ani nemá flagy, jako např. carry. A kupodivu ono se bez toho dá obejít. :-) Když potřebuje vědět výsledek operace, otestuje to až potom. Např. u součtu 64-bit sečte LOW, porovná výsledek aby otestoval přetečení, a podle toho pak inkrementuje součet HIGH.

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
PříspěvekNapsal: 30.08.2024, 15:32 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3861
Bydliště: Bratislava
Has thanked: 377 times
Been thanked: 819 times
Panda38 píše:
RISC-V Hazard3 v RP2350 (Pico 2), a on vůbec ani nemá flagy, jako např. carry
A nielen RISCy, ale aj niektore klasiky: napriklad taky *51 vobec nema zero flag. Ale pritom ma podmieneny skor zero/non-zero :)
Proste, skoci/neskoci podla toho, ci je akumulator prave nulovy alebo nie.
Takze clovek, ktory je zvyknuty skakat podla toho ci vysledok operacie bol nula, nesmie pred tymto skokom naplnit akumulator, lebo v tomto pripade strati informaciu o tom ze vysledok bol nula.

Ale k veci.

_dworkin píše:
... Protoze 6502 ma invertovanou hodnotu carry oprotu Z80. ...
Podla mna to moc komplikujes.
Uplne staci vediet ze 6502 pri odcitani (a teda aj porovnani) proste pouziva carry invertovane. 1 znamena ze nebol prenos a 0 znamena ze bol. Tot vsio :)
Viem ze pre intelakov a zilogakov je to trosku odveci, ale co narobime.
Co ale mne osobne pride od veci este viac, je ze pri scitani sa pouziva carry neinvertovane. Taka mala nekonzistencia, no ;)

Inak ono v 6502 je viacero veci co sa pouzivaju naopak. Napriklad bit pre zakaz/povolenie prerusenia - 0 znamena povolene a 1 zakazane. Teda tiez presne naopak ako pri Inteli / Zilogu.

No a ze kopec uzitocnych instrukcii chyba (scitanie a odcitanie bez carry, inkremet / dekrement akumulatora) si uz urcite zistil.
Ale to nie je nic neobvykle, vela procesorov, aby nemalo prilis vela instrukcii, vobec nema aritmetiku bez carry.

Na tomto mieste uvediem este jednu perlicku, ktorou zvyknem prejst do protiutoku vzdy vtedy, ked mi nejaky 6502 programator vycita, ze Z80 nema zero page.
Vtedy zvyknem odpovedat: Z80 nielenze MA zero page, ale este navyse ma hned dve zero pagy, pricom kazdu z nich si mozem umiestnit do pameti kde len chcem ! :lol:


Nahoru
 Profil  
 
PříspěvekNapsal: 30.08.2024, 21:42 
Offline
Pan Generální
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 2119
Bydliště: Most, Praha
Has thanked: 955 times
Been thanked: 757 times
Proč je invertovaný carry pro procesor přirozený:

Příklad, součet dvou 16-bitů bez vstupního carry, tj. carry = 0:
FFFE + 0003 + 0 = 0001, C je 1

Po bajtech:
FE + 03 + 0 = 01, C = 1
FF + 00 + 1 = 00, C = 1

Příklad, rozdíl dvou 16-bitů bez vstupního borrow, tj. borrow = 0:
0001 - 0003 - 0 = FFFE, B = 1 resp. invertovaný C = 0

Procesor namísto odečtení dělá přičtení invertované hodnoty, včetně inverze carry:
0001 + FFFC + 1 = FFFE, C = 0

Po bajtech:
01 + FC + 1 = FC, C = 0
00 + FF + 0 = FF, C = 0

Z80 i 6502 dělají interně odečtení stejně, převedením na součet pomocí inverze, rozdíl je pouze v tom, že 6502 invertuje carry PŘED operací a Z80 invertuje carry PO operaci (převede carry na borrow).

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 08:58 
Offline
Pan Generální
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 2119
Bydliště: Most, Praha
Has thanked: 955 times
Been thanked: 757 times
Jejda překlep, :shock: mělo být: 01 + FC + 1 = FE, C = 0

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 09:33 
Offline
Pan Generální
Uživatelský avatar

Registrován: 23.03.2014, 20:13
Příspěvky: 2934
Has thanked: 257 times
Been thanked: 641 times
Nad tímhle jsem u TWELVE dost dlouho zpytoval, a nakonec jsem to udělal tak, že před začátkem sčítání/odčítání se Carry musí vždy vynulovat, a pokud došlo k přenosu/výpůjčce, nastaví se na 1. No a ta jednička se při pokračování výpočtu k dalšímu slovu automaticky přičte/odečte. Vlastně jsou tam jenom ADC a SBC.
Takže pokud je po spočtení všech řádů Carry 1, tak se to buď nevešlo nebo překlopilo znaménko. Což jde testovat jednou podmínkou bez ohledu na to, jestli se předtím přičítalo nebo odčítalo.

_________________
Plesnivý sýr z Tesca, zatuchlé kuřecí řízky z Albertu, oslizlé hovězí a myší trus z Lidlu.
Nákup potravinářské inspekce v ČR, říjen 2023.


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 14:11 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1335
Has thanked: 102 times
Been thanked: 195 times
Panda38 píše:
Mnoho procesorů používá invertovaný carry při borrow, včetně ARM a původních Microchip. Protože je to pro procesor přirozený stav - odčítání realizuje jako sčítání s invertovanou hodnotou.

Panda38 píše:
Proč je invertovaný carry pro procesor přirozený:

Příklad, součet dvou 16-bitů bez vstupního carry, tj. carry = 0:
FFFE + 0003 + 0 = 0001, C je 1

Po bajtech:
FE + 03 + 0 = 01, C = 1
FF + 00 + 1 = 00, C = 1

Příklad, rozdíl dvou 16-bitů bez vstupního borrow, tj. borrow = 0:
0001 - 0003 - 0 = FFFE, B = 1 resp. invertovaný C = 0

Procesor namísto odečtení dělá přičtení invertované hodnoty, včetně inverze carry:
0001 + FFFC + 1 = FFFE, C = 0

Po bajtech:
01 + FC + 1 = FC, C = 0
00 + FF + 0 = FF, C = 0

Z80 i 6502 dělají interně odečtení stejně, převedením na součet pomocí inverze, rozdíl je pouze v tom, že 6502 invertuje carry PŘED operací a Z80 invertuje carry PO operaci (převede carry na borrow).


Ja to vlastne uvadim taky
_dworkin píše:
Aby to nebylo tak nesmyslne tak ve skutecnosti provadi SBC to same co ADC jen invertuje odcitanou hodnotu.

NEG = (0xFF xor num)+1 ; ok, dodatecna podminka je ze je to dvojkovy doplnek, tzn -1 = 0xFF
NEG = 0xFF xor (num-1)

A - num = A + NEG(num) = A + (0xFF xor num) + 1

kde tu 1 na konci zamenite za hodnotu carry.
Takze kdyz bude 1 tak se to odecte.
A kdyz bude 0 tak vysledek bude evidentne o 1 nizsi, takze to bude odecteni a jeste -1.

Ale je dobre vedet ze to Z80 ma vnitrne taky tak.

Panda38 píše:
Když jsem emuloval 6502, tak mě docela příjemně překvapil svou instrukční sadou - je to sice málo instrukcí, ale jsou zajímavé těmi stránkovými módy (jako zero page), výsledně pro malá zařízení může být kód dost rychlý.


Ja bych to ani malo instrukci nenazval, jen jinym resenim s mensim mnozstvim vice univerzalnich instrukci.
Ale koukam ze mas pravdu!
Predpokladal jsem ze bude jako u Z80 vyuzity vsech 256 hodnot pro kodovani instrukci... Tam kde bude mit Z80 specializovane tak budou nahrazeny vice vice univerzalnimi 6502. A ono ne. Ma tam mezery... a nebo jinak receno nelegalni instrukce.
https://www.masswerk.at/6502/6502_instruction_set.html
Kód:
HI                                                             LO-NIBBLE
    ‐0       ‐1         ‐2    ‐3   ‐4        ‐5         ‐6        ‐7   ‐8        ‐9        ‐A       ‐B   ‐C       ‐D         ‐E        ‐F
0‐  BRK impl ORA X,ind  ---   ---  ---       ORA zpg    ASL zpg   ---  PHP impl  ORA #     ASL A    ---  ---       ORA abs   ASL abs   ---
1‐  BPL rel  ORA ind,Y  ---   ---  ---       ORA zpg,X  ASL zpg,X ---  CLC impl  ORA abs,Y ---      ---  ---       ORA abs,X ASL abs,X ---
2‐  JSR abs  AND X,ind  ---   ---  BIT zpg   AND zpg    ROL zpg   ---  PLP impl  AND #     ROL A    ---  BIT abs   AND abs   ROL abs   ---
3‐  BMI rel  AND ind,Y  ---   ---  ---       AND zpg,X  ROL zpg,X ---  SEC impl  AND abs,Y ---      ---  ---       AND abs,X ROL abs,X ---
4‐  RTI impl EOR X,ind  ---   ---  ---       EOR zpg    LSR zpg   ---  PHA impl  EOR #     LSR A    ---  JMP abs   EOR abs   LSR abs   ---
5‐  BVC rel  EOR ind,Y  ---   ---  ---       EOR zpg,X  LSR zpg,X ---  CLI impl  EOR abs,Y ---      ---  ---       EOR abs,X LSR abs,X ---
6‐  RTS impl ADC X,ind  ---   ---  ---       ADC zpg    ROR zpg   ---  PLA impl  ADC #     ROR A    ---  JMP ind   ADC abs   ROR abs   ---
7‐  BVS rel  ADC ind,Y  ---   ---  ---       ADC zpg,X  ROR zpg,X ---  SEI impl  ADC abs,Y ---      ---  ---       ADC abs,X ROR abs,X ---
8‐  ---      STA X,ind  ---   ---  STY zpg   STA zpg    STX zpg   ---  DEY impl  ---       TXA impl ---  STY abs   STA abs   STX abs   ---
9‐  BCC rel  STA ind,Y  ---   ---  STY zpg,X STA zpg,X  STX zpg,Y ---  TYA impl  STA abs,Y TXS impl ---  ---       STA abs,X ---       ---
A‐  LDY #    LDA X,ind  LDX # ---  LDY zpg   LDA zpg    LDX zpg   ---  TAY impl  LDA #     TAX impl ---  LDY abs   LDA abs   LDX abs   ---
B‐  BCS rel  LDA ind,Y  ---   ---  LDY zpg,X LDA zpg,X  LDX zpg,Y ---  CLV impl  LDA abs,Y TSX impl ---  LDY abs,X LDA abs,X LDX abs,Y ---
C‐  CPY #    CMP X,ind  ---   ---  CPY zpg   CMP zpg    DEC zpg   ---  INY impl  CMP #     DEX impl ---  CPY abs   CMP abs   DEC abs   ---
D‐  BNE rel  CMP ind,Y  ---   ---  ---       CMP zpg,X  DEC zpg,X ---  CLD impl  CMP abs,Y ---      ---  ---       CMP abs,X DEC abs,X ---
E‐  CPX #    SBC X,ind  ---   ---  CPX zpg   SBC zpg    INC zpg   ---  INX impl  SBC #     NOP impl ---  CPX abs   SBC abs   INC abs   ---
F‐  BEQ rel  SBC ind,Y  ---   ---  ---       SBC zpg,X  INC zpg,X ---  SED impl  SBC abs,Y ---      ---  ---       SBC abs,X INC abs,X ---


Busy píše:
_dworkin píše:
... Protoze 6502 ma invertovanou hodnotu carry oprotu Z80. ...
Podla mna to moc komplikujes.
Uplne staci vediet ze 6502 pri odcitani (a teda aj porovnani) proste pouziva carry invertovane. 1 znamena ze nebol prenos a 0 znamena ze bol. Tot vsio :)
Viem ze pre intelakov a zilogakov je to trosku odveci, ale co narobime.
Co ale mne osobne pride od veci este viac, je ze pri scitani sa pouziva carry neinvertovane. Taka mala nekonzistencia, no ;)

To me prijde spis zvlastni videt ze ma pri odcitani/porovnani 6502 oproti Z80 invertovany carry jako prirozeny fakt, ale to ze ma u adc carry S TEJNY jako Z80 jeste zvlastnejsi. Asi narazis na to ze se s timhle otocenim musi vyporadat i 6502 programator? Ten to asi bere jako prirozeny fakt.

Kdyz ignoruji jak to ma vnitrne zadratovany procesor a budu to brat z pohledu programatora, tak stale nedokazi odhadnout ktery zpusob je obecne vyhodnejsi... (a nebo to vyjde celkove nastejno) ale v konkretnim algoritmu deleni je lepsi to mit "invertovane". Tam kde se ti u metody "dlouheho deleni" vleze odcitane cislo (delitel) do posunovaneho delence je dobre mit rovnou carry jako 1, protoze ho nacitas(posunem) do vysledku. A nemusis invertovat carry (kratsi ale pomalejsi) a nebo na konci provest xor 0xFF s vysledkem (delsi ale rychlejsi). A nebo pouzit uplne jinou metodu.

Jen me stale nejak hlava nedokaze ukazat jak se to poradne chova.
U Z80 jsem automaticky schopen provest:

A+X aby carry bylo 0 nebo 1 tim ze upravim X do nejakeho tvaru (256-X) a pouziji bud ADC/ADD nebo SBC/SUB
A-X aby carry bylo 0 nebo 1 tim ze upravim X do nejakeho tvaru (256-X) a pouziji bud ADC/ADD nebo SBC/SUB

u 6502 me hlava rika... DEJ ME POKOJ! Nechces se radsi kouknout na anime nez delat tyhle kraviny a odmita myslet.

Kdyby mel 6502 instrukci ADD a SUB (coz by evidetne mohl kdyz ma tolik mista v kodovani instrukci, jen by se jim prodrazil hw) tak by si usetril i to jednou nastavit carry (SBC-->SUB) a jednou ho vynulovat (ADC-->ADD). Mozna by bylo zajimave vedet jak casto to musis delat a jak casto znas predchozi stav. Zda se ze 6502 nemeni CARRY pri nacitani hodnoty do A (na rozdil od ZERO a SIGN FLAG!!!).
V nejhorsim pripade to muze byt dvojnasobna delka a trvani...
Tezko rici kde 6502 programatory tlaci nejvice bota, pro me by to bylo(byla?) asi velikost zasobniku. Mit tam jeste neco co ma Z80 tak by mel najednou 2 zasobniky a byl by to idealni procesor pro FORTH. Sorry offtopic.

faraon píše:
Nad tímhle jsem u TWELVE dost dlouho zpytoval, a nakonec jsem to udělal tak, že před začátkem sčítání/odčítání se Carry musí vždy vynulovat, a pokud došlo k přenosu/výpůjčce, nastaví se na 1. No a ta jednička se při pokračování výpočtu k dalšímu slovu automaticky přičte/odečte. Vlastně jsou tam jenom ADC a SBC.
Takže pokud je po spočtení všech řádů Carry 1, tak se to buď nevešlo nebo překlopilo znaménko. Což jde testovat jednou podmínkou bez ohledu na to, jestli se předtím přičítalo nebo odčítalo.


Co je TWELVE?
Jinak popisujes Z80 variantu pokud to spravne chapu, jen s tim ze nemas ADD a SUB.
Ale kdyz pises o "jednou podminkou" tak to asi neumi jr(jp) C a jr(jp) NC, ale jen jednu variantu? Pravdepodobne jr(jp) NC, aby se skocilo dal pokud nemusime resit problem. Stejne by s jeste bezpodminkovym skokem sla resit i opacna varianta jen o neco sloziteji... aaaa...uz zase offtopic.

Busy píše:
Inak ono v 6502 je viacero veci co sa pouzivaju naopak. Napriklad bit pre zakaz/povolenie prerusenia - 0 znamena povolene a 1 zakazane. Teda tiez presne naopak ako pri Inteli / Zilogu.

Dobra informace.
V tomhle odkazu https://litwr2.github.io/8080-8085-z80- ... -6502.html kde se snazi emulovat Z80 na 6502 je toho vic.

6502 a Z80 mají několik architektonických rozdílů, díky kterým je emulace několika funkcí Z80 téměř nemožná:

Ukazatel zásobníku u 6502 má svůj horní bajt vždy nastaven na 1, ale SP u Z80 má 16 bitů;
Zaváděcí instrukce 6502 (LDA, TXA, LDY, PLA, ...) mění SF a ZF, zaváděcí instrukce Z80 nemění příznaky;
6502 má dekadický režim a Z80 má instrukci decimální korekce (DAA);
6502 nemá příznaky parity, polovičního přenosu a odečítání;
6502 používá invertovaný příznak přenosu pro odečítání a porovnávání;
Instrukce 6502 JSR a RET pracují se zásobníkem trochu jinak než instrukce Z80 CALL a RET;
6502 nemá nic podobného instrukcím Z80 HALT, RETN a IM nebo registrům R a I;
Instrukce Z80 RETI je ve světě procesorů jedinečná;
6502 nemá speciální adresní prostor pro vstup a výstup.

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


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 14:26 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1335
Has thanked: 102 times
Been thanked: 195 times
Busy píše:
Panda38 píše:
RISC-V Hazard3 v RP2350 (Pico 2), a on vůbec ani nemá flagy, jako např. carry
A nielen RISCy, ale aj niektore klasiky: napriklad taky *51 vobec nema zero flag. Ale pritom ma podmieneny skor zero/non-zero :)
Proste, skoci/neskoci podla toho, ci je akumulator prave nulovy alebo nie.
Takze clovek, ktory je zvyknuty skakat podla toho ci vysledok operacie bol nula, nesmie pred tymto skokom naplnit akumulator, lebo v tomto pripade strati informaciu o tom ze vysledok bol nula.


A vnitrne to ma tak ze ZERO FLAG existuje jen neni pristrupny pro programatora a nebo fakt fyzicky pri potrebe zjistit stav dela OR nad vsemi bity (a pak to invertuje pokud by to melo vypadat jako na Z80) predtim nez udela skok?

Tezko posoudit co je z pohledu HW obtiznejsi.
Delat tohle zjisteni POKAZDE pri scitani nebo odcitani (nebo cokoliv co meni priznak)
a nebo az pri tech skocich.
Prijde me ze snazsi je to delat asi potom (z pohledu hw), ale pomalejsi, protoze pri prvnim zpusobu to muze bezet paralelne a pri podminenem skou uz jen cte jeden bit. Ale pokud dokaze provest 8x (nebo vickrat) ten bitovy OR v "temer nulovem" case tak je to asi lepsi... (vnitrne to vsechno muze vypadat jinak, mezitim co pocita stav ZERO muze do TMP pocitat nove PC u relativniho skoku a pak to jen "prekolopit" nebo ponechat podle toho co mu vyjde a jestli jeste u toho zpracovava dopredu do fronty nasledujici instrukce... tak to neni muj problem... co to anime?).

V podstate ta 6502 muze mit vnitrne taky neexistujici ZERO FLAG ne? Pokud ho nastavuje i pri nacteni hodnoty do A, tak to muze pocitat klidne az pri podminkovem skoku. A ZERO FLAG muze byt virtualni pro programatora.

Panda38 píše:
Studuji teď RISC-V Hazard3 v RP2350 (Pico 2), a on vůbec ani nemá flagy, jako např. carry. A kupodivu ono se bez toho dá obejít. :-) Když potřebuje vědět výsledek operace, otestuje to až potom. Např. u součtu 64-bit sečte LOW, porovná výsledek aby otestoval přetečení, a podle toho pak inkrementuje součet HIGH.

Vubec nechapu jak si to mam predstavit... jak to myslis s tim souctem
Skryty flag?
Ma 2 instrukce pro to scitani a odcitani?
V podstate ma ADD a ADC pro hi? Jen se skrytym carry?
Takze u 32 bitoveho souctu pouzivas ADD (presneji je to asi OR A : ADC)
a kdyz mas 64 bitovy soucet tak po ADD provedes ADC?

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


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 14:55 
Offline
Radil

Registrován: 16.09.2022, 16:24
Příspěvky: 347
Has thanked: 8 times
Been thanked: 62 times
_dworkin píše:

Panda38 píše:
Studuji teď RISC-V Hazard3 v RP2350 (Pico 2), a on vůbec ani nemá flagy, jako např. carry. A kupodivu ono se bez toho dá obejít. :-) Když potřebuje vědět výsledek operace, otestuje to až potom. Např. u součtu 64-bit sečte LOW, porovná výsledek aby otestoval přetečení, a podle toho pak inkrementuje součet HIGH.

Vubec nechapu jak si to mam predstavit... jak to myslis s tim souctem
Skryty flag?
Ma 2 instrukce pro to scitani a odcitani?
V podstate ma ADD a ADC pro hi? Jen se skrytym carry?
Takze u 32 bitoveho souctu pouzivas ADD (presneji je to asi OR A : ADC)
a kdyz mas 64 bitovy soucet tak po ADD provedes ADC?


Celkem komplexni odpoved je zde:

https://stackoverflow.com/questions/709 ... -carry-out

Cela rada hlavne RISC architektur miri navrhem na "flagless", ma to svoje vyhody, ktere mohou prevazit nad nevyhodami (a ja pocitam, ze navrhari techto architektur delali hluboke analyzy, zkouseli ruzne alternativy nad real-world kodem, atd.).

RISC-V ma i jine zajimave vlastnosti, treba mixovani bitu u skokovych instrukci, tohle mne zaujalo hodne - vysvetleni zde https://stackoverflow.com/questions/584 ... n-this-way (strucne: usetri se tim par logickych prvku v procesoru).

K tematu "odstranovani tradicnich vlastnosti" procesoru doporucuji tohle https://github.com/xoreaxeaxeax/movfuscator


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 16:28 
Offline
Óm Nejvyšší

Registrován: 22.05.2013, 21:14
Příspěvky: 3861
Bydliště: Bratislava
Has thanked: 377 times
Been thanked: 819 times
_dworkin píše:
Mozna by bylo zajimave vedet jak casto to musis delat a jak casto znas predchozi stav.
V mojich kodoch je tak 90% ADD/SUB a iba 10% ADC/SBC. Takze pre mna by absencia ADD/SUB na Z80 predstavovala velky zasah do programu. Akurat problem je skor v tom, ze ADD/SUB pomocou ADC/SBC nahradis ovela lahsie, nez naopak. Preto mnoho CPU ma iba to sice menej pouzivane, ale obecne ovela pouzitelnejsie ADC/SBC.
_dworkin píše:
Ukazatel zásobníku u 6502 má svůj horní bajt vždy nastaven na 1, ale SP u Z80 má 16 bitů;
Toto je taka dvojsecna zbran. 16-bitovy SP je obecne urcite ovela lepsi, ale zase 8-bitovy ma jednu vlastnost, ktoru ocenim hlavne pri pisani kratkych intier - vobec ho netreba inicializovat, cim usetrim zopar vzacnych bajtov. Tych 256 bajtov mozno chapat ako kruhovy buffer a v principe mi je uplne jedno, kde v tom kruhu sa pointer nachadza na zaciatku.

Inak, taka pikoska - 8080 umoznuje mat samostatnych 64kB pre program a data a dalsich samostatnych nezavislych 64kB pre zasobnik ;)
_dworkin píše:
6502 má dekadický režim a Z80 má instrukci decimální korekce (DAA);
6502 nemá příznaky parity, polovičního přenosu a odečítání;
Polovicny prenos a priznak odcitania vyuziva prave ta instrukcia DAA aby vedela aka operacia sa robila predtym a aby spravne upravila vysledok. 6502 to robi uz priamo pri samotnej operacii a netreba na to dalsiu instrukciu, preto dane priznaky nepotrebuje.

Taka pikoska - x86 ma samostatne instrukcie na desiatkove korekcie pre kazdu operaciu, takze tiez nepotrebuje priznak, ci posledna operacia bola scitanie alebo odcitanie.
AAA = Adjust after Addition
AAS = Adjust after Substraction
AAM = Adjust after Multiplication
AAD = Adjust before Division
_dworkin píše:
Instrukce 6502 JSR a RET pracují se zásobníkem trochu jinak než instrukce Z80 CALL a RET;
Ako inak ? Podla mna tak isto - JSR tiez PUSHne 16-bitovu navratovu adresu (a tiez vyssi bajt je vyssie) a potom RTS adresu POPne a vlozi do PC.
_dworkin píše:
Instrukce Z80 RETI je ve světě procesorů jedinečná;
Jedna pikoska: RETI a RETN je uplne to iste, obe zapisu IFF2 do IFF1 a urobia RET. A toto robi hned osem opkodov (po ED): 45 4D 55 5D 65 6D 75 7D
_dworkin píše:
6502 nemá speciální adresní prostor pro vstup a výstup.
A nielen 6502 ale aj vela inych procesorov. V podstate by som napisal, ze specialny adresovy priestor pre I/O je skor vynimka, nez zvyklost ;)

Pikoska: Verzia 6510 pouzita v C64 ma priamo na sebe jeden I/O port, ale aj ten je mapovany do bezneho pametoveho priestoru na adresy 0 a 1.


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 18:02 
Offline
Pan Generální
Uživatelský avatar

Registrován: 23.03.2014, 20:13
Příspěvky: 2934
Has thanked: 257 times
Been thanked: 641 times
_dworkin píše:
Co je TWELVE?
Jinak popisujes Z80 variantu pokud to spravne chapu, jen s tim ze nemas ADD a SUB.
Dvanáctibitový minipočítač TWELVE: https://www.oldcomp.cz/viewtopic.php?f=75&t=5918

Z80 to má u SBC opačně, ne? Před odčítáním musíš C nastavit na 1 a výpůjčka tam nechá nulu. Nebo si to pamatuji blbě?

_________________
Plesnivý sýr z Tesca, zatuchlé kuřecí řízky z Albertu, oslizlé hovězí a myší trus z Lidlu.
Nákup potravinářské inspekce v ČR, říjen 2023.


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 18:40 
Offline
Kecálek
Uživatelský avatar

Registrován: 18.06.2023, 18:37
Příspěvky: 132
Bydliště: Pražák z Prahe, žádná náplava :)
Has thanked: 25 times
Been thanked: 32 times
Citace:
A vnitrne to ma tak ze ZERO FLAG existuje jen neni pristrupny pro programatora a nebo fakt fyzicky pri potrebe zjistit stav dela OR nad vsemi bity (a pak to invertuje pokud by to melo vypadat jako na Z80) predtim nez udela skok?

Tezko posoudit co je z pohledu HW obtiznejsi.
Delat tohle zjisteni POKAZDE pri scitani nebo odcitani (nebo cokoliv co meni priznak)
a nebo az pri tech skocich.
Prijde me ze snazsi je to delat asi potom (z pohledu hw), ale pomalejsi, protoze pri prvnim zpusobu to muze bezet paralelne a pri podminenem skou uz jen cte jeden bit. Ale pokud dokaze provest 8x (nebo vickrat) ten bitovy OR v "temer nulovem" case tak je to asi lepsi...


Udělat OR nad 8 bity a pak to invertovat se eventuálně dá udělat tak, že tam vrazíš jeden tranzistor s 8 emitory a hotovo :)
(a tranzistor s 8 emitory je celkem snadný a celé i s tou inverzí to běží v čase překlopení jednoho tranzistoru - no neber to :) )

_________________
Spousta věcí chodí líp, když se zapne ...
http://micro-corner.gilhad.cz/, http://8bit.gilhad.cz/ a mnohé další


Nahoru
 Profil  
 
PříspěvekNapsal: 31.08.2024, 20:21 
Offline
Pan Generální
Uživatelský avatar

Registrován: 24.05.2018, 22:32
Příspěvky: 2119
Bydliště: Most, Praha
Has thanked: 955 times
Been thanked: 757 times
_dworkin píše:
...Vubec nechapu jak si to mam predstavit... jak to myslis s tim souctem. Skryty flag?...
RISC-V vůbec nepoužívá flagy ve kterých by si uchovával výsledek předešlé operace. Testuje výsledek až dodatečně po operaci. Příklad pro součet dvou 64-bitových čísel (registry má 32-bitové):

- první číslo např. v A2:A1
- druhé číslo např. v A5:A4
- sečte LOW registry A4+A1, výsledek dá do A3: add a3,a4,a1
- sečte HIGH registry A5+A2, výsledek dá do A2: add a2,a5,a2
- otestuje, zda došlo k přetečení součtu LOW: sltu a0,a3,a4
.... Tato instrukce porovná výsledek součtu LOW v A3 s jedním z operandů A4. Pokud je výsledek menší, znamená to že došlo k přetečení součtu LOW, do registru A0 v tom případu uloží 1, jinak uloží 0
- přičte výsledek testu v A0 k součtu HIGH v A2, čímž zajistí přenos do HIGH: add a2,a0,a2

Tato metoda se používá i při operacích s velkými čísly v C, protože tam nejsou k dispozici flagy. Provede se součet LOW, otestuje zda došlo k přetečení (výsledek je menší než některý ze vstupních operandů), a pokud ano, tak inkrementuje vyšší řád.

_________________
i++ (INC) increment
i-- (DEC) decrement
i@@ (EXC) excrement


Nahoru
 Profil  
 
PříspěvekNapsal: 01.09.2024, 00:56 
Offline
Pan Štábní

Registrován: 23.06.2013, 23:49
Příspěvky: 1335
Has thanked: 102 times
Been thanked: 195 times
faraon píše:
_dworkin píše:
Co je TWELVE?
Jinak popisujes Z80 variantu pokud to spravne chapu, jen s tim ze nemas ADD a SUB.
Dvanáctibitový minipočítač TWELVE: https://www.oldcomp.cz/viewtopic.php?f=75&t=5918

Z80 to má u SBC opačně, ne? Před odčítáním musíš C nastavit na 1 a výpůjčka tam nechá nulu. Nebo si to pamatuji blbě?


Nezacinal jsi na Atarku? .)
Protoze popisujes chovani 6502, carry = 1 nic neubere navic u SBC. Tzn. "SBC #23" je A - #23 - (1-carry) a nebo "A + 0xFF^0x23 + carry.
Z80 "sbc a,b" udela A = A - B - carry. Tam se proste 1 u adc pricita a 1 u sbc odcita.


Panda38 píše:
_dworkin píše:
...Vubec nechapu jak si to mam predstavit... jak to myslis s tim souctem. Skryty flag?...
RISC-V vůbec nepoužívá flagy ve kterých by si uchovával výsledek předešlé operace. Testuje výsledek až dodatečně po operaci. Příklad pro součet dvou 64-bitových čísel (registry má 32-bitové):

- první číslo např. v A2:A1
- druhé číslo např. v A5:A4
- sečte LOW registry A4+A1, výsledek dá do A3: add a3,a4,a1
- sečte HIGH registry A5+A2, výsledek dá do A2: add a2,a5,a2
- otestuje, zda došlo k přetečení součtu LOW: sltu a0,a3,a4
.... Tato instrukce porovná výsledek součtu LOW v A3 s jedním z operandů A4. Pokud je výsledek menší, znamená to že došlo k přetečení součtu LOW, do registru A0 v tom případu uloží 1, jinak uloží 0
- přičte výsledek testu v A0 k součtu HIGH v A2, čímž zajistí přenos do HIGH: add a2,a0,a2

Tato metoda se používá i při operacích s velkými čísly v C, protože tam nejsou k dispozici flagy. Provede se součet LOW, otestuje zda došlo k přetečení (výsledek je menší než některý ze vstupních operandů), a pokud ano, tak inkrementuje vyšší řád.


Aha ty zadas dalsi instrukce abys to vyresil.
To me prijde az brutalni...
A vlastne to ani nechapu... jak se to pak retezi dal...

Dejme tomu ze scitame dve 24 bitove cislo s 8 bitovou aritmetikou
A = 130,255,110
B = 333,322,311

110+201+0=311 = 1*256 + 55 --> c = 1
255+202+1=458 = 1*256 + 202 --> c = 1
130+203+1=334 = 1*256 + 78 --> c = 1

ty sectes prvni pripad

110+201 = 55
porovnas 55 < 110 a ziskas true do dalsiho registru
...aha! ty to nepotrebujes pricist zpet, jen dopredu takze...
co dal?
255+1 = 0 ??? ted to znovu preteklo a jeste jsem ani nepricetl 202 takze musim kontrolovat i tohle???
nebo spis...
255+202= 201
porovnas zda 201 < 255 a ziskas dalsi true...
ale jeste musis upravit vysledek s predchozim carry?
201+1=202
hmm.. ale tam ti to muze taky pretect.. pokud ten soucet byl 255 bez carry a s carry bude 0...
pokud vim tak by mel arm umet nejake podminkove instrukce... tak snad pouzit ty?
tohle me hlava nebere...

Jedine co me napada je..
a) 110+201 --> zkontroluji a ziskam carry

b) carry+255 --> zkontroluji a ziskam carry (prepisi stare)
c) (carry+255)+202 = konecne vysledek "druheho scitani" --> zkontroluji a ziskam carry2
d) carry=carry+carry2 = tohle nepretece... (prepisi stare)

e) carry+130 -> zkontroluji a ziskam carry (prepisi stare)
f) (carry+130)+203 = konecne vysledek "tretitho scitani" --> zkontroluji a ziskam carry2 (prepisi stare)
g) carry=carry+carry2 = tohle nepretece... (prepisi stare)

V kroku b) a e) kdy muze nastat dalsi carry to i znamena ze "mezivysledek" je vzdy nula, protoze jsem pricitali predchozi carry k prvni hodnote co se bude scitat. Takze pak ani nema cenu ji pricitat v kroku c) a f) k druhe... carry+carry2 je vzdy jen 0 nebo 1.
ale to asi nijak nejde vyuzit...

_________________
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ů: 25 ]  Přejít na stránku 1, 2  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 1 návštěvní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