EEC V file conversion

All hardware related, disassembly / programming and code discussions belong here.
BOOSTEDEVERYTHING
Posts: 217
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 »

a byte value (8 bits) 0x80 represents -256 decimal, 0x81 is -255, 0x82 is -254, through to 0xfe = -2 and 0xff = -1 (and 0=0)
a word value (16 bits) 0x8000 represents -32768 , 0x8001 is - 32767, through to 0xfffe = -2, 0xffff = -1 (and 0=0)
This is what is in your head because you trained yourself over the years to just understand this. I guess I am asking what you maybe used to learn this or if there is a way someone can convert the f6 to a -10 or A? I can research how to tell if it should be negative or positive, or I will at least try, but then how do I make the conversion without having the info above already pre-programmed into my head? For example, I can research the operation and I have figured out, well you told me, I still need to go back and research again how to know exactly, that the f6 is supposed to be negative….being a newbie, I would just say ok it is -f6, but I know now that is not correct. Is there a conversion chart or a way to make the conversion on a calculator or something? Maybe an excel file or something? I wish I was better with excel myself. It would be awesome to make a spreadsheet file and put all the similarities I find in the documents in the spreadsheet and add new strategies as I do them to that same sheet. And then a column for notes and locations in the strategy docs for the ops being used. Maybe I will look into that a little bit too. Something better than a ruler and some notebook paper. I find myself writing the same thing repeatedly and then I end up researching things many times. To input a location and it tell me it is already there and or put it in order as I enter it would be awesome. Thanks again for the help and explanations. I honestly do really appreciate the help.
tvrfan
Posts: 84
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 »

In a nutshell -
On my desktop calculator in 'hex' mode I would do 100 - f6 for a byte calculation to get 'A'. For a word it would be 10000 - <Value>
It works this way 100-ff = 1 100-fe = 2 ... and shove a minus sign in front of the answer. Yes it's backwards to the way human brains work.
I can't actually dial up a number like say 874f in my brain for a negative either, but doing 10000 - 874f on calculator gives - 78b1 (- 30897 in decimal).

The wiki writeup has a much more complicated (but technically correct) way of doing it by bit flipping bits around. This is a lot simpler.

Spreadsheets - I think jsa has done this kind of thing across a few bins, so he may be able to help.
tvrfan
Posts: 84
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 »

How multiple adress mode opcodes work - using same numbers as much as possible
note bottom 2 bits define the address mode (0-3), and extra options have a 1 (are odd) in first following byte, stripped off for register address

ldb, load byte.

Code: Select all

 b0,46,50            ldb   R50,R46          R50 = R46;      register    : 1 
 b1,46,50            ldb   R50,46           R50 = 46;       immediate   : 2
 b2,46,50            ldb   R50,[R46]        R50 = [R46]     indirect    : 3
 b2,47,50            ldb   R50,[R46++]      R50 = [R46++]   indirect    : 4
 b3,46,31,50         ldb   R50,[R46+31]     R50 = [R46+31]  indexed byte   : 5
 b3,46,cf,50         ldb   R50,[R46-31]     R50 = [R46-31]  indexed byte   : 6
 b3,47,00,31,50      ldb   R50,[R46+31]     R50 = [R46+31]  indexed word   : 7
1 contents of R46 are copied into R50 (1 byte)
2 the value of 46 is loaded into R50 (1 byte)
3 the byte value in address pointed to by R46 is loaded into R50. R46 is a WORD POINTER (i.e R47,R46 made into a word)
4 as 3 but with with auto increment, as previous, but (WORD) R46 is incremented by 1 after operation.
5 the byte value of 31 (the 'index') is added to the value in R47,R46 (as WORD) and result is used as a pointer to get the value to be loaded in R50. The index is a SIGNED BYTE.
6 as 5) but index is MINUS 31
7 the word value of 0031 ('index') is added to the value in R47,R46 (as WORD) and result is used as a pointer to get the value to be loaded in R50. The index is an UNSIGNED WORD.


ldw, load word.

Code: Select all

 a0,46,50            ldw   R50,R46          R50 = R46;      register    : 1 
 a1,46,00,50         ldw   R50,46           R50 = 46;       immediate   : 2
 a2,46,50            ldw   R50,[R46]        R50 = [R46]     indirect    : 3
 a2,47,50            ldw   R50,[R46++]      R50 = [R46++]   indirect    : 4
 a3,46,31,50         ldw   R50,[R46+31]     R50 = [R46+31]  indexed byte  : 5
 a3,46,cf,50         ldw   R50,[R46-31]     R50 = [R46-31]  indexed byte  : 6
 a3,47,00,31,50      ldw   R50,[R46+31]     R50 = [R46+31]  indexed word  : 7
