EEC V file conversion

All hardware related, disassembly / programming and code discussions belong here.
BOOSTEDEVERYTHING
Posts: 235
Joined: 2023 Sep 06, 13:11
Location: Charlotte NC , USA
Vehicle Information: 1999 Ford Ranger with 2000 Explorer v8 swap, FLN0
2003 Ford F150 Harley Davidson, Built 5.4L SOHC with 3.4L Whipple and Built 4R100

Re: EEC V file conversion

Unread post by BOOSTEDEVERYTHING »

Just when I thought I was starting to wrap my head around it. Lol. Ford!! I am a Ford tech at a dealer so I do know the complexity they put into everything. And the info that they withhold even from dealer level techs. I had no idea about the !INV! Thing. I haven’t seen that yet while walking through the code. It starts to get a little confusing for me after a while trying to keep track of where to go next and where I came from and if I should go back or forward while following the code. I am even having issues following along in the strategy docs at times but I’m guessing that’s because they aren’t the docs for the strategy I’m actuallly working with? At least I hope. lol. I’ll wrap my head around your comments and see if I can finally get it. What I am getting is that 9a4 is not an actual address, it’s a pointer in the preceding subroutine, is that correct?
wwhite
Posts: 320
Joined: 2021 Feb 16, 15:53
Location: Victoria, BC, Canada
Vehicle Information: 1994 Flarside, XLT, 351w E4OD
SD48b, Quarter Horse, Burn2

Re: EEC V file conversion

Unread post by wwhite »

In the msg file will show errors and invalid information.
Using the EQE3 bin, I get

Code: Select all

Invalid opcode at 1e8f6 [5]
I put the following in my dir:

Code: Select all

sym 22  "StackPtr2"                  # auto
SYM  09A4 "P0400STATE"                #UY
sym 02060  "I0_HSO_0"                  # auto
And get the correct output in the lst.

What is interesting, is the msg file shows this:

Code: Select all

sym 0fd44  "Sub_0fd44"
sym 109a4  "P0400STATE"
sym 1206a  "Func_1206a"
And I get this in the lst, which is correct?:

Code: Select all

