This is where the BIN Hackers and definition junkies discuss the inner workings of the EEC code and hardware. General tuning questions do not go here. Only technical/hardware-specific/code questions and discussions belong here.

Moderators: cgrey8, EDS50, Jon 94GT, 2Shaker

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

CMP and the carry flag

Post by TripleBlackVert » Thu Jun 10, 2010 10:36 am

Looking to collect thoughts about the CMP command with respect to the CARRY flag.

Here is the problem:

According to the 27006102.pdf reference for the 8096 processor, the CMP command has 2 operands, D and A, where D is a location in the register file (addresses 00 - FF) and A refers to any memory location according to the addressing mode. CMP is defined as "perform D - A and set the flags accordingly".

Later the flags are described: "C is the Carry flag. It is set if a carry was generated by the prior operation".

Here is some code from the A9L initialization routine:

Code: Select all

 2032 FA            61 L2032 di
 2033 FF            62       nop
 2034 110C          63       clrb  HSI_Data_Mask
 2036               64 ;* Save  REG$2A
 2036 B02A12        65       ldb   REG_12,REG_2A
 2039               66 ;* Clear locations from  $0016  through  $0489
 2039 A1160014      67       ld    REG_14,#$0016
 203D C61500        68 L203D stb   Zero,[REG_14]+
 2040 1704          69       incb  Watchdog_Timer
 2042 898A0414      70       cmp   REG_14,#$048A
 2046 D3F5          71       jnc   L203D
 2048               73 ;*  then set bit 0  in  $EF
 2048 51121414      74       andb  REG_14,REG_12,#$60
The intent at address 2042 is that if the value stored in REG_14 is less than $048A, then jump back to 203D. Since REG_14 starts wtih $0016, it should jump back to 203D many times before falling through to 2048.

The first time the CMP executes, REG_14 (D) is $0017 and the other value (A) is #048A. The code expects the CMP to clear the CARRY flag, and subsequent JNC will direct the processor back to 203D.

But the CMP should compute 0017 - 048A, which should result in the CARRY flag being set. In this case, CARRY indicates that a borrow occurred, or in other words, that A > D.

There is a Wikipedia article about the carry flag that talks about some implementations using an identity that (D - A) is the same as (D + (not A) + 1) and setting the CARRY flag according to that addition. In this case, ($0017 + (not $048A) + 1) should not result in CARRY.

I am starting to think that the 8096 must use the (D - A) is the same as (D + (not A) + 1) approach, but I can't be sure.

The same Wikipedia page says that INTEL's x86 processors use the borrow bit approach which would set the CARRY flag.

Anyone know for sure?
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

User avatar
cgrey8
Administrator
Posts: 11269
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: CMP and the carry flag

Post by cgrey8 » Thu Jun 10, 2010 11:15 am

I'm not the expert, but it sounds to me like perhaps the comment is wrong, and that the code is actually clearing from 0x0016-0x048A. Once REG_14 hits 0x048B, then there'll be a carry and it'll break out of the loop. How confident are you that 0x0489 is where the code really is stopping?

Although I have to admit, stopping on an odd boundary is unusual unless you see code below this using 0x048B in some way that would automatically clear it before it is read/used.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, FMS Explorer (GT40p) headers, aftermarket T5 'Z-Spec', GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Thu Jun 10, 2010 11:52 am

the question here isn't so much where it should stop, but how the carry flag is set by the CMP command. in this case, REG_14 is "D" and $048A is "A".

if CMP sets the CARRY flag when REG_14 < $048A, then it will exit the loop the first time through and only clear 1 address. this cannot be the desired behavior, so the CARRY flag must be expected to be NOT set when REG_14 < $048A.

one approach to subtracting, the "borrow bit" approach computes D - A directly and sets CARRY to indicate if a borrow was needed.

the other approach, the "identity" approach, actually does this to subtract A from D: D + (not A) + 1 and sets CARRY if the result is bigger than $FFFF.

further analysis indicates that the 2 approaches result in exactly opposite values for the CARRY flag:

Code: Select all

condition   (A - D)     (D + (not A) + 1)
----------  ----------  ----------------------
D > A       C clear     C set
D = A       C clear     C set
D < A       C set       C clear
the more i look at it, the more i suspect this processor must use the "identity" approach to subtracting.
Last edited by TripleBlackVert on Thu Jun 10, 2010 12:06 pm, edited 1 time in total.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