1 contents of R47,R46 are copied into R51,R50 (1 word)
2 the value of 0046 (word) is loaded into R51,R50 (1 word)
3 the word value in address pointed to by R46 is loaded into R51,R50. R46 is a WORD POINTER (i.e R47,R46 made into a word)
4 as 3 but with with auto increment, as previous, but (WORD) R46 is incremented by 2 after operation.
5 the value of 31 (the 'index') is added to the value in R47,R46 (as WORD) and result is used as a pointer to get the value to be loaded in R51,R50. The index is a SIGNED BYTE.
6 as 5) but index is MINUS 31
7 the value of 31 (the 'index') is added to the value in R47,R46 (as WORD) and result is used as a pointer to get the value to be loaded in R51,R50. The index is an UNSIGNED WORD.

Hope that explains some.
jsa
Posts: 260
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 Oct 31, 11:39 I am having issues determining how to get to the sym 276 from the Rd4+f6.
Ok, SAD does the calculation correctly, Is it just a case of wanting to understand how?

Code: Select all

82438: c7,d4,f6,36        stb   R36,[Rd4+f6]     R276 = R36;                       # [276]  # = 0x8
82438: c7,d4,f6,36        stb   R36,[Rd4+f6]     SPI_BIT_TRANSFER_RATE = R36;      # [276]  # = 0x8
For example, Rd4= 280, f6 converted to decimal= 246, so it looks to me like it would be 280+246 which equals 526, convert that to hex and get 20e. But your entry says 276. So I know I am doing something wrong, just not sure what yet.

Rd4=0x280=dec 640 the base address is unsigned.
0xf6=dec -10 the offset is signed. If you look up the opcode in the software manual, you should find it tells you the offset is signed.

640-10=dec 630 = 0x276 unsigned. The address result is unsigned.

I've used the Windows calculator in programmer mode to do the conversions.
TVRfan has shown how to do the 0x100-F6 method.

This might help. I might have another if I can find it later.
Signed Binary.xlsx
(10.9 KiB) Downloaded 51 times

The R52+be1a is confusing as well because I was thinking that R52=FGTMP5L,

I'm not finding R52+be1a in EQE3, what address is that at?
I do see R52 being loaded with lots of different values. R52 is being used as a scratch register.

0xbe1a = dec -16870 it's an offset so it's signed.
Also I wanted to make sure I understand the entries like B6_R34, Is this saying R34 located in Bank 6? as opposed to R34 in another bank? I thought there were only banks 0, 1, 8, and 9?
Just like the SYM option, B is bit.
B5_RC6

Code: Select all

SYM    C6 "FFG_MAF?"                      :B5 #
Any reason you chose byt over sym?
I was wondering that myself actually. I originally chose sym when entering it in the dir file, but found the same entry in the RZASA dir used byt. That is one of the things I also was going to research. But if you could explain it It may make more sense to me than if I found it in the documentation. Should I have stayed with the sym command?
If a block of hex had bytes that SAD did not discover, then BYT will force SAD to break out the byte/s from the hex block.
It can be named with the byte command or the SYM command. SYM will not break up a hex block.

More later.
BOOSTEDEVERYTHING
Posts: 217
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 »

BOOSTEDEVERYTHING wrote: ↑2023 Oct 31, 11:39
I am having issues determining how to get to the sym 276 from the Rd4+f6.
Ok, SAD does the calculation correctly, Is it just a case of wanting to understand how?
Yes, for the times when SAD has not yet done the calculations, maybe because an rbase has not been defined yet maybe? Or so I can at least know how SAD got to the result. Shortcuts are good but I want to try and understand this as best as I can.
I'm not finding R52+be1a in EQE3, what address is that at?
Sorry, That is my fault. I can't read my own writing,LOL. It is supposed to be R52+6e1a. I was comparing it in some code in RZASA and it looked like it could be DARC_OUT_IMA_L, but I was confused on how to get there due to the temporary register.
f a block of hex had bytes that SAD did not discover, then BYT will force SAD to break out the byte/s from the hex block.
It can be named with the byte command or the SYM command. SYM will not break up a hex block.
So, was it correct to choose the byte command over sym, or should I have stayed with the sym command? And how do I know when to use each? I couldn't find much info in the SAD manual about the byte command that explained why to use it. Maybe I missed it?
Thanks, I will take a look at the spreadsheet when I get home tonight and see if it helps.
BOOSTEDEVERYTHING
Posts: 217
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 »

ldb, load byte.
CODE: SELECT ALL