83111: 10,00              rombk 0
83113: ef,cb,b4           call  0e5e1            Sub_0e5e1 (
83116: a4,09                    #arg 1              P0400STATE,
83118: 05                       #arg 2              5 );
83119: 91,40,89           orb   R89,40           B6_R89 = 1;
tvrfan
Posts: 88
Joined: 2023 Oct 22, 22:13
Location: New Zealand
Vehicle Information: Several Kit cars, Ford (Europe), EEC-IV, TVR Vixen, Tasmin (a.k.a Wedge),
Engine - Cologne 2.8 V6 (Europe) catch code 'AA'.

EEC_Disassembler https://github.com/tvrfan/EEC-IV-disassembler

Re: EEC V file conversion

Unread post by tvrfan »

To all -

!!INV!! is a SAD backstop when it thinks it has encountered an illegal opcode. I'll say this up front - it should never happen if bin is disassembled correctly. But there are still bugs/holes in SAD. Mostly the !INV! occurs when subroutine arguments are calculated incorrectly. But there are a few other situations where it can happen also.

In several places SAD uses a BEST GUESS, and it ain't always right. It still misses some code here and there, and I know that data can be missed entirely in some cases. This is why I have all those user commands, so that you can override, and hopefully fix the problem.

Ford software engineers did some clever stuff which works well and speeds things up. (I say this as an IT designer) They also came up with designs which allow them to change calibrations for testing, allows for 'limp home' modes, 'learning' and 'autocorrect' for sensor fails. That's bloody good, frankly. But for disassembling the code, these tricks can be a real PITA to try to pick apart and interpret correctly with another program.

A few examples -
encoded addresses - Ford use 4 types (so far) of encoded address, where they squeeze a [base+index] into one word. SAD handles these correctly from V4. (This trick uses the RBASE registers).

Subroutine Arguments - SAD has to actually emulate/run the code for these, as the tricks don't work in a 'static' scan (= going through the code like a plain list) in CARD for example there is a truly HORRIBLE piece of code in an args extract (in the decode sense, I mean). I'm still not certain the emulate works correctly for every bin.

Vector Lists (background task list, test list, etc). This is a list of subroutine addresses, which are 'called' in sequence. It's not always obvious where the list ends, which means SAD can pick up a faulty address. I know this happens in a couple of bins. A9L actually has some DATA in the middle of its pointer list which doesn't help either.

'lookup' lists. (A list of pointers) In some bins it appears that some tables and functions are referenced by a list of pointers. They use an index (base address + index) instead of a plain address. As SAD scans the code in a 'static' way it will only get one of the list items. I haven't got a neat way to handle this one yet.

Functions and tables and some other code tricks - I have the concept of a 'fingerprint match' in SAD, which identifies blocks of code which do a particular job, like say the function lookup routines. These do work, and can handle small variations in the code, but now and then I see another variation which does NOT work, so I must add a new fingerprint.

Tables - sometimes SAD gets the sizes wrong - I'm still trying to come up with a method to try to sort out what the table looks like (i.e. rows and columns).

And there's more..... that gives you an idea of where SAD is at...and why it's still ongoing.

So please don't assume everything it prints is always 100% right ....maybe 90% ??.

After an !INV! SAD will stop that block, as a safety thing, but next code block (i.e. jumped to or called) will be right again.
tvrfan
Posts: 88
Joined: 2023 Oct 22, 22:13
Location: New Zealand
Vehicle Information: Several Kit cars, Ford (Europe), EEC-IV, TVR Vixen, Tasmin (a.k.a Wedge),
Engine - Cologne 2.8 V6 (Europe) catch code 'AA'.

EEC_Disassembler https://github.com/tvrfan/EEC-IV-disassembler

Re: EEC V file conversion

Unread post by tvrfan »

CARD.......an explanation of how the best designs/plans get wrecked....
this is an example of a HORRIBLE code trick from a disassembly point of view. And maybe a primer on how arguments are extracted.
See if you can work out how these actually do their job...

Up until jsa sent me the CARD bin, I had a 'static' (fingerprint') matcher for args.
After all, most bins use variations of the same code to get arguments. e.g. A9L
this worked well, and this code appears often across bins.

Fixed type A9L - get 2 bytes from caller subroutine ...

Code: Select all

   
   Get_par:
3695: cc,38               pop   R38              R38 = pop();                      # This subroutine's return addr
3697: cc,3a               pop   R3a              R3a = pop();                      # Caller subroutine's return addr
3699: b2,3b,3c            ldb   R3c,[R3a++]      R3c = [R3a++];
369c: b2,3b,3d            ldb   R3d,[R3a++]      R3d = [R3a++];                    # 3c, 3d from caller
369f: c8,3a               push  R3a              push(R3a);                        # restore caller address (+2)
36a1: c8,38               push  R38              push(R38);                        # restore this return address

Variable args A9L - get specified number of args from caller subroutine.........

Code: Select all


77c2: cc,3c               pop   R3c              R3c = pop();                      # this subroutines return address
77c4: b2,3d,3a            ldb   R3a,[R3c++]      R3a = [R3c++];                    # Get count of bytes required
77c7: cc,42               pop   R42              R42 = pop();                      # Get Caller's return address
77c9: b2,43,3b            ldb   R3b,[R42++]      R3b = [R42++];
77cc: c6,17,3b            stb   R3b,[R16++]      [R16++] = R3b;                    # get byte from caller 
77cf: e0,3a,f7            djnz  R3a,77c9         R3a--;
                                                 if (R3a != 0) goto 77c9;          # Get no of bytes into dest. addr
77d2: c8,42               push  R42              push(R42);
77d4: c8,3c               push  R3c              push(R3c);                        # and push modded returns back.

And then their multibank equivalents - (xdt2 bin)
NB. this looks a lot more complicated but it's mostly for fiddling with banks.
This gets 4 bytes from caller subroutine.

Code: Select all

82f93: a3,20,02,36        ldw   R36,[R20+2]      R36 = [StackPtr+2];
82f97: a3,20,04,3a        ldw   R3a,[R20+4]      R3a = [StackPtr+4];
82f9b: f2                 pushp                  push(PSW);
82f9c: fa                 di                     interrupts OFF;
82f9d: 18,02,37           shrb  R37,2            R37 >>= 2;
82fa0: b0,37,11           ldb   R11,R37          BANK_Select = R37;
82fa3: b2,3b,36           ldb   R36,[R3a++]      R36 = [R3a++];
82fa6: b2,3b,37           ldb   R37,[R3a++]      R37 = [R3a++];
82fa9: b2,3b,38           ldb   R38,[R3a++]      R38 = [R3a++];
82fac: b2,3b,39           ldb   R39,[R3a++]      R39 = [R3a++];
82faf: b1,11,11           ldb   R11,11           Data_Bank = 1;
                                                 Stack_Bank = 1;
82fb2: f3                 popp                   PSW = pop();
82fb3: c3,20,04,3a        stw   R3a,[R20+4]      [StackPtr+4] = R3a;
and its xdt2 variable equivalent -

NB. again a lot of fiddling to get the bank(s) right, but it does same job as 77be above

Code: Select all

8a526: a2,20,40           ldw   R40,[R20]        R40 = [StackPtr];
8a529: 18,02,41           shrb  R41,2            R41 >>= 2;
8a52c: c4,11,41           stb   R41,R11          BANK_Select = R41;
8a52f: a3,20,02,40        ldw   R40,[R20+2]      R40 = [StackPtr+2];
8a533: b2,41,3e           ldb   R3e,[R40++]      R3e = [R40++];
8a536: c3,20,02,40        stw   R40,[R20+2]      [StackPtr+2] = R40;
8a53a: a3,20,04,40        ldw   R40,[R20+4]      R40 = [StackPtr+4];
8a53e: 18,02,41           shrb  R41,2            R41 >>= 2;
8a541: b0,41,11           ldb   R11,R41          BANK_Select = R41;
8a544: a3,20,06,46        ldw   R46,[R20+6]      R46 = [StackPtr+6];
8a548: b2,47,3f           ldb   R3f,[R46++]      R3f = [R46++];
8a54b: c6,27,3f           stb   R3f,[R26++]      [R26++] = R3f;
8a54e: e0,3e,f7           djnz  R3e,8a548        R3e--;
                                                 if (R3e != 0) goto 8a548;
8a551: b1,11,11           ldb   R11,11           Data_Bank = 1;
                                                 Stack_Bank = 1;
8a554: c3,20,06,46        stw   R46,[R20+6]      [StackPtr+6] = R46;

and then jsa sent me THIS - and the air went blue (Do you say this in USA, or
is it more like "swears like a trooper?")

446a - - - - WHAT THE F**K is THAT ??!!!! AAARRGGGHHHH !!!!!!

Code: Select all

   Sub_4456:
4456: f8                  clc                    CY = 0;
4457: 20,01               sjmp  445a             goto 445a;

   Sub_4459:
4459: f9                  stc                    CY = 1;
445a: cc,18               pop   R18              R18 = pop();
445c: b2,19,1a            ldb   R1a,[R18++]      R1a = [R18++];
445f: b2,19,1b            ldb   R1b,[R18++]      R1b = [R18++];
4462: b2,19,1c            ldb   R1c,[R18++]      R1c = [R18++];
4465: b2,19,1d            ldb   R1d,[R18++]      R1d = [R18++];
4468: d3,05               jnc   446f             if (CY = 1) {
446a: c9,fa,40            push  40fa             push(Sub_40fa);
446d: 20,02               sjmp  4471             goto 4471; }

446f: c8,18               push  R18              push(R18);
4471: 91,02,2c            orb   R2c,2            R2c |= 2;


   Sub_40f8:
40f8: cc,18               pop   R18              R18 = pop();
   Sub_40fa:
40fa: ae,19,14            ldzbw R14,[R18++]      wR14 = y[R18++];
40fd: b2,19,17            ldb   R17,[R18++]      R17 = [R18++];
4100: c8,18               push  R18              push(R18);

And I knew then I had to throw away all my work on the fingerprint type arg getters.
real shame as they had worked just fine up to now... I had to 'emulate' the code.
Emulate is to set up enough conditions to actually run the code as if it is for real,
but you can 'fake' it quite a lot. But I needed to have a 'fake stack' and have it
built correctly for each 'call' of subroutine, (and some more as it turned out)

Later I also found a bin (which I can't find right now, but it's saved somewhere) which
gets 2 extra bytes if top bit of first argument byte is set...)

So I had to rework a whole bunch of SAD code to do this.

(true answer is 4456 gets 4 args, 4459 gets 6 args)
decipha
Posts: 5051
Joined: 2021 Feb 15, 12:23
Location: Metairie, LA
Vehicle Information: Work Truck
'19 F-150 3.3L

Re: EEC V file conversion

Unread post by decipha »

no need to throw it away just have it as an option to not label args at the top of the directive

/done
tvrfan
Posts: 88
Joined: 2023 Oct 22, 22:13
Location: New Zealand
Vehicle Information: Several Kit cars, Ford (Europe), EEC-IV, TVR Vixen, Tasmin (a.k.a Wedge),
Engine - Cologne 2.8 V6 (Europe) catch code 'AA'.

EEC_Disassembler https://github.com/tvrfan/EEC-IV-disassembler

Re: EEC V file conversion

Unread post by tvrfan »

Nice idea, but SAD has to work out how many arg bytes there are, to avoid !INV and/or it going off into fantasy land, as args are often valid opcode numbers (but trash...). I did wonder if it was possible somehow to guess how many arg bytes...but can't think of any way that works.
An issue with v4 , trying to sort this out..........

Code: Select all

0e8dc: ef,6a,08           call  0f149            Sub_0f149 ();                # this should have 9 following bytes ......
0e8df: c8,09              push  R108             push(R108);
0e8e1: dc,09              jvt   0e8ec            if (OVT = 1) {
0e8e3: 90,0a,5b           orb   R5b,Ra           R5b |= IO_Status;
0e8e6: 08,80,ef           shrw  R1ee,R80         R1ee >>= R80;        # should be opcode ef ...call <something>
0e8e9: 66,06,ef           ad2w  R1ee,[R6]        R1ee += [IO_Timer]; }
0e8ec: 93,09,f3,f0,a3     orb   Ra3,[R8+f0f3]    Ra3 |= [INT_Mask+1f0f3];
0e8f1: 20,02              sjmp  0e8f5            goto 0e8f5;

0e8f3: 3e,a3,20           jb    B6,Ra3,0e916     if (B6_Ra3 = 1) 
0e8f6: 04                 !INV! 
0e8f7: 26,f2              sjmp  0e7eb            
jsa
Posts: 274
Joined: 2021 Feb 16, 15:46
Location: Australia
Vehicle Information: 95 Escort RS Cosworth
2.0 YBP
CARD / QUIK / COSY / ANTI
GHAJ0
SMD-190 / SMD-490 EEC-IV

Binary Editor
ForDiag

Re: EEC V file conversion

Unread post by jsa »

BOOSTEDEVERYTHING wrote: 2023 Nov 15, 16:29 Please help me understand the arg code a little better?

Code: Select all

83113: ef,cb,b4           call  0e5e1            Sub_0e5e1 (
83116: a4,09                    #arg 1              9a4,
83118: 05                       #arg 2              5 );
83119: 91,40,89           orb   R89,40           EGR_MON = 1;
This spreadsheet lays out the code from L83108 linearly to keep track of the Stack, SFR11 and relevant registers.
I've gone as far as confirming the arg quantities and sizes, further work is required to understand the sub totally.
I will say that it looks like fault code handling code, as others have said.
Args EQE3.xlsx
(15.63 KiB) Downloaded 73 times
The spreadsheet is 'emulating' the code, one might say, as SAD needs to do to successfully handle args.

BIN's typically contain a list of strategy supported fault codes. These can be used as a means of confirming assumptions about parts of the disassembly. If you find fault handling code comparing values for fault code 112, you know it is Air Charge Temp or Intake Air Temp.

Fault code 112 & 113 are typically supported in strategies, so one can search LST for 12,01 and 13,01 to quickly track down that list. Once the list address is know, 16be6 for EQE3, then LST can be searched for 6BE6. Subs using 6BE6 can be worked through to find payloads and scalars. This approach requires solid understanding of the 8061/5 workings, so a bit heavy for someone getting started. One gets used to rereading the manuals to confirm details.

These are links to posts elsewhere that have other spreadsheets working through different arg methods. It'd be worth reviewing to enhance your understanding.
http://eectuning.org/forums/viewtopic.p ... 60#p136055
http://eectuning.org/forums/viewtopic.p ... 20#p136291

These two entries can be added to your DIR in appropriate places.

Code: Select all

SYM 16BE6 "FAULT_CODE_LIST"                    # Address to list of strategy supported fault codes

WOR 16BE6 16D5D
jsa
Posts: 274
Joined: 2021 Feb 16, 15:46
Location: Australia
Vehicle Information: 95 Escort RS Cosworth
2.0 YBP
CARD / QUIK / COSY / ANTI
GHAJ0
SMD-190 / SMD-490 EEC-IV

Binary Editor
ForDiag

Re: EEC V file conversion

Unread post by jsa »

BOOSTEDEVERYTHING wrote: 2023 Nov 15, 16:29 I first tried it at address 9a4, but obviously it is not correct because it does not define it in the lst file when i put that in the dir file.
BOOSTEDEVERYTHING wrote: 2023 Nov 30, 08:18
For this one I was just trying to name the 9a4 address as p0400state. so I put this in my dir file.

Code: Select all

SYM  09A4 "P0400STATE"                #UY
But it doesn't seem to want to name that 9a4 address in the argument. I does appear elsewhere in the lst file, not as an arg, and names it as p0400state. Not sure what I am doing wrong. Is there something I am missing?
These go in DIR as a starting point.

Code: Select all

SYM   9A4 "FM_9A4"                        # W # Failure management

SUB 0E5E1 "Sub0E5E1_FM"                     :WN :Y
Rather than applying options to the Sub command it would be possible to use the arg command individually for every occurrence of an arg to sub 0e5e1.
That would look like
DIR

Code: Select all

SYM   9A4 "FM_9A4"                        # W # Failure management

arg 83116 83117 :WN
arg 83118 83118 :Y
 
SUB 0E5E1 "Sub0E5E1_FM"
One caution, note the loop counter arg we previously discovered at L0E5E7.
If Sub_Oe5E1 is called and the loop counter arg is a value other than 3, we will need to use the arg command instead of adding options to the sub command. I've also searched LST for INV to make sure my sub command with options does not stuff the disassembly.

I've decided to name the word arg but not the byte arg. The byte arg goes on to be compared to values such as 8 and 9, so it is likely some sort of event count. That count could be an inline scalar which will have a name.

CATCH 22, 5 conflicts with the name for Special Function Register 5.
This has been an ongoing discussion with TVRfan for ever.
Multipliers, dividers, fault code numbers, in line parameters, addresses, etc, all conflict because the hex values match for symbol names.

The latest proposal for SAD V5 is to retain SYmbol Multiple as it is now, but add SYmbol siNgle to name 5 for address 83118.
Something like;

Code: Select all

SYN    5 83118 "thingo_count"
For now SAD 4.07.16B names the arg, but 4.12 does not.
LST 4.07.16B

Code: Select all

83113: ef,cb,b4           call  0e5e1            Sub0E5E1_FM (
83116: a4,09                    #arg 1              FM_9A4,
83118: 05                       #arg 2              5 );
jsa
Posts: 274
Joined: 2021 Feb 16, 15:46
Location: Australia
Vehicle Information: 95 Escort RS Cosworth
2.0 YBP
CARD / QUIK / COSY / ANTI
GHAJ0
SMD-190 / SMD-490 EEC-IV

Binary Editor
ForDiag

Re: EEC V file conversion

Unread post by jsa »

BOOSTEDEVERYTHING wrote: 2023 Nov 30, 20:56 I had no idea about the !INV! Thing.
That is SAD indicating that the disassembly is going wrong.
Hopefully the DIR I posted earlier has eliminated any that might occur.

Put something like this in DIR and see if it generates !Inv!
Not tried it but you can mess around with it.

Code: Select all

SUB 0E5E1 "Sub0E5E1_Stuffed"                     :WN :WN :WN
I am even having issues following along in the strategy docs at times but I’m guessing that’s because they aren’t the docs for the strategy I’m actuallly working with?

Yes that can be the case.
jsa
Posts: 274
Joined: 2021 Feb 16, 15:46
Location: Australia
Vehicle Information: 95 Escort RS Cosworth
2.0 YBP
CARD / QUIK / COSY / ANTI
GHAJ0
SMD-190 / SMD-490 EEC-IV

Binary Editor
ForDiag

Re: EEC V file conversion

Unread post by jsa »

wwhite wrote: 2023 Dec 01, 11:49 In the msg file will show errors and invalid information.
Using the EQE3 bin, I get

Code: Select all

Invalid opcode at 1e8f6 [5]
I get fill for that address.

Code: Select all

179e6 -> 1ffff = 0xff  ## fill ## 
What DIR and SAD version are you using?

Edit: SAD bug, see post earlier in the thread.
Post Reply