Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Carry (Wun mo time!)

Reply to topic
Author Message
Consolemu
  • Guest
Reply with quote
Carry (Wun mo time!)
Post Posted: Sat May 06, 2000 10:42 pm
Check it. I kinda understand what was said below but now I would like some code (no direct spoonfeed though). I'll guess the code, you tell me if I'm right or wrong...

Simple ADC immediate interpretation...

case ADC_Im:
PC++;
if((P & CARRY) == CARRY){ A = A + mem[PC] + 1;}
if((P & CARRY) != CARRY){ A = A + mem[PC];}
break;

Simple SBC immediate interpretation...

case SBC_Im:
PC++;
A = A - mem[PC] - ~(P & CARRY);
break;

Simple ASL (shift left) interpretation...

case ASL:
A << 1;
break;

Simple ROL (rotate left) interpretation...
case ROL:
BYTE dummy;
if((P & CARRY) != CARRY){
dummy = A & 0x80;
dummy >>= 8;
A << 1;
A += dummy;
break;
if((P & CARRY) == CARRY){
dummy = A & 0x80;
dummy >>= 8;
A << 1;
A += (P & CARRY);
if((dummy & CARRY) == CARRY){ P = SetBit8(P,CARRY);}
if((dummy & CARRY) != CARRY){ P = ResetBit8(P, CARRY);}
break;


Chris :o)
 
  • Site Admin
  • Joined: 25 Oct 1999
  • Posts: 2029
  • Location: Monterey, California
Reply with quote
Post Posted: Sun May 07, 2000 6:11 am
Quote
> Check it. I kinda understand what was said below but now I would like some code (no direct spoonfeed though). I'll guess the code, you tell me if I'm right or wrong...

> Simple ADC immediate interpretation...

> case ADC_Im:
> PC++;
> if((P & CARRY) == CARRY){ A = A + mem[PC] + 1;}
> if((P & CARRY) != CARRY){ A = A + mem[PC];}
> break;

Conceptual error:
Add with carry does add one extra if the carry flag is set, you've got that right, however, the carry flag itself will be set or clear after ADC completes, depending on whether the result of the operation exceeded the range of the byte (i.e. if the result was greater than 255 and 'wrapped around').
This is useful for adding values across multiple bytes (even 8-bit programs like to count past 65536 sometimes).

Implementation Error:
you'd want to increase the program counter by two, or else the CPU emulator will try to execute the immediate data as an opcode.

Ugly C Error:
Use the += operator or you will have no friends.

Goofy C Error:
You don't need to compare (P & CARRY) with CARRY, if only needs an expression that evalutes to a nonzero value (i.e. whatever CARRY is)) to consider it true.
Also, if the first 'if' succeeds, the second will fail, and if first succeeds, the second will fail. So why test twice? Use else.



//Assume an 'unsigned int temp' at your disposal
if(P & CARRY) temp = A + mem[PC] + 1;
else temp = A + mem[PC];
A = temp & 255; //only the bottom 8 bits.
if(temp & 512) SetBit(P,CARRY);
else ClearBit(P,CARRY);

There's probably a neater way to do it, but I'll leave myself out of that.

However, there's more flags than carry which are affected by the adc instruction, as well as the others listed. If you don't support them your emulator will crash and burn on the most mundane software.

Similar problems plague the rest of the routines. I won't go into detail, though, since as I mentioned I'm less familair with the 6502.
  View user's profile Send private message Visit poster's website
  • Joined: 24 Jun 1999
  • Posts: 1732
  • Location: Paris, France
Reply with quote
Post Posted: Sun May 07, 2000 12:27 pm
Quote
> case ADC_Im:
> PC++;
> if((P & CARRY) == CARRY){ A = A + mem[PC] + 1;}
> if((P & CARRY) != CARRY){ A = A + mem[PC];}
> break;

You could reduce it to:

A += (P & CARRY) ? mem[PC] + 1 : mem[PC];
break;

As Heliphobe mentionned, as you are ANDing P with Carry which I hope is a single bit set, the result is either that bit set or zero.
  View user's profile Send private message Visit poster's website
Cosolemu
  • Guest
Reply with quote
True, true...
Post Posted: Sun May 07, 2000 2:44 pm
Quote
> > Simple ADC immediate interpretation...

> > case ADC_Im:
> > PC++;
> > if((P & CARRY) == CARRY){ A = A + mem[PC] + 1;}
> > if((P & CARRY) != CARRY){ A = A + mem[PC];}
> > break;

> Conceptual error:
> Add with carry does add one extra if the carry flag is set, you've got that right, however, the carry flag itself will be set or clear after ADC completes, depending on whether the result of the operation exceeded the range of the byte (i.e. if the result was greater than 255 and 'wrapped around').
> This is useful for adding values across multiple bytes (even 8-bit programs like to count past 65536 sometimes).

Opps...I forgot to mention that. I think ADC affects carry, negative, and zero.

Quote
> Implementation Error:
> you'd want to increase the program counter by two, or else the CPU emulator will try to execute the immediate data as an opcode.

Last time I did that, you said, "Why are you increasing PC twice? PC usually only increases once." or something like that. But yes, PC should be incremented to the next instruction, not the next byte(s).

Quote
> Ugly C Error:
> Use the += operator or you will have no friends.

I'm sorry. I had a little 'BASIC' attack. I just had to! I'm okay now :o)