sailorbob
BIN Hacker
Posts: 1760
Joined: Tue Jul 12, 2005 6:10 am

Re: CMP and the carry flag

Post by sailorbob » Thu Jun 10, 2010 11:55 am

The CMP AX,BX instruction subtracts BX from AX and the carry is set before operation (think of it acting like a 'borrow' rather than a 'carry' in this instance).

That part of the code clears the ram from 0x0016 to 0x048A.

Edit: 14/06/10 - Corrected 0x0489 to 0x048A
Last edited by sailorbob on Mon Jun 14, 2010 9:51 am, edited 1 time in total.

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Thu Jun 10, 2010 12:14 pm

sailorbob wrote:The CMP AX,BX instruction subtracts BX from AX and the carry is set before operation (think of it acting like a 'borrow' rather than a 'carry' in this instance).

That part of the code clears the ram from 0x0016 to 0x0489.
exactly what do you mean by "the carry is set before the operation"?

do you mean the INCB Watchdog_Timer changes the value of the carry flag and the CMP does not?

it seems to me the CMP would result in CARRY being either set or clear, depending on the relationship between the values being compared.

if BX is larger than AX, should the carry flag be set or cleared by CMP AX, BX?

i'm trying to understand it at this level because i am working on a simulator for the EEC and want to be able to simulate actually running the code.
Last edited by TripleBlackVert on Thu Jun 10, 2010 12:17 pm, edited 1 time in total.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

sailorbob
BIN Hacker
Posts: 1760
Joined: Tue Jul 12, 2005 6:10 am

Re: CMP and the carry flag

Post by sailorbob » Thu Jun 10, 2010 12:16 pm

The carry is set before the subtraction is done.

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Thu Jun 10, 2010 12:21 pm

sorry to be a pain ... i'm trying to understand it at this level because i am working on a simulator for the EEC and want to be able to simulate actually running the code.

does CMP set it based on the relationship, and then do the subtraction to determine Z and N, but C does not change as a result of the subtraction?
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

sailorbob
BIN Hacker
Posts: 1760
Joined: Tue Jul 12, 2005 6:10 am

Re: CMP and the carry flag

Post by sailorbob » Thu Jun 10, 2010 12:42 pm

The carry is set first. The subtraction is done next. If AX >= BX then the carry remains set. If AX < BX then the carry is cleared,

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Thu Jun 10, 2010 2:22 pm

ok. this code seems to be consistent with way the assembler logic is written. thanks!

it still seems counter-intuitive though, because if AX > BX, carry is set, indicating that a borrow was necessary, when it wasn't

Code: Select all

struct 
{
	bool Z; // true if result is ZERO
	bool C; // true if CARRY is set
	bool N; // true if result is NEGATIVE
} flags;
per the logic from sailorbob ...

Code: Select all

void CMP(WORD AX_D, WORD BX_A)
{
	// CMP is defined as D - A, or AX - BX in sailorbob's terminology

	long res = (long)AX_D - (long)BX_A;

	flags.Z = (res == 0);
	flags.C = ( AX_D >= BX_A );
	flags.N = (res < 0);
}
as it turns out, the "identity" version of the subtraction results in the same flags ...

Code: Select all

void CMP2(WORD AX_D, WORD BX_A) 
{
	BX_A = ~BX_A;
	DWORD res_w = AX_D + BX_A + 1;
	WORD res = (WORD)(res_w & 0x0000FFFF);

	flags.Z = ( res == 0 );
	flags.C = ( (res_w & 0xFFFF0000) != 0 );
	flags.N = ( (res & 0x8000) == 0x8000 );
}
Last edited by TripleBlackVert on Fri Jun 11, 2010 9:21 am, edited 1 time in total.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

dualdj1
Tuning Addict
Posts: 627
Joined: Thu Feb 19, 2009 3:04 pm
Location: East Peoria, IL
Contact:

Re: CMP and the carry flag

Post by dualdj1 » Thu Jun 10, 2010 3:17 pm

very interesting. I'd be very curious to see your code sometime, if you were so inclined to share it :)
1978 Mustang II King Cobra
89 5.0HO, Stock Short Block, Edelbrock 4bbl aluminum intake, Holley 650 double pumper, MSD 6AL, Ford F303 cam, 1.7:1 Crane Roller Rockers, Pocket Ported stock heads, Hedman Long Tube Headers
5 spd Manual
Full roll cage, 9" full floater w/Currie trac lock/373 gears, RCI Fuel Cell
Project Page: http://www.brandttuning.com/projects.htm

