Submind YouTube summaries
Thumbnail for How to Code a 6502 Emulator in Python Part 13

How to Code a 6502 Emulator in Python Part 13

Watch on YouTube

Video summary

In this episode of the 6502 emulator series, the creator focuses on implementing four specific bit manipulation instructions: Arithmetic Shift Left (ASL), Logical Shift Right (LSR), Rotate Left (ROL), and Rotate Right (ROR). The video begins by explaining the fundamental logic behind these operations, noting that ASL shifts bits left while inserting a zero into the rightmost position and moving the original leftmost bit into the carry flag. Conversely, LSR shifts bits right with a zero entering from the left and the original rightmost bit moving to the carry. The Rotate instructions follow a similar pattern but differ by feeding the current value of the carry flag back into the opposite end of the register instead of inserting a zero. The implementation process involves handling different addressing modes, specifically introducing the accumulator mode which requires modifying how values are retrieved and stored. A significant portion of the coding session is dedicated to debugging logic errors, such as forgetting to update the accumulator after a shift operation or failing to correctly calculate the carry flag when the leftmost bit is set. The creator demonstrates the iterative nature of live coding, where initial tests reveal missing steps like wrapping values back into memory or updating the carry flag state, which are then corrected through trial and error until the binary math behaves as expected for edge cases like shifting from 128 down to zero. Once the basic shift functions are stable, the creator moves on to the more complex rotate instructions, which require checking the existing carry bit before performing the shift and then using bitwise OR operations to reintroduce that carry value into the register if necessary. The video concludes with successful testing of all four instructions, verifying that they correctly handle data rotation between the accumulator and the carry flag. The creator expresses satisfaction with completing these specific tasks for the day and directs viewers to an external resource for more detailed graphical explanations of binary operations before signing off on another successful installment of the series.
Read the full video transcript
Okay, welcome to 6502 emulator in Python part 13. We are definitely getting up there. Is that lucky 13 or is it unlucky 13? Let's hope it's lucky. Um, today we're going to be implementing shift and rotate. We're doing the instructions. Uh, arithmetic shift left. Uh, I think it's logical shift right. Uh, rotate left and rotate right. So, let me just kind of explain what they do real quick. Um so arith arithmetic shift left takes the bits of the of the the value and shifts them to the left. Um so if there is so on the far right bit which is 01 you just put a zero in. Uh and then if there's a one in the far left bit that goes into the carry. So carry gets a one uh true whatever. Um now when you do it right it goes the opposite direction. you put a zero into the leftmost bit and you put whatever's in the like rightmost bit into carry. So it's that's it. It's pretty straightforward. Uh and then for rotate left and rotate right, it's very similar except instead of a zero going into the rightmost bit for rotate left, it's whatever is in the carry. So the carry goes into the the rightmost bit and then comes out of the leftmost bit. the and then to the right it is the opposite. So we're going to go ahead and implement that. Um just a reminder this is live coding. I haven't implemented this before. Going to try and figure it out and see how it goes. Now again like last time I did go ahead and make some very simple testing code. So we're going to load uh value 01 into the accumulator and then we're going to shift the accumulator to the left. So if it's one, we shift to the left. This has the This has the, you know, the I don't know the outcome of multiplying by two. It's like, yeah, it's like multiplying by 10 decimal, but we're doing it in binary. So, let's go ahead and implement that. So, we're going to go to our trusty 6502.org here. We're going to be implementing just just the accumulator one. We'll we'll worry about the other ones later. Um, so accumulator as SLA and is hex0A. Let's go ahead and give that a shot. Um, so let's come down to here and copy. Okay, so we said it was I believe 0 A and it is ASL arithmetic shift left and the mode is accumulator and do we have an accumulator mode? Oh my gosh, we don't have an accumulator mode. That's very exciting. We're have to add that. So mode accumulator, that's something we haven't seen before. Um, so it is accumulator mode. Fascinating. Um, yeah. Interesting. So then that means we got to go down to our get location by mode. So in this case, the location is going to be the accumulator. Um, h how's that going to work? Let me let me give it some thought here. Um, let's skip this part. because it'll return zero by default. Okay, I can live with that. Um, so let's go there. Let's go and just code it. What the heck? And I did notice there are some mistakes here that we from previous stuff. Later I'll go through and try and fix everything that's that's wrong. Um, so defl mode. And I think what we're going to have to do here is [sighs] H. Got it. Um, no, I don't got it. I don't have this one. So, I don't think we've had we've seen the accumulator mode before. All right. I'm going to give this a shot. Uh, so I'm going to do if mode equals mode accumul accumulator. Got it? Uh, value equals self. A. So if we're in accumulator mode means the value that we're doing this on comes from the accumulator. Otherwise, else we're just going to do what we've done every other time is we're going to get it based on the memory location. So, I think this will work. Um, and I think that's going to do it. I'm I'm okay with that. Okay. So, now so now we got the value from the accumulator if it's in accumulator mode. We've got the uh location of the value from the memory if it's a different mode. So, I think that's correct. So now we need to shift left. Okay. Now the way we do this in Python is we would do value equals value and we do two of those and one. And what the one means is we want to shift one bit to the left. Okay. Now the only thing we haven't done here yet is if I actually let's go ahead and run this. Let's test this to see if it's working. Um there is a missing part. So, uh, so I'm going to go ahead and throw in a debug here real quick. Um, so CPU.push 0x42. And that is my custom debug command. And I'm going to go ahead and just throw another one at the end here so it stops. All right, let's try that and run. And of course, um, where's that? Where's that error at? Mode accumulator line 134. It's way up here. It's fun watching me scroll, I'm sure. 134 mode. Jeez. Oh my gosh. Um, and that is one. It's one bite. So, let's go back. You guys probably noticed that early on. So, let's try it again. cumulator. I forgot. Where did I forget to put that in? Increments. Ah, yeah. And cumul equals auto. It's funny. It's only been a few days since I was working on this, but I've already forgotten stuff. It's probably a good lesson about commenting your code there. Okay, fantastic. So, we've loaded one into the accumulator and we're [snorts] going to shift the bits to the left by one. And that should double it to two. And it did not because I forgot. Uh I swear to God. Um so I shifted the value but then I didn't put it back into the accumulator. Um so yeah. So uh put the value value into accumulator accumul. So same thing we're going to do. So if mode equals mode accumulator then we just say self a equals value. Okay. else. Um, we're going to do memory uh self.mmemory self.mmemory um location equals value. And that should do it. Let's go back test it. Testing is a lot of fun. It's important. All right. So, one and we've got two and then we're not implemented. That's I'm pretty confident that's going to work. But let's go ahead and just go ahead just try it here a couple. So we shift it once. That goes to 2 4 8 16 32 64 128. So let's see if we get 128 out of this, which I think. Okay, so one and then we're going to shift it all those times and it gives us 128, which is awesome. Okay. Now, the thing that we haven't dealt with, of course, is now that we're at 128, which is uh which is one 1 0 0 0. Since this bit is a one, that's got to go into the carry. So, we got to do So, let's try to figure out how we want to do that. So, Um, so before we before we shift it, we got to check and see check the leftmost bit. Okay, so let's see if uh value I'm going to do and 128 equals 128. And I'll explain that in just a second. 28 equals 128. self.cry equals true. Okay. So we we saw this earlier. I did that in a previous video. But basically what I'm saying here, go back to here. So I deleted anyway. So let's say if we got 128 0 0. So I do an and oops. And it doesn't matter what I do here. So let's actually let's say that the value is you know something else. Doesn't matter what it is. All we're concerned about is this particular bit. So that was one more. So if I do 1 0 0 0 0 that's 128. I could have done it in binary but let's probably be easier. So 1 and 1 is one. And then all these are going to be zero cuz that's a zero. So this is going to be the value of 128. So that tells us that this bit was set for us. So if that bit is set, there's probably another way to do it. I just don't know it. Um, so if that value and 128 equals 128, then the self carry is true. So let's go ahead and run our testing code again. And I'm not sure if I added enough, though. Let's find out. So one, okay, we're at 128. We got to add one more. And that should push us back to zero with the carry flag set. Okay. One. And it should go to zero. With carry flag set, which it did not do, right? Because uh I did not wrap it. Um, still that shouldn't matter. I I know what's wrong. Well, do I know what's wrong? Not really. Um, value equals value. And then we of course have to wrap the value. Value equals wrap value. Okay. So, that kind of messed things up. Let's try it again. Okay. self.wrap. Yes, I did. [sighs] Wrap. Now, once we get one of these done, it should be pretty straightforward to get the rest of them done. But, uh, yeah, I said this is the process. Okay, one. This should a should go to zero and carry should be one. Oh, for freaking heaven's sakes. Um, self. Let's try it again. [snorts] live coding. Anything can go wrong zero and stupid carry is not set. I'm going to go back to my code and figure out why it is not set value and 128 128. >> [sighs] >> Oh, selfc. Okay, Java, you wouldn't be able to do that. Python. Okay, we're back to zero and the carry flag is set. I'm satisfied pretty more or less. Um, so let's go ahead and just bring that back down. And I could also, you know, I could just load uh 128 here. I think that's 16. No, 89. I think it's 80. So if we load 80 here, we just test it this way, too. That gives us 128. And then we're going to shift left, which gives us zero and one carried. Awesome sauce. Let us go back. So that was ASL and now we're going to do LSR logical shift left shift right. There we go. So it's same thing. It says shift all bits right one position. Zero is shifted into bit 7 and the original zero is carry shifted to the carry. So we're going to do the same thing. We're going to do accumulator mode which is 4 A. So remember that. It should be easier this time because we're just going to copy and paste and make some changes. So, [snorts] copy and we've got 4A and this is going to be LSR. LSR and this is mode accumulator. Let's go down to ASL here. And I'm I'm just going to copy this because again, I'm reasonably confident this is correct, but I'm not sure. I didn't test the other modes, but we'll go with it. Um, LSSR. And that part's the same. Okay. Now, this is this is going to be different because we're going to be shifting right. So, that should be value one. And then we're going to shift everything to the right by one. And that should do it kind of. Let's give it a shot here. System and LSR was what is it? 4 A, I believe. 4 A. All right. So, we got 80, which is 128. So, if we shift right, that gives us 64 because we're going to go in half now. Oops. Okay, we got 128 and next should give us 64. Okay, so I'm pretty confident that's working. U so let's go ahead and do 01 to make sure that the carry part works. Okay, so let's compile. Let's run it. So we got one. We're going to shift to the right. That takes it to zero because there's a one here that gets shifted down to the carry. And we should see zero and one. Pretty sweet. Okay, so that brings us to u our last two which are very very similar. Let me go back to the concepts. So you can see you know we shifted left and zero went we're shifting left zero went into the right. Um whatever is in the left most went to carry and then we reverse that. And now what we're going to do is we're going to do both times instead of zero we're going to bring in the carry. So, we're just going to add a little bit of code to do that. [sighs] H, how are we going to do that? Uh, so we got to find the command, which is R O L R O L. And we're going to do 2 A. Again, we're just going to do accumulator mode just to keep it simple. And 2 A. So to a 2 A and that is going to be R O L accumulator. So let's go ahead and just we're just going to copy ASL. It's very very similar. That's what I always tell my students. You get something working, you know, try and copy and paste where necessary. Um, so this going to be R O L. And we want to check the leftmost bit. So that part's the same, but we also need to check carry. Okay. So Okay. So the actually the timing is really important on this. So we got to check the original carry. All right. So I'm just going to do it here just cuz it that's without the least amount of rearranging. So if cell so check carry bit. So if if carry h okay self c equals true. So if it's set um H spell temp that's not the best thing about temp equals one. Got it. So temp equals 1. So that's the same as like 0 0 0 1 in binary. So we're going to do one. And what we'll do is after we wrap the value um we're going to add the carry carry. So we'll say value equals value or temp. Okay. So what that gives us because you know once we rotate once we shift it left no matter what the values are we know there's going to be a zero. So let's say 0 1 0 1 0 1 0 0. Once we shift left we know this is going to be a zero. So what we're going to do is we're going to do an or. [clears throat] So we're do the value or one. So that gives us in this case 0 1 or 0 is 1. 0 or 0 0 1 or 0 0 1 0. And this will flip that bit to one for us. If and it's only going to happen if the carry is set. Okay. And then the leftmost bit. Oh, here we got to do else self. C equals false. Have to do that in the other one. That's a good question. I don't know if I have to do that in the other one. That might be something a conversation for another day. But uh if the leftmost bit does it flip it is the question. says it's probably here. Maybe I do need to do that. So I may have to do this for all of them. This is something I'm not sure about. Um check the leftmost bit true. Else selfc equals false. Probably going to have to do that again. It's something I'll have to check. Um but selfc equals false. But let's just go ahead and assume that is the case for now because I think that's how it works. Um, so that was rotate left. Now we got to test it. Um, which was again, what's that? A Z. And we're going to actually need set carry as well. So that's 38 and 2 A. Okay. All right. Let's try it. So, R O L 2 A. All right. So, let's just test that. Make sure it's still working. So, we got one and we're going to rotate it left. That'll give us two. There's nothing in the carry, so it should just give us two. All right. So, that's pretty good. So, let's go ahead and do set carry. So, I'm going do CPU.push push uh 0x I think it was 38 and sec. So what should happen is when we run this, so we have one in the carry. This should shift to two. The carry gets added to it. That should give us 2 + 1, which is three. And then the carry should become zero because that's a zero. Amazing. Okay, it's doing what it's supposed to do. As far as I know. As far as I know, I'm going to You know what? I'm going to call that a win. All right. And then we need to do the final one, which is uh rotate right. Um so we're going to go ahead back to here. That is 6A. So again, I know we got to deal with modes and things, but uh one day at a time. uh 6 A R O R and 6 A. So let's go back to here. 6 6 A. So let's go ahead and comment that out. We don't need to set the carry here. So one. So let's go ahead and run this. I am not very bright. Um R got some good feedback uh you know from from viewers like some stuff I've messed up which is nice. Uh just some other ways of doing things and so I got some pretty good advice and I was also said don't they're not they're not commands they're instructions. So thank you for whoever came up with that. Um, so we're going to rotate right. So now we got to do check the carry bit. So now we're coming from the left side. So temp is going to be 128 because it's the last bit. We're going to check the rightmost bit, right most bit. And that's going to be one. And we're going to shift the values to the right by one bit. And I think everything else should be the same. So let's try that again. Okay, we got a one again. We're budge. Sorry, I didn't switch from the coding concept screen. I'm not redoing that. I'm sorry. You can look at the code later. I don't know how long it's been there, but it's probably been there for a while. Um I I'll go back and show you in a second. So, um, we've got one here in the accumulator. We're going to rotate that, right? And that should go into the carry. So, let's, uh, see what happens there. And that did go to the carry. I'm pretty happy with that. Uh, let me just go back and show you the code. I hate when I do that. Um, so rotate left. So, what I did was since we're rotating left, we first have to check the carry bit. I apologize for the last five minutes. um we check the carry bit and then um if it's true we set temp to one. Then we check the value of the leftmost bit just like we did earlier. This is not this is not different from uh a ASL. So do the exact same thing there. Then we shift it to the left. We wrap it and then we do the ore with the carry value. Okay, the temp value. So, uh, let me just probably didn't have that on the screen when I was doing it. So, 0 0 0. So, 0 0 0. So, let's say it's zero. If we do this, is this is always going to be a zero because we shifted left. So, we're if it's uh if there's a one in the carry, we do an or and that will flip this bit to one. That's that's it. [snorts] I'm not going to go through the whole thing again. Um, I don't think there's going to be a lot of people watching this, but check out the code. It's pretty obvious, pretty straightforward, I should say. Um, and then yeah, so RO L R O R. So, let's go ahead and test R O R to see if that is doing what it's supposed to do. And R O I think I did. That was dumb. Um, C R O R. And is that six? 68 is 6A. Okay, good. All right. So, I think we're pretty happy there. Um, now the only thing I want to do here is I'm going to set the carry. Okay. And I'm going to run this. Okay. We got one and we have a carry. So the one is going to go back to the carry, which is what we want. And then this carry is going to go onto the left side, which should give us 128. And yeah, so that's that's pretty good. Um, let's just test one more quick value. Let's make this a zero. So going to run this. So we got zero here. We got a carry. So the zero is going to go into the carry. The carry is going to go into the left side, which gives us 128. Yosh. All righty. And just just because I'm having fun with this now, uh I'm going to try two. Okay. So, the two will be shifted over one bit. That gives us one. Um there's a zero there. That'll go into the carry. And the carry will come to the end. That gives us 128. So, 128 + 1 is 129. And there we go. So, I'm happy with that. I'm pretty confident that that is what we wanted. Again, I do apologize for the Yeah, I have the code on the screen. Um, but check it out. It's reasonably well commented. And, uh, as long as you understand as long as you understand how and works with binary numbers and if you don't, maybe this isn't the video for you. Um, yeah, I think that's that's it. I think we're going to call that a day. Uh, accomplish what I set out to do today. So, I'll call it a win. So again, uh we implemented uh arithmetic shift left, uh logical shift right and rotate left and rotate right. If you need a little more, if you want a little more information about how they work, um you might want to check out this uh mass work uh website here. They do have quite a bit more little bit more detail than what we have here uh with this. This explains it kind of in English pretty well. this kind of has a bit more extra information that maybe is a bit more graphical for depending on depending on the thing that we're looking at. So, uh yeah, that's it. Uh thanks for watching and keep on going.