b0,46,50 ldb R50,R46 R50 = R46; register : 1
b1,46,50 ldb R50,46 R50 = 46; immediate : 2
b2,46,50 ldb R50,[R46] R50 = [R46] indirect : 3
b2,47,50 ldb R50,[R46++] R50 = [R46++] indirect : 4
b3,46,31,50 ldb R50,[R46+31] R50 = [R46+31] indexed byte : 5
b3,46,cf,50 ldb R50,[R46-31] R50 = [R46-31] indexed byte : 6
b3,47,00,31,50 ldb R50,[R46+31] R50 = [R46+31] indexed word : 7
1 contents of R46 are copied into R50 (1 byte)
2 the value of 46 is loaded into R50 (1 byte)
3 the byte value in address pointed to by R46 is loaded into R50. R46 is a WORD POINTER (i.e R47,R46 made into a word)
4 as 3 but with with auto increment, as previous, but (WORD) R46 is incremented by 1 after operation.
5 the byte value of 31 (the 'index') is added to the value in R47,R46 (as WORD) and result is used as a pointer to get the value to be loaded in R50. The index is a SIGNED BYTE.
6 as 5) but index is MINUS 31
7 the word value of 0031 ('index') is added to the value in R47,R46 (as WORD) and result is used as a pointer to get the value to be loaded in R50. The index is an UNSIGNED WORD.
So, In this example, Is R50 being overwritten every line or is it being added to in every line? If R50=R46 that means whatever value is in R46 is now in R50, but then it says that R50 is 46, does that mean that it changed it to a value of 46 instead of what is in R46?
3 the byte value in address pointed to by R46 is loaded into R50. R46 is a WORD POINTER (i.e R47,R46 made into a word)
How do I know it is R46 and R47, or that R46 is a word pointer? Sorry if I should know this, It is a lot of info and I have to keep going back to the docs and trying to find the answers, but sometimes the "engineer speak" in the manuals doesn't make any sense to me either.
4 as 3 but with with auto increment, as previous, but (WORD) R46 is incremented by 1 after operation.
So the ++ after a value means (+ one value, or one byte)? Am I getting that right? instead of adding a number to a value it just moves it up one address? EX: R46++ moves it to R47 or does it Take the value in R46 and add 1 to it? EX: say R46 is 1122, it goes to 1123? A word value is 4 digits and a byte is 2? Is that also correct? Sorry again if these questions frustrate you. I am honestly trying to learn this.
BOOSTEDEVERYTHING
Posts: 217
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 »

Tvrfan, how does SAD add signed and unsigned numbers together, and determine the difference between the two? Is there a formula it uses that could be put in a spreadsheet or separate program to use for this type of thing? Or am I overthinking this and it is pointless to have something like that for disassembly? I was wanting to be able to have something tp use to do the calculations in an already broken out lst file maybe, like RZASA. One example is ldb R44,[R0+a18] is broken out to TMP9L=P0740STATE.
So if I want to know what the actual address is I have to look for it in a file run through sad with a partial directive file with just the Rbase stuff in it to figure out what the address is. I was thinking it would be nice to have something I could put the R0+a18 into and get the address number while looking at the files to compare. Again, maybe I am overthinking this a bit? I may be. Maybe the rbase stuff needs to be broken out before finding actual addresses anyways.
tvrfan
Posts: 84
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 »

In code example, the opcode is LDB or LDW which will always overwrite what's in the target (R50). Every line overwrites R50 in my example.
Check the address TYPE as shown in the description, in an immediate, it loads an absolute value, in position 1, in this case 46.
By hardware design, for R50 in an opcode, a single byte operation would be R50. A word operation is R51,R50, with R51 having the UPPER byte. Some operations (like MULTiply) return a LONG which is 4 bytes , which would be R53,R52,R51,R50.

++ again notice that for a byte it adds one, for a word it adds 2 so it's by one value. NO it does not move R46, it adds to the VALUE in R46, as R46 is a pointer in that opcode.

A lot of people have trouble with the idea of pointers - basically you load a value into a register and then it uses that value as an address, which is why indirects are always WORD. The increment adds to the VALUE in R46. This is R46 saying "look - there's my data, over there....", and ++ is "and there's the next one"

SIGNED AND UNSIGNED additions - Oh bugger.... That's really hard to explain in simple terms. For most operations the CPU doesn't care, because the way that 'two complement" trick works, it doesn't need to. (Yes, really true, what I said about clever design....). In the manual go and have a look at the "PSW - Processor Status Word". That has a set of 'condition flags' which are reset after an addition. Those flags in combinations are then used for both signed and unsigned checks and jumps. So SAD doesn't know unless it's defined already (like in the opcodes). Some opcodes set the PSW, but some (like LDW and LDB do not).

