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.