Quote
> Goofy C Error:
> You don't need to compare (P & CARRY) with CARRY, if only needs an expression that evalutes to a nonzero value (i.e. whatever CARRY is)) to consider it true.

Then, it isn't really all that goofy. CARRY represents 0x01, which is the LSB (bit0). So, if the AND returns a value that matches the bit that I was checking then it's true. If it's Zero or NOT carry then it's false.

Quote
> Also, if the first 'if' succeeds, the second will fail, and if first succeeds, the second will fail. So why test twice? Use else.

Believe me when I say this. I don't know whether it's my compiler or what but when I did that it wouldn't work all the time and I couldn't figure out why. It's a logical statement but I think it's something about the other bits conflicting or something. I don't know. I just did what worked. Shouldn't use too many extra cycles, would it?

Quote
>
>
> //Assume an 'unsigned int temp' at your disposal
> if(P & CARRY) temp = A + mem[PC] + 1;
> else temp = A + mem[PC];
> A = temp & 255; //only the bottom 8 bits.
> if(temp & 512) SetBit(P,CARRY);
> else ClearBit(P,CARRY);
>

> There's probably a neater way to do it, but I'll leave myself out of that.

Why didn't you test the result of (P & CARRY)? Is the return value automatically checked for a value bigger than 1? I never did that before.

Quote
> However, there's more flags than carry which are affected by the adc instruction, as well as the others listed. If you don't support them your emulator will crash and burn on the most mundane software.

I can't imagine the horror. That's why I'm double-checking and asking you guys so much as to whether I'm doing it right or wrong. I almost feel like saying fuck it and using Marat's core but I'm too deep in this to quit.

Quote
> Similar problems plague the rest of the routines. I won't go into detail, though, since as I mentioned I'm less familair with the 6502.

Instructions that are used with carry are highly needed in most assembly programs so not fully or correctly supporting them can cost major compadibility.

Chris :o)
 
  • Site Admin
  • Joined: 25 Oct 1999
  • Posts: 2029
  • Location: Monterey, California
Reply with quote
Re: True, true...
Post Posted: Sun May 07, 2000 5:23 pm
Quote
> > > Simple ADC immediate interpretation...

> > > case ADC_Im:
> > > PC++;
> > > if((P & CARRY) == CARRY){ A = A + mem[PC] + 1;}
> > > if((P & CARRY) != CARRY){ A = A + mem[PC];}
> > > break;

> > Conceptual error:
> > Add with carry does add one extra if the carry flag is set, you've got that right, however, the carry flag itself will be set or clear after ADC completes, depending on whether the result of the operation exceeded the range of the byte (i.e. if the result was greater than 255 and 'wrapped around').
> > This is useful for adding values across multiple bytes (even 8-bit programs like to count past 65536 sometimes).

> Opps...I forgot to mention that. I think ADC affects carry, negative, and zero.

Also oVerflow.

Quote
> > Implementation Error:
> > you'd want to increase the program counter by two, or else the CPU emulator will try to execute the immediate data as an opcode.

> Last time I did that, you said, "Why are you increasing PC twice? PC usually only increases once." or something like that. But yes, PC should be incremented to the next instruction, not the next byte(s).

I thought you meant 'increase the program counter' as in 'increase the program counter by the number of bytes in the instruction'. Just do that in one step, and do it once, possibly at the end of the instruction.

Quote
> I'm sorry. I had a little 'BASIC' attack. I just had to! I'm okay now :o)

i hope so. jeez.

Quote
> > Goofy C Error:

> Then, it isn't really all that goofy. CARRY represents 0x01, which is the LSB (bit0). So, if the AND returns a value that matches the bit that I was checking then it's true. If it's Zero or NOT carry then it's false.

it works, but there's an unneccessary step in there. You needn't check if the result is equal to CARRY, it's enough that the answer is nonzero.


Quote
> Believe me when I say this. I don't know whether it's my compiler or what but when I did that it wouldn't work all the time and I couldn't figure out why. It's a logical statement but I think it's something about the other bits conflicting or something. I don't know. I just did what worked. Shouldn't use too many extra cycles, would it?