As nuts as this sounds, operations like ADD effectively do both signed and unsigned at the same time, because there is no difference to the add logic. It's all done with those PSW flags.

The combination of operation CMPB or CMPW (byte,word) with a JUMP after it,is the other common way to do a check in code. You will see those all over the place. Depending on which jump is used (and there are 16 different ones) that then defines whether the result is signed and unsigned.

As an example without explaining (because it takes a lot of words) CMP followed by JGE, JLT is probably SIGNED, a CMP followed by JNC or JC is probably unsigned.

Have a look at PSW and the opcode descriptions for say ADD and SUBtract, and think about how they work in combination with the flags, and that may help you.

Sorry, but this stuff is definitely well into the TECH universe....
tvrfan
Posts: 84
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 »

Actually, I could rewrite that differently. This might be clearer.

The CPU calc unit treats all calcs internally as unsigned, with a couple of exceptions.

The sign bit comes out correctly for both signed and unsigned calculations, because the way negative numbers are represented (and other tricks).

How - If you imagine the numbers from 0 to 255 as a kind of 'block' of values (for a byte), you can 'remap' that block to represent -128 to +127. (by subtracting -128 from everything.)

All the maths still works just fine.

The calculation also 'wraps', that means that 255+1 = 0 and 0 -1 = 255 (and sets PSW flags for both) and this is used as part of calculation.

That's (sort of) how it works for both at the same time.
jsa
Posts: 260
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 01, 08:16
Sorry, That is my fault. I can't read my own writing,LOL. It is supposed to be R52+6e1a. I was comparing it in some code in RZASA and it looked like it could be DARC_OUT_IMA_L, but I was confused on how to get there due to the temporary register.
Best to paste the line of code up.
EQE3

Code: Select all

02320: b3,53,1a,6e,4c     ldb   R4c,[R52+6e1a]   R4c = [R52+16e1a];
I've not had a chance to compare with RZASA.

Some more code from that Sub 0230E

Code: Select all

0231d: ac,67,52           ldzbw R52,R67          wR52 = yR67;

0236c: 17,52              incb  R52              R52++;

0236e: 99,05,52           cmpb  R52,5            
02371: d3,02              jnc   02375            if (R52 >= 5)  {
02373: 11,52              clrb  R52              R52 = 0; }

02375: c4,67,52           stb   R52,R67          R67 = R52;

0237b: d7,a0              jne   0231d            if (R52 != 5) goto 0231d;
First off 6E1A is between 0x0000 & 0x7FFF so it is a positive value.
TVRFan suggested it is for an address, I agree.

Line 02373 sets R52 = 0, so we are starting at [0+6E1A], add the data bank prefix, = 0x16E1A.
Line 0263C increments R52 by 1 on each loop.
Line 02371 skips Line 02373 while R52 = 0 through 4.
Line 02375 stores the current value of R52 so that it can be loaded back at Line 0231D.
Line 0237B loops back to Line 0231D until R52 = 5, that is the loop stop. R52 = 0 through 4 will be processed.

EQE3 before adding to DIR

Code: Select all

16e1a: fe                 byte     fe

16e1b: fd,fb,f7,7f        ???   

Add this to your EQE3 DIR

Code: Select all

RBA    52 00 0230E 02382                  #   # Temp Rbase Sub 0230E

BYT 16E14 16E23                             # Sub 0230E


LST should look like

Code: Select all

02320: b3,53,1a,6e,4c     ldb   R4c,[R52+6e1a]   R4c = [16e1a];

16e14: cc                 byte     cc
16e15: cc                 byte     cc
16e16: df                 byte     df
16e17: fe                 byte     fe
16e18: ff                 byte     ff
16e19: ff                 byte     ff
16e1a: fe                 byte     fe
16e1b: fd                 byte     fd
16e1c: fb                 byte     fb
16e1d: f7                 byte     f7
16e1e: 7f                 byte     7f
16e1f: 01                 byte      1
16e20: 02                 byte      2
16e21: 04                 byte      4
16e22: 08                 byte      8
16e23: 80                 byte     80
16e24: 00                 byte      0
So, was it correct to choose the byte command over sym, or should I have stayed with the sym command? And how do I know when to use each? I couldn't find much info in the SAD manual about the byte command that explained why to use it.
If it works, it's correct.
The above is a classic example of using BYT to break them out from a block. I put the command under Bank 1 Commands.
I have not named them or commented them yet. If names are applied, I'd use SYM in the SFTP section of the DIR.
This decouples having to know the name right away from knowing there are a series of bytes attributed to a subroutine.

This SAD manual is not overly prescriptive. The idea is to give as much flexibility as possible for the user to apply the commands.
Post Reply