mpaton
BIN Hacker
Posts: 381
Joined: Mon Jun 23, 2008 1:39 pm

Re: CMP and the carry flag

Post by mpaton » Mon Jun 14, 2010 9:36 am

You understand that this "identity" is nothing more mysterious than saying that to negate a 2's complement number, take the 1's complement and add one. So it isn't a different method of doing it, it's more like a different way of visualizing it.


I believe the comment is wrong, and that location 0x048A is zeroed. The carry flag will not be set until 048B is compared to 048A and that doesn't happen until after 0481 is zeroed.

Your code below is fine as pseudo code, but you MAY (no promises) have to be more careful and try some examples to check that it is correct code. You know that standard C causes all arithmetic involving in lengths or shorter to happen in signed int. This MAY cause conversions between signed and unsigned that you don't expect. I think you said you're using MS C, and those guys feel free to write their own standards, so anything may happen.

When you wrote function CMP2, you refined the code a little, and I believe your code for flags.N is wrong. It's correct in CMP. Correct in this case means like the 8096, and I believe, but haven't yet proven, is how the 8061 and 8096 work.

Your code for flags.C is probably incorrect (I can't see your user defined types) as the Carry should be set as the result of an unsigned comparison.

I think this is a fine project, and you'll learn a lot doing it. However you're probably realizing about now, that as a way of producing an assembly listing that has all the code separated from all the data, this is a harder way.

And when you get to that error free listing, you then have to work out what data is where, and what all the functions do. The end product you want is really not an error free listing; that's pretty easy to generate even with the current disassemblers. What you want to generate is something that reads like a strategy document. That's a LOT harder.

But, great project, enjoy yourself with it. PM me with any questions. If you weren't already planning on it, I'd suggest you build in a simple command line debugger interface to your simulator so you can stop execution at any point and examine memory locations.

Michael


TripleBlackVert wrote:ok. this code seems to be consistent with way the assembler logic is written. thanks!

it still seems counter-intuitive though, because if AX > BX, carry is set, indicating that a borrow was necessary, when it wasn't

Code: Select all

struct 
{
	bool Z; // true if result is ZERO
	bool C; // true if CARRY is set
	bool N; // true if result is NEGATIVE
} flags;
per the logic from sailorbob ...

Code: Select all

void CMP(WORD AX_D, WORD BX_A)
{
	// CMP is defined as D - A, or AX - BX in sailorbob's terminology

	long res = (long)AX_D - (long)BX_A;

	flags.Z = (res == 0);
	flags.C = ( AX_D >= BX_A );
	flags.N = (res < 0);
}
as it turns out, the "identity" version of the subtraction results in the same flags ...

Code: Select all

void CMP2(WORD AX_D, WORD BX_A) 
{
	BX_A = ~BX_A;
	DWORD res_w = AX_D + BX_A + 1;
	WORD res = (WORD)(res_w & 0x0000FFFF);

	flags.Z = ( res == 0 );
	flags.C = ( (res_w & 0xFFFF0000) != 0 );
	flags.N = ( (res & 0x8000) == 0x8000 );
}

wa_4x4builder
Regular
Posts: 106
Joined: Wed Mar 30, 2005 12:37 pm
Location: Seattle, Washington

Re: CMP and the carry flag

Post by wa_4x4builder » Mon Jun 14, 2010 11:39 am

mpaton wrote:If you weren't already planning on it, I'd suggest you build in a simple command line debugger interface to your simulator so you can stop execution at any point and examine memory locations.
You are right- creating one of these critters is not the easiest task... Sorry to come late to this party (not trying to steal TBV's thunder in any way), but I've written *exactly* what you are attempting to create. And, again, you are correct, it took a ton of work and a lot of head scratching to get the instruction set to function properly. I used this project as a way to learn some new technologies and to see if it could be done. I'm in the middle of upgrading it to a new user interface which, hopefully, will add to the overall usefulness of the tool.

It's not fully functional, however, I need to hang the 8061 I/O system onto it (it is rudimentary at best right now) and build a number of other UI features into it. But, at its core, it's working great. After the updates/upgrades/feature additions, I'll let some folks give it a whirl and tell me what they think, if anyone wants to. I didn't think there was much interest in such a tool, but after reading these threads, I guess there's more interest than I thought.

I also attached a partial disassembly of the A9L code for comparison purposes. I say it's partial because I haven't commented all the code nor has all of it been exectuted due to various reasons. So, I can't be *positively* sure that's everything is correct. But, it's a start and should work well for TBV's comparisions.

TBV, please don't let my work stop you in any way. The more folks working on this type of thing, the better off the community is. I'm sure you'll have a great time figuring all this stuff out- and a lot of late nights! I'm not sure I can help as you seem to have a pretty good grasp of what's going on, but if you find you have a question, please don't hesitate to ask.

Chris
Attachments
6-14-10 A9L.zip
Partial A9L disassembly.
(141.83 KiB) Downloaded 801 times
EEC Emualtor Debugging.jpg
Screen capture of a functioning EEC IV emulator.
(145.09 KiB) Downloaded 4795 times
'93 EDIS 5.0L with A9L installed into a '77 Bronco.

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Mon Jun 14, 2010 11:56 am

thanks michael. this approach was originally suggested by cgrey as a way to address the issue of discovering more thoroughly the places where the FORD programmers put paramters for functions directly after the call instructions. i took it to the next level by deciding to actually create a simulator to be able to really run the code.

this project has multiple goals, one of which is to end up with a clean, commented disassembly. the other goals are:

- to learn c# in the process. after i get it worked out in c++, i plan to migrate it to c#
- to be able to simulate a run based on a real life datalog taken
- to be able to assemble code correctly, initially the disassemby back into the original binary
- to create a higher level language that can result in assembly or machine code for this processor
- - this might be like FORTH or a subset of C, but it will be a pretty simple language
- eventually, to be able to write a completely new engine management system using this processor as the hardware

re the first goal ... i have been a c++ developer for 20+ years, so that is my main strength. i don't want to be struggling with the language and the logic both at the same time, or i will more likely give up. after i get the logic figured out and working, i can focus on the language issues.

and yes, i am working towards an interactive enviromnent where i can put breakpoints in and look at things while running. i find it very interesting.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

User avatar
cgrey8
Administrator
Posts: 11269
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: CMP and the carry flag

Post by cgrey8 » Mon Jun 14, 2010 12:02 pm

I'm just glad more people are interested in doing this kind of work. I wanted to do it, but I found that trying to do it in Java was just going to be more work than it was worth for me. If I were a seasoned C++ developer, that might have been different. What I program at my job is straight C, and that's not a good language for trying to create, what should be a very UI-intensive application from the very beginning. Add to that, UI has NEVER been one of my strong points. I do much better with processing and algorithms than I do with displays.

It's encouraging though to see screencaps of some programs people are working on where people are making progress in this area.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, FMS Explorer (GT40p) headers, aftermarket T5 'Z-Spec', GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Mon Jun 14, 2010 12:11 pm

dang 4x4, and here i was hoping i was onto something that hadn't been done yet.

this is still an interesting project and i intend to continue moving forward with it. but it looks like i have some catching up to do!

it's all good.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

User avatar
cgrey8
Administrator
Posts: 11269
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: CMP and the carry flag

Post by cgrey8 » Mon Jun 14, 2010 12:29 pm

If you guys can work together, there's a possibility that the two of you could work on a core component that is common between the two efforts. I don't know how difficult that'd be for either of you to do at this point, but it is a shame to think that the two of you could be working in concert instead of both inventing your version of the wheel.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, FMS Explorer (GT40p) headers, aftermarket T5 'Z-Spec', GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

dualdj1
Tuning Addict
Posts: 627
Joined: Thu Feb 19, 2009 3:04 pm
Location: East Peoria, IL
Contact:

Re: CMP and the carry flag

Post by dualdj1 » Mon Jun 14, 2010 1:37 pm

TBV, If you need any help on the C# side once you get to that point, just let me know. I'm no expert by any means, but I've been using it exclusively for ASP and WinForms projects for the last 3-4 years now, and have learned a good deal of tricks and such from the main program I maintain/develop. It's a good language to get into, and fairly similar to C++ with some good added libraries.
1978 Mustang II King Cobra
89 5.0HO, Stock Short Block, Edelbrock 4bbl aluminum intake, Holley 650 double pumper, MSD 6AL, Ford F303 cam, 1.7:1 Crane Roller Rockers, Pocket Ported stock heads, Hedman Long Tube Headers
5 spd Manual
Full roll cage, 9" full floater w/Currie trac lock/373 gears, RCI Fuel Cell
Project Page: http://www.brandttuning.com/projects.htm

mpaton
BIN Hacker
Posts: 381
Joined: Mon Jun 23, 2008 1:39 pm

Re: CMP and the carry flag

Post by mpaton » Mon Jun 14, 2010 2:11 pm

TripleBlackVert wrote:thanks michael. this approach was originally suggested by cgrey as a way to address the issue of discovering more thoroughly the places where the FORD programmers put paramters for functions directly after the call instructions. i took it to the next level by deciding to actually create a simulator to be able to really run the code.
I was watching that interchange. Discovering the places where passing parameters inline happens is fairly simple if you take the trouble to work out what the instructions are doing. It can be tedious to build up the dir file to accommodate them all; I think too tedious for cgrey, and he kept telling me that it was simple for a computer to do this tedious work.

Interestingly I think th esimulator way of doing this requires even more understanding of exactly what the instructions do. To drive the disassembler, you don't really need that. Like your cmp and carry flag example; it's enough to see that you have a loop zeroing memory. It doesn't really matter if the last thing it zeroes is 048A or 0489, but to program a disassembler, you need to do much more work to really understand things. Your carry flag example made me go back and think about how much I really understood what's going on. So, thanks.
TripleBlackVert wrote: this project has multiple goals, one of which is to end up with a clean, commented disassembly. the other goals are:

- to learn c# in the process. after i get it worked out in c++, i plan to migrate it to c#
- to be able to simulate a run based on a real life datalog taken
I'm not sure it's so simple to log the raw inputs so you can use them as simulation inputs. I'm sure you'll find a way that's nearly as good though. I think it's drmayf on the Yahoo Tweecer group who has a hardware generator for several EEC-IV inputs. He's probably not the only one.
TripleBlackVert wrote: - to be able to assemble code correctly, initially the disassemby back into the original binary
I'm sure you'll have no trouble with that. And assembling it back into the QH will be much easier and, I think, more useful.
I'll also be interested when you achieve that goal to hear whether you agree that building a simulator was a rather hard way to achieve a clean disassembly. :-)
TripleBlackVert wrote: - to create a higher level language that can result in assembly or machine code for this processor.

- - this might be like FORTH or a subset of C, but it will be a pretty simple language
- eventually, to be able to write a completely new engine management system using this processor as the hardware
at that level of simplicity, code bloat will be a big issue, and I suspect you'll need to be thinking of recompiling for a bigger memory space.

A new EMS would be interesting work, but I believe it would be more effective to modify a later EEC-V ECU. The A9L is pretty primitive, it's just the most understood (publicly) for the obvious reasons. for example later EEC-IV ecus have an OBD2 style data link that can spew out data for logging, and accept data to run as code. Many people push A9L because more of it is believed to be understood.
TripleBlackVert wrote:re the first goal ... i have been a c++ developer for 20+ years, so that is my main strength. i don't want to be struggling with the language and the logic both at the same time, or i will more likely give up. after i get the logic figured out and working, i can focus on the language issues.

and yes, i am working towards an interactive enviromnent where i can put breakpoints in and look at things while running. i find it very interesting.
Watch out for those language issues of C/C++ arithmetic though. It's amazing how much you find out you don't know, working with a language standards group.

Sailorbob also told me, and he's right that doing disassemblies gets a lot easier after the first one.

I started on a simulator myself (after working on one for the Motorola 88000 years ago), but decided that my goals would be better met by working on my disassembler mods, and adding control flow data to it; giving myself a refresher on compiler technology. Doing it the harder way is always more interesting.


One feature of your simulator you might consider adding is an easy way to go straight to the place where a particular memory location is first stored to. I've found that useful when looking for particular variables.

Michael

decipha

Re: CMP and the carry flag

Post by decipha » Mon Jun 14, 2010 4:28 pm

when i was in the man-scouts i carried the flag once

:lol:


:roll:

User avatar
cgrey8
Administrator
Posts: 11269
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: CMP and the carry flag

Post by cgrey8 » Mon Jun 14, 2010 6:28 pm

mpaton wrote:...Many people push A9L because more of it is believed to be understood...
If there were more open source EEC-V def files that were worth use, I'd be recommending one of them and would probably convert my GUFB-perfected setup to use an EEC-V instead just because they are so much better. And for people that need something like GURE or CBAZ0, I refer them to Derek's CRY files. But after being the maintainer of the GUFx stuff, I'm spoiled to being able to go manipulate things when I want, the way I want. Since nobody else has complained about the way the GUFx stuff is organized, or anything I've done in them, I continue to maintain them. But if someone decides they want that responsibility, it's theirs. Although I'd probably still maintain my own version. At this point, the GUFx stuff is so mature, there's not much that needs to be done to them. I say that, but I have just recently added some functionality to the QH patch code to support tune-position datalogging in the Quarterhorse and modified some scalars from being unsigned to being signed.

With a CRY file, I can't do that kind of stuff. I'm dependent on someone else to do that. For many, that's no big deal since they don't have any desire to deal with the def file...they just want the thing to work. But I personally would find dealing with a CRY file down right frustrating. Don't get me wrong, I think the CRY developers have the right to encrypt their stuff and maintain it and I support their ability to do it. But dealing with CRY files is just not for me which is another reason I'm so excited about these guys putting effort into these emulator programs to more-effortlessly disassemble BINs which will hopefully make it easier for the open source library to get bigger or at least get better quality open source defs for the popular stuff. From what I understand, it wouldn't take but a few 2-bank and 4-bank EEC-V defs to be made open source and reliable to be a viable solution for people particularly since the Quarterhorse allows us to run tune strategies other than the EEC's native strategy. Thus I could take a CDAN4 tune and run it on a CDAN6 (2-bank Grand Marquis) or CQAB1 (2-bank 97 Explorer) EEC and get most all of the functionality/flexibility of a 2-bank EEC-V from the CDAN4 strategy. Likewise with some of the 4-bank stuff like CRAI8, CRAJ0, etc. With more people able to get a clean disassembly, we'd have more people familiar with those platforms which is a good thing for the community at large.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, FMS Explorer (GT40p) headers, aftermarket T5 'Z-Spec', GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Mon Jun 14, 2010 7:01 pm

what is a CRY file?
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

User avatar
cgrey8
Administrator
Posts: 11269
Joined: Fri Jun 24, 2005 5:54 am
Location: Acworth, Ga (Metro Atlanta)
Contact:

Re: CMP and the carry flag

Post by cgrey8 » Mon Jun 14, 2010 7:03 pm

A CRY is a def file that's been encrypted by the creator. The creator can create license keys to unlock use of the CRY def file on subscriber's computers, but that only allows them the ability to use the def file, not open/view the details of the def file like the offsets, signed/unsigned setting, size, conversions, etc. This prevents others from benefiting from their hard work without paying for it.
...Always Somethin'

89 Ranger Supercab, 331 w/GT40p heads, ported Explorer lower, Crane Powermax 2020 cam, FMS Explorer (GT40p) headers, aftermarket T5 'Z-Spec', GUFB, Moates QuarterHorse tuned using BE&EA

Member V8-Ranger.com

BillMarkViii
BIN Hacker
Posts: 15
Joined: Fri Jun 19, 2009 5:10 pm

Re: CMP and the carry flag

Post by BillMarkViii » Sun Jun 20, 2010 11:57 am

TripleBlackVert wrote:ok. this code seems to be consistent with way the assembler logic is written. thanks!

it still seems counter-intuitive though, because if AX > BX, carry is set, indicating that a borrow was necessary, when it wasn't

Code: Select all

struct 
{
	bool Z; // true if result is ZERO
	bool C; // true if CARRY is set
	bool N; // true if result is NEGATIVE
} flags;
per the logic from sailorbob ...

Code: Select all

void CMP(WORD AX_D, WORD BX_A)
{
	// CMP is defined as D - A, or AX - BX in sailorbob's terminology

	long res = (long)AX_D - (long)BX_A;

	flags.Z = (res == 0);
	flags.C = ( AX_D >= BX_A );
	flags.N = (res < 0);
}
as it turns out, the "identity" version of the subtraction results in the same flags ...

Code: Select all

void CMP2(WORD AX_D, WORD BX_A) 
{
	BX_A = ~BX_A;
	DWORD res_w = AX_D + BX_A + 1;
	WORD res = (WORD)(res_w & 0x0000FFFF);

	flags.Z = ( res == 0 );
	flags.C = ( (res_w & 0xFFFF0000) != 0 );
	flags.N = ( (res & 0x8000) == 0x8000 );
}

I have been working on analyzing the disassemblies of several of my BINs and in trying to follow the control flow it became clear that JC/JNC were not acting like they seem to be documented.

I put together a short piece of code along with a 'datalog' section to grab the stack dump and ran it on an EEC-V. What I found is not consistent with the docs. The description of CMP as D-A with D being the left and A being the right is not correct. OR JC/JNC are reversed. In this disassembly JC is opcode 'DB' and JNC is 'D3' like in the docs.

CMPB 0,0
JC takes the jump yet it should not jump as 0-0 shouldn't set carry

CMPB 0xE0,0xE0
JC takes the jump yet it should not jump as E0-E0 shouldn't set carry

CMPB 41,40
JC takes the jump yet it should not jump as 41-40 shouldn't set carry

CMPB 40,41
JC doesn't take the jump. 40-41 should set carry

CMPB 0,0
JNC doesn't take the jump yet it should, 0-0 should not set carry

CMPB 41,40
JNC doesn't take the jump yet it should, 41-40 should not set carry

CMPB 40,41
JNC does take the jump yet it should not, 40-41 should set carry

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Sun Jun 20, 2010 11:21 pm

BillMarkViii wrote: I have been working on analyzing the disassemblies of several of my BINs and in trying to follow the control flow it became clear that JC/JNC were not acting like they seem to be documented.

I put together a short piece of code along with a 'datalog' section to grab the stack dump and ran it on an EEC-V. What I found is not consistent with the docs. The description of CMP as D-A with D being the left and A being the right is not correct. OR JC/JNC are reversed. In this disassembly JC is opcode 'DB' and JNC is 'D3' like in the docs.

CMPB 0,0
JC takes the jump yet it should not jump as 0-0 shouldn't set carry

CMPB 0xE0,0xE0
JC takes the jump yet it should not jump as E0-E0 shouldn't set carry

CMPB 41,40
JC takes the jump yet it should not jump as 41-40 shouldn't set carry

CMPB 40,41
JC doesn't take the jump. 40-41 should set carry

CMPB 0,0
JNC doesn't take the jump yet it should, 0-0 should not set carry

CMPB 41,40
JNC doesn't take the jump yet it should, 41-40 should not set carry

CMPB 40,41
JNC does take the jump yet it should not, 40-41 should set carry
this is exactly why i believe it uses the identity that D-A = D + (not A) + 1, NOT the concept that the carry flag indicates a borrow in the case of a subtraction.

using the D + (not A) + 1 logic, then if the result is larger than the base type, the carry flag is set.

notice this .... using BYTE sized values ...

0 - 0 = 0 + (not 0) + 1 = 0 + (FF) + 1 = 100, so the carry flag is set and the BYTE result is 0

41 - 40 = 41 + (not 40) + 1 = 41 + (BF) + 1 = 101, carry is set, result is 1

40 - 41 = 41 + (not 41) + 1 = 40 + (BE) + 1 = FF, carry not set, result is FF or -1

make sense?
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

mpaton
BIN Hacker
Posts: 381
Joined: Mon Jun 23, 2008 1:39 pm

Re: CMP and the carry flag

Post by mpaton » Mon Jun 21, 2010 1:40 pm

TripleBlackVert wrote: this is exactly why i believe it uses the identity that D-A = D + (not A) + 1, NOT the concept that the carry flag indicates a borrow in the case of a subtraction.

using the D + (not A) + 1 logic, then if the result is larger than the base type, the carry flag is set.

notice this .... using BYTE sized values ...

0 - 0 = 0 + (not 0) + 1 = 0 + (FF) + 1 = 100, so the carry flag is set and the BYTE result is 0

41 - 40 = 41 + (not 40) + 1 = 41 + (BF) + 1 = 101, carry is set, result is 1

40 - 41 = 41 + (not 41) + 1 = 40 + (BE) + 1 = FF, carry not set, result is FF or -1

make sense?
Not to me, I'm afraid. Not completely anyway. That identity is nothing more than the standard way to negate 2's complement signed numbers. So using it or not using it doesn't change the results on signed numbers. Even though you've used the identity to justify the results, I don't believe it's possible to get a different result by NOT using the identity.

Additionally, the 8096 family manuals state that the carry flag is set when a borrow happens on subtraction.
Whatever that's worth, because although the processors are quite similar, they aren't identical in all aspects.

I think a conventional understanding of what conditions are set by the various operations meshes well with the conventional understanding of how jumping based on those conditions should work.

What's NOT clear, IMO is the actual bits being set. You can do disassembly fairly well with only the conventional understanding, but simulation MAY require a deeper understanding. If one intends to model the actual condition bits, then one does need that deeper understanding. Running code will eventually reveal that.

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Mon Jun 21, 2010 3:41 pm

i probably read the same things you did that talked about the carry flag indicating a borrow.

and you are right in that it is simply another way to perform the subtraction. but here is the part that you seem to be missing ...

the evidence does not support the statement in the documentation that the carry flag indicates that a borrow occurred. the evidence actualy supports the exact opposite.

the same evidence indicates that if the subtraction is done using the corresponding addition (D + (not A) + 1), then the carry flag that is set as a result of the addition appears to be exactly the way it should be for the JC and JNC statements to behave as expected.

or said another way, the resulting value from the subtraction done the "identity" way is the same, but they have different side effects with respect to the setting of the carry flag.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

mpaton
BIN Hacker
Posts: 381
Joined: Mon Jun 23, 2008 1:39 pm

Re: CMP and the carry flag

Post by mpaton » Mon Jun 21, 2010 6:59 pm

TripleBlackVert wrote:i probably read the same things you did that talked about the carry flag indicating a borrow.

and you are right in that it is simply another way to perform the subtraction. but here is the part that you seem to be missing ...

the evidence does not support the statement in the documentation that the carry flag indicates that a borrow occurred. the evidence actually supports the exact opposite.
That's a fair conclusion. However I'm really just waiting for ALL the evidence.
TripleBlackVert wrote:the same evidence indicates that if the subtraction is done using the corresponding addition (D + (not A) + 1), then the carry flag that is set as a result of the addition appears to be exactly the way it should be for the JC and JNC statements to behave as expected.

or said another way, the resulting value from the subtraction done the "identity" way is the same, but they have different side effects with respect to the setting of the carry flag.
Again, that's a reasonable working hypothesis. I'd rather wait for all the evidence from the code tests, now that the applicability of the 8096 manual to the 806x processor is in doubt in this area.

The conventional way to take the negative of a 2's complement number is to

1 Flip all the bits

2 Add one

3 Discard any carry bit so as to get back to the same number of bits

You've omitted step 3, in order to justify your hypothesis.

That's not wrong, just interesting.

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Mon Jun 21, 2010 9:43 pm

mpaton wrote:...
The conventional way to take the negative of a 2's complement number is to

1 Flip all the bits

2 Add one

3 Discard any carry bit so as to get back to the same number of bits

You've omitted step 3, in order to justify your hypothesis.

That's not wrong, just interesting.
For a comparison, you can't just throw away the carry bit; the comparison is supposed to set (or clear) it. But the D + (not A) + 1 implementation of the subtraction just so happens to set the carry bit the same way as the empirical evidence BillMarkViii collected shows.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

mpaton
BIN Hacker
Posts: 381
Joined: Mon Jun 23, 2008 1:39 pm

Re: CMP and the carry flag

Post by mpaton » Mon Jun 21, 2010 9:59 pm

TripleBlackVert wrote:
mpaton wrote:...
The conventional way to take the negative of a 2's complement number is to

1 Flip all the bits

2 Add one

3 Discard any carry bit so as to get back to the same number of bits

You've omitted step 3, in order to justify your hypothesis.

That's not wrong, just interesting.
For a comparison, you can't just throw away the carry bit; the comparison is supposed to set (or clear) it. But the D + (not A) + 1 implementation of the subtraction just so happens to set the carry bit the same way as the empirical evidence BillMarkViii collected shows.
But for a negation, you can and usually do. And if you don't discard it, then your byte comparison is actually comparing a 9 bit number with an 8 bit number.

But you're correct that you've built a case that it could work that way. I'm just not yet convinced that that's the true explanation. Could be though.

TripleBlackVert
BIN Hacker
Posts: 802
Joined: Tue Apr 20, 2004 2:50 pm
Location: Bethesda, Maryland

Re: CMP and the carry flag

Post by TripleBlackVert » Mon Jun 21, 2010 11:42 pm

hmmmm. re-reading sailorbob's posts, i think i finally understand the algorithm he was describing ...

the carry bit is set to ONE first, then the subtraction is done, and if it needed to borrow a bit (as would be the case when A > D), then the carry bit is the bit that is borrowed and it becomes ZERO if (when) the borrow happens. if D >= A, then there is no borrow, and the carry bit remains set.

this would also result in the carry bit being set if D >= A and clear if A > D.
95 GT Vert, TwEECer R/T v1.30A9
1970 block, 410ci, 10.27:1 CR, 42#, LMAF, CBAZA/T4M0, AOD, 2500 Stall, Custom Cam

1967 Fairlane Vert, 390FE, C6, 100% stock

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests