Title: Tricore Custom Code Post by: superglitch on July 28, 2021, 10:32:59 AM So I'm fairly familiar with IDA Pro and writing assembly, and it's a pain. I'm looking to start utilizing a compiler to help aid in creating more complex functions and reduce effort required to create patching programs to translate to similar ECU software.
I found Hightech's free compiler here: https://free-entry-toolchain.hightec-rt.com/ I do have that working and generating assembly without issue, my issue comes from properly writing code in order to read and write variables correctly. I'll keep it very basic in order so we can create knowledge on how to adapt this to any problem/situation that someone is working on. Here's the C code: Code: #include <tc1767.h> Which does compile and generates this assembly: Code: main: Inserting this code causes the ECU to not respond, requiring boot to restore. Almost as if it's stuck in a loop in the ASW. :'( I have manually written assembly to accomplish the same desired code and can be called without issue: Code: movh.a a9, #@HIS(unk_D000C000) Obviously this is an over simplification of what I'm actually trying to accomplish, but I figure it's best to keep everything simple until I can get the compiler trick to operate correctly so I can actually perform some real functions and math. Any help with the method of writing my C or understanding what is going wrong would be greatly appreciated. Title: Re: Tricore Custom Code Post by: daniel2345 on July 28, 2021, 11:21:46 AM Some Registers are used by generic functions in ASW and some are dedicated to BSW.
It changes from build to build. Try to use other Registers in generated assembler code. Then modify toolchain according correct register usage. Maybe modifications of stack pointer (sp) are also not a good idea, depending on main loop functions or BSW. Title: Re: Tricore Custom Code Post by: nihalot on July 28, 2021, 12:38:19 PM compile the C/C++ code with -mcpu=TC1767 and -O2 or -O3 flags
That way stack ptr is usually avoided by compiler unless absolutely necessary. Title: Re: Tricore Custom Code Post by: superglitch on July 28, 2021, 01:01:38 PM @nihalot that resolved the stack pointer stuff, I am now generating much simpler code
Now we are sitting at Code: movh.a a15, #0xD001 I have not had a chance to test, but what @daniel2345 brings up. it would be best if possible to somehow inform the compiler of existing registers to use, for example if I know the mappings of a0, a1, or a9 throughout the file without the need to modify a15. Though I do think that in this particular binary I'm testing with a15 is safe to be modified in the position I'm placing the code. Is there a better manual out there on the compiler than -v --help? The verbose help output is definitely something everyone should review. Title: Re: Tricore Custom Code Post by: d3irb on July 28, 2021, 01:39:11 PM https://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Global-Reg-Vars.html#Global-Reg-Vars
Yes, the HighTec compiler is just Tricore backend patches to GCC (GNU C Compiler) so there is a wealth of documentation dating back many years. Title: Re: Tricore Custom Code Post by: prj on July 29, 2021, 04:06:26 AM Read TriCore manual and EABI.
You're not gonna get anywhere without. Title: Re: Tricore Custom Code Post by: jcsbanks on July 29, 2021, 08:17:38 AM Apart from the good advice already given, I never tried floats since the OS in my targets doesn't use floats, it might need some initialization that you are not having. You can use the stack though, but it is rarely needed or used when using high -O levels. Don't use a0, a1, a8, a9, your compiler isn't and will generally follow the EABI and work with existing code. Read up on upper and lower contexts, check out the calling conventions using the first variable in d4, first pointer in a4, return variable in d2 and if you are returning a pointer, a2. IIRC you can pass up to 4 variables and 4 pointers before the EABI and the compiler will use the stack.
Title: Re: Tricore Custom Code Post by: Herleybob on August 30, 2021, 11:02:52 PM I use these guidelines when compiling code. 99% of the time I will be patching a function, or jumping out of the end of a call tree into my own code so I can either use the registers that hightec assigns or I can change them out to not modify existing ones. I like to just use a new function per code segment i'm writing because ghidra makes it easy to find it.
You will need to disassemble (obviously) and then inspect the asm before patching. Code: #define CUSTOM_VARIABLE_ONE (*((volatile unsigned char *) 0xD0003F11)) If you don't need to repeatedly call the address, just make a pointer to the address. Code: void COPY_PARAM_TO_RAM() { Also, ive found multiple functions that process 2D and 3D tables, returning varying variables ( chars, shorts, longs, signed, unsigned, etc). I created a faux function that calls to the map interpolation function that i want to use, and give it the same arguments so that i can call it and then just replace the call address when i decompile and patch it in. (hopefully that made sense, im just trying to interpolate my own 2d/3d tables so i use the built in functions). Once I compile it and then disassemble it in Ghidra, i know the call address to the actual interpolation functions, i will replace those in my code asm and verify it is putting the correct variables in the registers before it calls. Code: unsigned char FUNC_PROCESS_2D_TABLE_8BIT(unsigned char AXIS_LENGTH, unsigned char MONITOR ,volatile unsigned char *AXIS_VALUES, volatile unsigned char *TABLE_VALUES) As a final example, i'm working on adding turn signals to a SxS, something that didnt originally come with the function. See below for my code. It might not be 100% correct but it works and give me the least amount of asm. Code: void PROCESS_TURN_SIGNALS() { In the end I will decompile my code, verify the flow looks correct and then patch it in, Make sure it isn't overwriting any registers that are needed, and then try it out. The above code needs 0 modifying before patching in and trying. EDIT: See below for some macros to work with bits. I have needed these quite a bit and just got the storebit working. These will translate into: JZ.T/JNZ.T - For getting a bit ST.T - For storing a bit Code: #define GETBIT(var, bit) (((char)(var) >> (bit)) & 1) |