![]() |
![]() |
#21 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,441
|
subx is handling X not C. If you have carry from ror or cmp, subx isn't going to register it. scs is more appropriate.
|
![]() |
![]() |
#22 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
Right, can be 2 versions subx.w and scs.
subx.w is perhaps fastest. for scs also ext.w is perhaps necessary. |
![]() |
![]() |
#23 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,441
|
subx is useless as it won't catch all occurrences of carry.
add/sub/asr/asl/rox => set X and C cmp/rol/lsr => set C only 6502 carry is also a nightmare when handling with 68000. It's inverted for comparisons, and also when SBC it's not a carry it's a "borrow", so also inverted. |
![]() |
![]() |
#24 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
I dont think that subx.w is useless.
This is emulation, every emulated command can used different handling of Carry. 2 versions of fast enough handling C is for me ok. Of course, I dont know 6502 instructions. But if 6502 has something like rorx.b #1 or rolx.b #1 or similar commands. Then word value as C/X is better than byte value for handling similar instructions. You can use f.e Code:
move.b D0,D6 ror.w #1,D6 move.b D6,D0 |
![]() |
![]() |
#25 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,386
|
|
![]() |
![]() |
#26 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,441
|
yes, LSR sets X, my bad.
ADDX can efficiently emulate ADC. But SUBX and SBC don't work the same, you have to invert X flag (borrow, not carry). Those 8 bit processors don't have X and also don't have flag set on LDA (move), and they use that a lot. example on Z80: Code:
CP B LD C,A BNE xxx another example (Z80) Code:
CP B RR C |
![]() |
![]() |
#27 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
Of course I dont know 8 bit commands.
But if You want JOTD open new thread, with proposition of fast emulation of 8bit instructions. For me Carry bit for most 8 bit commands can be handled very fast with subx.w command. f.e for left shift (8 bit commands): Code:
add.b D0,D0 subx.w D6,D6 ; set carry bit Code:
add.b D6,D6 ; use carry bit (can be add.w too) addx.b D0,D0 subx.w D6,D6 ; set carry bit |
![]() |
![]() |
#28 | |||
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,386
|
Quote:
68k designers valued programmability more than transistor count enough to do that inversion in HW. Quote:
Quote:
If you convert code you can use extra register and use SUB rather than CMP, then follow with EORI to CCR to revert the carry. If you emulate, SCC will give you the carry and then you have to reload and revert it again prior to the SUBX. |
|||
![]() |
![]() |
#29 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
After some rethinking time it must be add.w, not add.b.
Because D6.b can be always used as temp. Using add.b is wasting this possibility. for left shift with carry Code:
add.w D6,D6 ; use carry bit addx.b D0,D0 subx.w D6,D6 ; set carry bit |
![]() |
![]() |
#30 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
Perhaps for handling CCR bits similar code can be used:
Code:
lea ReturnFull(PC),A6 sub.l D0,D0 ReturnFull subx.w D6,D6 ; set X bit as word tst.b D0 sxx D7 ext.w D7 ; set N bit as word tst.b D0 sxx D7 ; set Z bit as byte move.b (A0)+,D0 jmp Emu00(PC,D0.L*8) Emu00 .... |
![]() |
![]() |
#31 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,441
|
Smart, very good use of Sxx. BTW carry is left out of this code. Required for CMP for instance. But maybe flag tests are specific per-instruction?
|
![]() |
![]() |
#32 |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
Of course this is only idea.
Everything can be changed or adapted to be better/faster. F.e tst.w D7 can check 2 bits (if zero), N and Z. Dependent which value N and Z is the common too test, then different sxx can be used. N=1 not must be $FF, can be for emulatiion also set as $00. Of course also place of flags can be changed. When I tried to optimize dos.library, I used one data register for fast checking of 3 flags. And it was very fast, much fastest than original dos.library which using stack for flags via link.w command. Same here, now D6 is free, but maybe better can be handling 3 CCR bits in 2 registers. I dont know. I dont see emulation code for 6502. Code:
lea ReturnFull(PC),A6 sub.l D0,D0 ReturnFull sxx D7 extb.l D7 ; set C bit as longword tst.b D0 sxx D7 ext.w D7 ; set N bit as word tst.b D0 sxx D7 ; set Z bit as byte move.b (A0)+,D0 jmp Emu00(PC,D0.L*8) Emu00 .... |
![]() |
![]() |
#33 | |
Registered User
Join Date: May 2013
Location: Grimstad / Norway
Posts: 876
|
Quote:
As for X and Y I treat them the same way as A, I just copy the updated register to my "NZ" register. Yes, it would be nice to have more registers for once... |
|
![]() |
![]() |
#34 |
Zone Friend
Join Date: Apr 2006
Location: Gothenburg/Sweden
Age: 48
Posts: 347
|
Ah of course.. Can you explain more about how you worked with the Carry-bit?
|
![]() |
![]() |
#35 | |
Registered User
Join Date: May 2013
Location: Grimstad / Norway
Posts: 876
|
Quote:
I can't remember if I ever did anything but make it functional. Might even be bugged: Code:
move.b (reg_P,arDATA),drZP_EA smi drNZ extb.l drNZ ; set N NNNN add.b drZP_EA,drZP_EA ; N V_BDIZC0 smi drVC ; set V extb.l drVC ; VVVV lsl.b #3,drZP_EA ; B DIZC0000 smi drEA ; set D ext.w drEA ; move.b drA,drEA move.w drEA,drA lsl.b #2,drZP_EA ; I ZC000000 scs (reg_I,arDATA) ; set I spl drNZ ; set Z NNNZ add.b drZP_EA,drZP_EA ; Z C0000000 smi drVC ; set C VVVC This is the register use: Code:
drJUMP equr d0 ; use same to dispatch drZP_EA equr d0 ; 64k aligned $xxxx00xx, .b is 'scratch' drSP equr d1 drEA equr d2 ; 64k aligned, .w is 'scratch' drVC equr d3 ; .w overflow(15), carry(7-0) drNZ equr d4 ; negative(15-8), zero(7-0) drA equr d5 ; only low word used $00xx.w drD equr drA ; .w decimal drX equr d6 ; only low word used $00xx.w drY equr d7 ; only low word used $00xx.w arDATA equr a6 ; pointer to base of variables arPC equr a5 ; 64k aligned program counter arJUMP equr a4 arWSTAT equr a3 ; pointer to array of write status bytes ar68CODE equr a2 ; 256 functions max 112 bytes big arEA equr a1 hwREG equr a1 arTMP equr a0 |
|
![]() |
![]() |
#36 | |
Registered User
Join Date: May 2013
Location: Grimstad / Norway
Posts: 876
|
Quote:
This is BCC/CPY/ADC for example: Code:
; BCC op_start op90_BCC CARRYTEST bmi.b .nobcc DoBranch .nobcc jump2 2 ; CPY abs op_start opCC EA_abs move.b drY,drNZ ReadCheckF sub.b drZP_EA,drNZ scc drVC SETN jump3 4 ; ADC zp op_start op65 EA_zp movea.l drZP_EA,arEA ReadCheckZP move.b (arEA),drZP_EA add.b drVC,drVC ; set X flag DTEST bmi.b .opdec\@ addx.b drZP_EA,drA MOVENOPW .opdec\@ ; OTHER CODE abcd drZP_EA,drA ; ADDX.B or ABCD drZP_EA,drA scs drNZ svs drVC extb.l drVC move.b drNZ,drVC SetAndJump drA jump2 3 Code:
CARRYTEST macro tst.b drVC endm ZEROTEST macro tst.b drNZ endm DTEST macro tst.w drD endm NEGTEST macro tst.w drNZ endm VTEST macro tst.w drVC endm CLEARV macro and.w #$00ff,drVC endm CLEARD macro and.w #$00ff,drD endm CLEARCARRY macro clr.b drVC endm CLEARN macro and.w #$00ff,drNZ endm SETN macro extb.l drNZ endm SETD macro or.w #$ff00,drD endm SETV macro or.w #$ff00,drVC endm SETCARRY macro move.b #$ff,drVC ; st drVC endm There is a lot to ponder when emulating - do you always read at least 2 bytes from memory for an opcode, do you do hw checks on all opcodes you read from memory, do you use post/pre-increment for memory access or do you make 100% sure that you can handle any wraparound, is there any memory banking going on, and if so do you use indirection tables for accessing the right memory stuff, and how do you handle things like write to ROM with RAM under? Many things are easier if it is not a C= 64 you model. |
|
![]() |
![]() |
#37 | |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,386
|
Quote:
Nothing to do with just storing A,X,Y value for later computation. Wasn't it an idea you had but later rejected, instead ? This is what happened to me. Perhaps the code for LDA would help understanding the way you handled NZ flags at the end. |
|
![]() |
![]() |
#38 | |
Registered User
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 56
Posts: 2,121
|
Quote:
And for me handling X bit is much easier than C bit. Then i will add for some instructiions which dont handle X bit, extra code. f.e for emulating ror it will be Code:
ror.b #1,d0 move.b d0, d7 (temp) add.b d7,d7 ; set X bit |
|
![]() |
![]() |
#39 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,386
|
You don't need to emulate ror on 6502.
As 6502's rol/ror are actually roxl/roxr with count=1... |
![]() |
![]() |
#40 |
Alien Bleed
Join Date: Aug 2022
Location: UK
Posts: 4,865
|
This thread is very interesting. Once, long ago, I wrote a z80 emulator for 68020 and I remember the whole threaded jump table approach and trying to make sure every handler was on the same power of 2 boundary etc. I also remember it being a massive pain in the backside, especially flags and interrupts.
I know next to nothing about 6502 by comparison, but ended up writing an emulation (for fun and a challenge) in php of all things. What is being targeted as a host CPU here? |
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Converting 6502 to 680x0 (calling all 6502/680x0 experts) | oRBIT | Coders. General | 12 | 14 January 2015 19:18 |
Visual 6502 in JavaScript | Charlie | Retrogaming General Discussion | 1 | 03 October 2010 13:35 |
6502 Asm | pmc | Coders. General | 21 | 06 November 2008 09:37 |
|
|