Emulating a CPU in C++ #31 (6502) - Break & Return From Interrupt

  Рет қаралды 4,278

Dave Poo

Dave Poo

Күн бұрын

In this video I implement the "Break" BRK instruction and the "Return From Interrupt" instruction RTI. These (i thought!) are the last instructions to be implemented, after which we can start trying out real test programs in the next video.
Links:
Source for this project: github.com/davepoo/6502Emulator
Google Test: github.com/google/googletest
6502 Information: www.obelisk.me.uk/6502/
6502 test program: github.com/Klaus2m5/6502_65C0...
Timestamps
0:00 Intro
0:30 BRK instruction
2:40 BRK program counter test
7:30 BRK program counter implementation
9:52 B Flag test
10:54 B Flag implemented
11:12 Stack values test
16:10 Pushing stack values
27:00 Refactoring PushPCToStack
30:30 RTI instruction
31:00 RTI test
33:28 RTI implementation
41:11 Fixing failing tests
44:15 Closing comments
45:01 6502 test program

Пікірлер: 20
@twobob
@twobob 3 жыл бұрын
Yep, loved the series, Great binge watch.
@declspec
@declspec 3 жыл бұрын
This is actually really interesting, looking forward to watch the rest of the vid :)
@cigmorfil4101
@cigmorfil4101 3 жыл бұрын
The instruction clock cycles are: BRK 1 - fetch OP, PC++ 2 - PC++ ; decode BRK, set B 3 - store PCH on stack; dec S 4 - store PCL on stack; dec S 5 - store P on stack; dec S 6 - fetch IRQL* to PCL; set I 7 - fetch IRQH* to PCH During an interrupt cycle 1 finishes previous OP, cycle 2 forces a BRK instruction, and the PC value is held. RTI 1 - fetch OP 2 - decode RTI 3 - inc S 4 - Fetch P; inc S 5 - fetch PCL; inc S 6 - fetch PCH Cycle 3 is needed as stack pointer points to next location to use and the 6502 can't actually pre-increment the stack pointer: the address is (synchronously) put out at the start of the cycle and the increment happens during the cycle. Using synchronous memory access the 6502 is split into 2 halves - every cycle something happens external (reading/writing memory) and internal (processing some data and changing its internal state). It does mean the 6502 often reads data which it then ignores, but it effectively gives it a 1 byte pipeline/cache which means the processor overlaps finishing one instruction whilst loading the pipeline/cache with the next instruction from memory. Whilst it decodes the instruction the processor has already loaded the next byte which can be immediate data or the low byte of an address (or the next instruction), ready for use. Being little-endian it can process the ADL (eg add an index) whilst loading the ADH. * this is what should happen, however due to a "feature" should a NMI occur at the same time as a BRK instruction it will load from NMIL and NMIH instead.
@andrsam3682
@andrsam3682 3 жыл бұрын
Hey Dave, thanks for this series. Great example of TDD approach.
@DavePoo
@DavePoo 3 жыл бұрын
Thanks, this CPU emulator seemed to be a perfect candidate for testing, is it basically has 152 discrete things it does, which can be tested on their own. I fixed the cycle count you mentioned in #34 (which isn't out yet)
@andrsam3682
@andrsam3682 3 жыл бұрын
@@DavePoo you inspired me with your project:) I'm currently working on Z80 emulator with option of emulating Z80's soviet clone Т34ВМ1, which didn't have some of the undocumented commands (obviously). And now I want to try TDD methodology, Unity framework, to be more specific (I'm programming in plain C).
@DavePoo
@DavePoo 3 жыл бұрын
@@andrsam3682 Go for it. I think one of my conclusions has been that the Unit testing approach is a very big help but you will need additional testing as well as it can't find everything. It's still possible to screw somethings up, as you pointed out about the branch cycles error, but once if you have a full suite of tests it's much eaiser to change the program and still be confident that you still have a working emulator at the end of it.
@superkplunk
@superkplunk 3 жыл бұрын
Really enjoying this series, finally caught up after watching every video over past few days. Excellent example of proper test driven development, well done! One small thing, I think you have a bug in your addressing methods when calculating extra cycle if passing a page boundary (AddrAbsoluteX, AddrAbsoluteY, AddrIndirectY). You are not actually checking if you pass a page boundary - only checking if the value you are adding to the address is >= 255. Guessing your tests for this one aren't robust enough. Interestingly, you did this correctly in the conditional branch code - look at the BranchIf lambda. Great work so far - can't wait to see it run a full program
@DavePoo
@DavePoo 3 жыл бұрын
Thanks, I think you are right about that. Actually, i did also write the BranchIf incorrectly as well (but for a different reason and also pointed out in youtube comment), and that is fixed in a future video.
@tv8g
@tv8g 3 жыл бұрын
Hey so far iv'e learned a lot from your videos! You should create a discord chat, I think a lot of people would like if you had one.
@JulianOnions
@JulianOnions 3 жыл бұрын
Enjoying this - one suggestion, make the instructions part of an enum, just for my OCD :) That way they are all part of something common, and you might even win on the switch statement detecting unused cases.
@DavePoo
@DavePoo 3 жыл бұрын
I could make them an enum, but I never deemed it a good idea because a) you are allowed duplicate definitions in an enum so it doesn't stop that b) FetchByte returns an byte not an instrucion, so an enum class would require an extra cast c) If there are unused cases then they won't have any effect on the program, the unit tests and test programs (in later video) will detect any cases that haven't been handled correctly d) every time i use the instruction in the unit tests, i am pushing the byte into memory to create the test progam, an enum class would require me to write 100's of casts, a normal enum would be better but then i lose type safety of knowing it's a byte (they also pollute the namespace) . So i just want the instructions to be what the progam treats them as "a Byte", if i make them an enum class they become a new type, if i make them a normal enum i can't define the Byte type explicity. Remember that the D in OCD stands for "Disorder" not "Order", so don't let that get in the way of reasoning about how a thing should work, something should exist or be a particular way for a reason, not because either your brain likes it that way, or it's a "rule of thumb". And if my code triggers your OCD, then please don't look at the VICE emulator, they don't even name the instruction, it's just a magic number in switch statement e.g. "case 0x61: /* ADC ($nn,X) */"
@JulianOnions
@JulianOnions 3 жыл бұрын
@@DavePoo Yes fair enough, the casting would be a pain. I still like the grouping it gives you, but in the end I take my hat off to all your efforts!
@sandervanderhorst9851
@sandervanderhorst9851 3 жыл бұрын
You should check for the number of instructions handled
@CommanderKlag
@CommanderKlag 2 жыл бұрын
Hello, hello, Where is the video that shows the final emulator actually doing real world work, Where's the "Hello World" program or other real-world program example (non build tests), other than your work note & concept debugging tests? I saw the google copyright. I must have overlooked the actual program example apps that use your work. You did so much personal work. This is hudge, but I'm lacking confidance in spending hours on it as I would need to port it to Linux. Plus I was hoping to be able to execute programs, but I guess this is perfect for a windows developer. I would haft to spend hours to even determine if I can use it for my needs. It's allot of code. I'm sure it functions, but does it actualy work and do anything? That's the video I can't find. The final Presentation Video.
@DavePoo
@DavePoo 2 жыл бұрын
There is no actual final "Hello World" program for this, I just wrote a CPU emulator. To get a computer to display "Hello World" that requires video output capability which implies writing a full computer emulator. I didn't set out to do that in this video, as 35 videos was enough just getting the CPU emulator to go. I in the end I did get it to execute a test program from start to end, but the program itself does not produce any output, it just runs through all the functions of the CPU. If you are looking for a full computer emulation, you could look through the source code for VICE which emulates the C64 and other 8-bit platforms.
@rob876
@rob876 3 жыл бұрын
How do you do multiplication on the 6502?
@DavePoo
@DavePoo 3 жыл бұрын
Well i suppose short answer is "you express your multiplication as a series of additions", which is what multiplication really is mathematically. But you also have "shift left" which multiplies by 2, so you can use that to multiply by 2, 4, 8 etc. This webpage is worth a read if you are interested nparker.llx.com/a2/mult.html Also worth noting is that when you go up to 16-bit processors like the 68000 which could multiply natively. Check out how many clock cycles it takes to do the multiply, 70 clock cycles!!! wiki.neogeodev.org/index.php?title=68k_instructions_timings So you can see that there is no free lunch there for the CPU that could natively multiply, you might be able to write a faster multiply yourself if you knew something about the input data.
@cigmorfil4101
@cigmorfil4101 3 жыл бұрын
By addition: add together the values of one number multiplied by 2^(every bit set in second number). eg to multiply a number by 10 (decimal): 10 in binary is 0000 1010 so add together the number×2^1 and the number×2^3 since bits 1 and 3 are set: 9 × 10 = 9×2^1 + 9×2^3 = 18 + 72 = 90 By using right shifts the set bits of the multiplier can be detected, and by using left shifts on the number that number multiplied by the powers of 2 are calculated. The loop can either be done for a count of the bits in the multiplier, or until the multiplier equals zero. When multiplying two 8 bit numbers the result can be 16 bits, so 16 bits need to be used as the working storage for the result and number (whilst the multiplier uses 8 bits) during the loop.
@cigmorfil4101
@cigmorfil4101 3 жыл бұрын
@@DavePoo The time on the 68k is it doing the equivalent of the 6502 discreet instructions in micro code?
Emulating a CPU in C++ #32 (6502) -  Test Program Debugging
52:25
Replace your 6502 computer's RAM or ROM in seconds with this! (ROMulator)
38:18
Adrian's Digital Basement
Рет қаралды 95 М.
CAN FOXY TRICK HIM?! 🤣 #shorts *FOXY AND NUGGET!*
00:17
LankyBox
Рет қаралды 15 МЛН
请善待你的娃娃第二集 #naruto  #cosplay  #shorts
00:52
佐助与鸣人
Рет қаралды 24 МЛН
Суд над Бишимбаевым. 2 мая | ОНЛАЙН
7:14:30
AKIpress news
Рет қаралды 673 М.
BEST WAY to make Desktop Applications in C++
26:00
The Cherno
Рет қаралды 863 М.
NES Emulator Part #2: The CPU (6502 Implementation)
1:07:12
javidx9
Рет қаралды 408 М.
I Designed My Own 16-bit CPU
15:46
AstroSam
Рет қаралды 1,8 МЛН
27c3: Reverse Engineering the MOS 6502 CPU (en)
51:57
Christiaan008
Рет қаралды 428 М.
Bjarne Stroustrup: C++ | Lex Fridman Podcast #48
1:47:13
Lex Fridman
Рет қаралды 1 МЛН
Software Testing Explained in 100 Seconds
2:16
Fireship
Рет қаралды 273 М.