Emulating a CPU in C++ #9 (6502) - JMP & C++ Unions!

  Рет қаралды 7,896

Dave Poo

Dave Poo

Күн бұрын

In this episde i improve the JSR/RTS unit tests and discover that it's much harder to make a C++ union with bit fields than i thought.
Links:
Source for this project: github.com/davepoo/6502Emulator
Google Test: github.com/google/googletest
6502 Information: www.obelisk.me.uk/6502/
Timestamps:
0:00 JSR/RTS Recap
2:20 Improving RTS test
3:30 JSR checking status flags
4:37 Union the status flags
14:47 Adding the unused status bit
16:14 JSR checking status flags
18:55 JMP unit test
25:50 JMP Implementation
27:53 Closing comments

Пікірлер: 22
@alk3myst
@alk3myst 5 ай бұрын
I have no need for this, but I can't stop watching these videos. My dad brought home an Apple //e in 1983 with a Grappler+, Apple DMP, Midi card, dual disks, Kensington System Saver :), modem and more. Lots of Beagle Bros software including a copy of their Peek and Pokes chart. :)
@mrdude3957
@mrdude3957 3 жыл бұрын
StatusFlags Bit5 "Must always be 1"
@robertgrant721
@robertgrant721 3 жыл бұрын
Having a good chuckle over the union effort! :)
@DavePoo
@DavePoo 3 жыл бұрын
You're welcome
@alk3myst
@alk3myst 5 ай бұрын
Me too, it was blowing my mind what was going wrong.
@hjups
@hjups 3 жыл бұрын
For unions (if you haven't found out about this yet), you can do something similar to what you ended up doing; union{ Byte Value; struct{ Byte A : 2; Byte B : 3; Byte C : 1; }Fields; } The problem was that you wanted to create a union between the packed struct object and the full value byte, so you had to put the packed bits into a struct within the union. Also, you typically need to make the struct members types the size of the largest element. So for example, if the value was a Word instead, then all of the struct members should be a Word as well even if they are 1 bit, or at least it has never worked for me otherwise. It's a super handy way for emulating and talking to actual hardware bit fields. In terms of the PC incrementing, you probably should have that as another step to the instructions, since it didn't necessarily happen for all instruction (like with JSR). Instead, the PC register is not updated so that it is saved directly onto the stack. That probably did simply the hardware, especially when doing jumps and branches. Most likely once RTS loaded the PC, it was then incremented before continuing, so that the PC pointed to the correct next instruction. Also, the 6th cycle for JSR was to decrement the stack pointer, because it used the ALU to do so.
@rjmercier1
@rjmercier1 3 жыл бұрын
The struct and union names can be omitted if the field names are unique: struct CPU { union { Byte PS; struct { Byte A:1; Byte B:1; }; }; ... }; Then can do cpu.PS or cpu.A, etc.
@splinefox
@splinefox 3 жыл бұрын
Thank you very much for such interesting and informative videos. You are doing a great job!
@DavePoo
@DavePoo 3 жыл бұрын
Thanks. The plan was at the start to show how you might write an emulator, but in the end i've decided to write the entire emulator on video and just see how that goes.
@arkanjo7509
@arkanjo7509 2 жыл бұрын
thanks
@jlawrence71
@jlawrence71 3 жыл бұрын
working my way through all your 6502 videos. thanks a million for the great work. i am following along but implementing in javascript. i am wanting to emulate c64 and this work will be the basis. i see your last posting in this series was nov 2020. are you planning on more? i am using JS because graphics and sound are more accessable on that platform without any big learning curve (at least for me). would like to see you cover memory mapped i/o and approach interfacing maybe a simplified simulation of a video and audio device (prob VIC,SID would be overly complex). Cheers
@DavePoo
@DavePoo 3 жыл бұрын
I don't have plans for more at the moment, i am busy with life and my day job. I was thinking about putting what i had into Unreal and taking it further. But perhaps instead maybe doing that with VICE which is a very good emulator for the C64. Have you seen Matt Godbolt's talk on emulating the BBC micro, he did that in Javascript!
@jlawrence71
@jlawrence71 3 жыл бұрын
@@DavePoo yes, i watched his video yesterday. there are many good emulators out there. i am doing this for learning purposes and seeing how far i can go. i will probably look at others only when i get stuck. unreal is a good idea as that would yield x-platform. i use a mac and did not want to learn metal. i appreciate your contributions. i am far enough along and have enough resources to continue. i have learned alot so far from you. i am a big TDD person too, i appreciate that approach. Cheers and happy life. !!
@64jcl
@64jcl 3 жыл бұрын
No doubt the program counter is counted first before it executes the next instruction. So PC is left at the last byte of the last instruction. Then on the next iteration it first increments PC before reading the next opcode. So an RTS would in fact reset the PC to what it actually was when it was doing the JSR which was that PC was pointing to the last byte of the address.
@hjups
@hjups 3 жыл бұрын
I think that's a matter of alignment. A better way to look at it is how it was written in the C++ code. The increment is done via reg -> inc.en -> reg. This means that the increment signal is applied per cycle. So for the JSR, most likely the order of operations was: fetch instruction (no increment), push PCL onto stack, increment stack pointer (in main ALU), push PCH onto stack, fetch new PCL, fetch new PCH [end of instruction / reset to fetch]. Then the next instruction starts at the address loaded into the PC register. Throughout that entire process, the inc.en was never asserted, so the PC was never incremented. For something like LDA_Imm, it was probably: fetch instruction (increment), fetch byte (increment) [end of instruction / reset to fetch]. There the PC increment was asserted for both cycles. The interesting thing is that the increment is generated by the decode ROM, so the critical path goes from the PC register, out the bus to memory, back in to the pre-decoder, into the decode ROM, through the incrementor, up the carry chain, over to the PCH carry in, up that carry chain, and finally into the PCH register. That may not be the longest critical path, but it sure is a long one, and probably a limiting factor to the CPU speed.
@tmbarral664
@tmbarral664 3 жыл бұрын
Dave, for the test, you're testing what the code is doing, changing. As for LDA #42, you're checking afterwards the value of the Acc. JMP and JSR are basically a LOAD PC. So you should always test the PC after. Also, when testing an opcode, it is better to test only this opcode. The JSR test with a LDA and RTS is not right. Too much here. For the statusFlags, Carry is bit 0. So it should be the last in your union, I believe. Also, you named it flag, singular. flags would have been better.
@DavePoo
@DavePoo 3 жыл бұрын
I think the rationalefor that test was that JSR had actually executed some code before it returned, so i was sure that it handn't skipped over any code. I think that test is probably the one that does most instructions in a single test, i don't do that very often. And i didn't test the PC afterwards on that one but i did on all the others. The Carry is bit 0 when i look at it in the debugger, however, i am getting to the point with the emulator where i am going to be running test programs, so if it is wrong then the test program will hopefully catch that. I prefer Flag as i think it reads better in the code "Flag.C = true" I set the flag to true, i don't set the flags to true.
@tmbarral664
@tmbarral664 3 жыл бұрын
@@DavePoo oops / you're absolutely right, the first field in a bitfield union in bit 0. Apologies on that. I made a bad assumption without verifying. Naughty boy. For the Flag, I do agree that it looks and reads better :) It's just a matter of coherence. It should be either StatusFlags Flags or StatusFlag Flag. And again, Dave, cheers to you for this serie. I'm really enjoying it. So much that I shared it with some colleagues ;)
@uwekall6281
@uwekall6281 3 жыл бұрын
Also, testing several opcodes in one test makes it more to a blackbox-test instead of white-box. Which is ok as long as you don't care how the stack is implemented, as Dave explicitly stated.
@jamesExiledLegends
@jamesExiledLegends 3 жыл бұрын
Me screaming at tv, you are looking at ANONYMOUS unions, put PC beside union and not inside. Aaaaaaahhhhhhhhh noooooooooooooo! union PS{ Byte C : 1;......}
@mrdude3957
@mrdude3957 3 жыл бұрын
Your tests everywhere for "StatusFlags NotAffected" does not work. If a Flag is 0 and your test function tries to set a flag to 0 the test will pass, but if a flag is 1 and that same function tries to set it to 0 the test will fail. All your flagtests have this problem
@BryanChance
@BryanChance Жыл бұрын
who are you talking to? LOL
Emulating a CPU in C++ #10 (6502) - Stack Operations
33:33
Dave Poo
Рет қаралды 7 М.
The ONLY REASON To Unit Test
8:26
Theo - t3․gg
Рет қаралды 67 М.
McDonald’s MCNUGGET PURSE?! #shorts
00:11
Lauren Godwin
Рет қаралды 29 МЛН
Суд над Бишимбаевым. 2 мая | ОНЛАЙН
7:14:30
AKIpress news
Рет қаралды 674 М.
白天使和小丑帮助黑天使。#天使 #超人不会飞 #超人夫妇
00:42
Assembly Language Snow Day!  Learn ASM Now!
32:13
Dave's Garage
Рет қаралды 101 М.
Wait, but Who's Debugging the Debugger?!
59:53
Tsoding Daily
Рет қаралды 33 М.
Why You Shouldn't Nest Your Code
8:30
CodeAesthetic
Рет қаралды 2,5 МЛН
Do you even test? (your code with CMake)
12:38
Code for yourself
Рет қаралды 16 М.
My 2 Year Journey of Learning C, in 9 minutes
8:42
VoxelRifts
Рет қаралды 522 М.
Making a Chip-8 Emulator
9:18
VoxelRifts
Рет қаралды 10 М.
Software Testing Explained in 100 Seconds
2:16
Fireship
Рет қаралды 274 М.
Back to Basics: C++ Testing - Amir Kirsh - CppCon 2022
1:02:04
McDonald’s MCNUGGET PURSE?! #shorts
00:11
Lauren Godwin
Рет қаралды 29 МЛН