It is a few extra cycles, but the simple fact of the matter is it's probably enough to put some programmers into laughing fits when they see something like that.
Advice: Keep using else, and find out if it's your mistake in implementation, or the compiler is out of whack (if you're using DJGPP or microsoft's compiler, I sincerely doubt they're making a mistake). You don't want your compiler to make you its bitch, especially over something this simple and mundane.
If you still can't figure it out, post it here and we'll dissect it for you.

Quote
> > //Assume an 'unsigned int temp' at your disposal
> > if(P & CARRY) temp = A + mem[PC] + 1;
> > else temp = A + mem[PC];
> > A = temp & 255; //only the bottom 8 bits.
> > if(temp & 512) SetBit(P,CARRY);
> > else ClearBit(P,CARRY);
> > There's probably a neater way to do it, but I'll leave myself out of that.

> Why didn't you test the result of (P & CARRY)? Is the return value automatically checked for a value bigger than 1? I never did that before.

Not even bigger than one: Anything other than zero is considered true.

if(-3) printf("Ja, das stimmt!
); //will print the string
if(4 - 2 - 2) printf("My word is falling apart
"); //no string printed.

BTW, just in case you're wondering, this is guaranteed behavior on all ANSI C compilers (and probably all non-ANSI, rare that they are).

This is important to know because:
-it is convienent shorthand
-it's faster than an explicit comparison. Some compilers may optimize away the difference, but there's no reason to count on that.
-once you get used to it, it's more readable. Really.
-nearly every programmer uses this, so if you're going to be reading other people's source code (hint: if you aren't yet, start. now) you'll need to understand what that means.

other tricks:
You can test is something ISN'T true by using the logical not operator (!) (not to be confused with bitwise not: ~)

if(!0) printf("True, true.
"); //0 is false, but ! inverts the 'falseness' so the string is printed
if(!(3-2)) printf("Not in a million years
"); //the ! invert makes the whole (3-2) expression FALSE, when it would have been TRUE. The string doesn't print.


you can check if a pointer is NULL this way:

mem = malloc(800000000); //malloc returns NULL on failure.
if(mem) printf("Got the memory
"); //anythign but NULL is success.
or you could also do:
if(!mem) printf("Error: buy more RAM
");

quick warning: Don't count on this behavior with floating point values, due to rounding errors floats an doubles are often not quite what you expect them to be.

Quote
> I can't imagine the horror. That's why I'm double-checking and asking you guys so much as to whether I'm doing it right or wrong. I almost feel like saying fuck it and using Marat's core but I'm too deep in this to quit.

This project will put some hair on your chest, guranteed.
Worse yet, I didn't realize (or remember) until just last night that the 6502 ONLY has adc and sbc instructions, there's no way to add and subtract without the carry affecting the output. Harhar. z80 rules*.
(* but then the 6502 seems to have quicker per-instruction execution times. so it could break either way).

Quote
> Instructions that are used with carry are highly needed in most assembly programs so not fully or correctly supporting them can cost major compadibility.

no doubt.
  View user's profile Send private message Visit poster's website
Johannes
  • Guest
Reply with quote
Post Posted: Tue May 09, 2000 8:57 am
Quote
> You could reduce it to:

> A += (P & CARRY) ? mem[PC] + 1 : mem[PC];
> break;

Why not just use...
A += mem[PC] + (P & CARRY);
...assuming that CARRY==0x01, which is the case on the 6502.
 
  • Joined: 24 Jun 1999
  • Posts: 1732
  • Location: Paris, France
Reply with quote
Post Posted: Tue May 09, 2000 12:08 pm
Quote
>> You could reduce it to:
>> A += (P & CARRY) ? mem[PC] + 1 : mem[PC];
>> break;
> Why not just use...
> A += mem[PC] + (P & CARRY);
> ...assuming that CARRY==0x01, which is the case on the 6502.

First, that trick is really ugly :)
But the real reason is that i'm not sure if an usual compiler will optimize the code knowing the addition can be of +0
  View user's profile Send private message Visit poster's website
Johannes
  • Guest
Reply with quote
Post Posted: Wed May 10, 2000 10:43 am
Quote
> > Why not just use...
> > A += mem[PC] + (P & CARRY);
> > ...assuming that CARRY==0x01, which is the case on the 6502.

> First, that trick is really ugly :)
> But the real reason is that i'm not sure if an usual compiler will optimize the code knowing the addition can be of +0

It's not ugly! It's beautiful! :)
I'm going to investigate this further as soon as my computer decides to start working again :
 
Reply to topic



Back to the top of this page

Back to SMS Power!