execute run-time generated asm code
Posted: Thu Oct 20, 2022 1:48 pm
Hello all
I need to generate and execute assembly code at runtime on my ESP8266 wemos D1 mini devboard, for real time reasons (I need it to be asm as it is runtime generated).
I wrote an example code to understand basics of the assembly instruction set (and used the ISA doc), then dumped the obj file using xtensa-lx106-elf-objdump.exe -S. Next step was to write the binary code inside a byte array (this is array is bound to contain runtime generated data in a future step). I then create a function pointer that points to this binary data and execute the function.
But when I do this, I get an exception each time the function is called.
Here is the exception contents (with decoder data):
_sendData calls _sendSingleLED and not millis, so I guess the call stack is wrong. _sendSingleLED calls my binary code, in this array :
First I thought this was a problem of endianess, so I inverted the bytes of every instruction, and I also tried to keep only the ret.i instruction. I actually don't know if the instruction fetch unit takes the bytes one my one (and thus I shall not use little endian) or not.
Also, I wonder if the issue is due to the fact my code is in a static region of the code, and need to be placed elsewhere so it can be executed (the PC register points to an invalid location, as the exception message may suggest)
I'll try coping the binary code in a dynamically allocated region and execute it from here to see if that fixes my problem (runtime generated code will be in heap memory anyways), while waiting for some help.
Does someone have an idea of what is actually wrong? Do you know documentation or information I may use to make this work? Thanks in advance!
I need to generate and execute assembly code at runtime on my ESP8266 wemos D1 mini devboard, for real time reasons (I need it to be asm as it is runtime generated).
I wrote an example code to understand basics of the assembly instruction set (and used the ISA doc), then dumped the obj file using xtensa-lx106-elf-objdump.exe -S. Next step was to write the binary code inside a byte array (this is array is bound to contain runtime generated data in a future step). I then create a function pointer that points to this binary data and execute the function.
But when I do this, I get an exception each time the function is called.
Here is the exception contents (with decoder data):
Code: Select all
20:24:55.258 > --------------- CUT HERE FOR EXCEPTION DECODER ---------------
20:24:55.323 >
20:24:55.323 > Exception (2):
20:24:55.323 > epc1=0x3ffe85d0 epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffe85d0 depc=0x00000000
20:24:55.423 >
20:24:55.423 > InstructionFetchError: Processor internal physical address or data error during instruction fetch
20:24:55.423 >
20:24:55.423 > >>>stack>>>
20:24:55.423 >
20:24:55.423 > ctx: cont
20:24:55.457 > sp: 3ffffdc0 end: 3fffffc0 offset: 0190
20:24:55.490 > 3fffff50: 00000fbc 29bf1c55 401002f1 00000000
20:24:55.562 > 3fffff60: 0012323f 00000000 00001388 402014d8
20:24:55.624 > 3fffff70: 00123239 3ffeead0 00000003 40201584
20:24:55.694 > 3fffff80: 3fffdad0 00000000 3ffeead0 402015b9
20:24:55.721 > 3fffff90: 3fffdad0 00000000 00000fbc 40207440
20:24:55.807 > 3fffffa0: feefeffe feefeffe 3ffe8618 4020dad6
20:24:55.833 > 3fffffb0: feefeffe feefeffe feefeffe 40100f4d
20:24:55.891 > <<<stack<<<
20:24:55.891 >
20:24:55.891 > 0x401002f1 in millis at C:\Users\axiagame\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_wiring.cpp:188
20:24:55.891 > 0x402014d8 in WS2812B::_sendData() at src/WS2812B.cpp:159 (discriminator 2)
20:24:55.891 > 0x40201584 in WS2812B::_doTestMode() at src/WS2812B.cpp:155
20:24:55.891 > 0x402015b9 in WS2812B::loop() at src/WS2812B.cpp:106
20:24:55.891 > 0x40207440 in loop at src/main.cpp:62
20:24:55.891 > 0x4020dad6 in loop_wrapper() at C:\Users\axiagame\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:201
20:24:55.891 > 0x40100f4d in cont_wrapper at C:\Users\axiagame\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/cont.S:81
20:24:55.891 >
20:24:55.891 >
20:24:55.891 > --------------- CUT HERE FOR EXCEPTION DECODER ---------------
_sendData calls _sendSingleLED and not millis, so I guess the call stack is wrong. _sendSingleLED calls my binary code, in this array :
Code: Select all
// contains
// noInterrupts();
// u32 ccount = 0;
// u32 curccount = 0;
// u32 lastWait = 0;
// u32 pinID = 1 << m_dataPin;
// u32 notPinID = ~pinID;
// u32 * outReg = (u32*)0x60000300;
// for (u32 b = 24; b > 0; --b)
// {
// *outReg |= pinID;
// *outReg &= notPinID;
// }
// interrupts();
static u8 functionCodeAndData[] =
{
0x00, 0x03, 0x00, 0x60, // 0x60000300, GPIO output register
0x30, 0x6f, 0x00, // rsil a3, 15
0x22, 0x02, 0x12, // l8ui a2, a2, 18 // offset of m_dataPin in class
// A2 contains m_dataPin
0x0c, 0x15, // movi.n a5, 1
0x00, 0x12, 0x40, // ssl a2
0x00, 0x55, 0xa1, // sll a5, a5
// A5 contains pinID
0x7c, 0xf6, // mov.i a6, -1
0x50, 0x66, 0x30, // xor a6, a6, a5
// A6 contains notPinID
0x1c, 0x84, // movi.n a4, 24 // prepare loop count
// A4 contains loop count
0x9c, 0x24, // beqz.n a4, 30
// jump when A4 = 0
0x31, 0xf9, 0xff, // l32r a3, 4 // address of register in which to write pin data
// A3 contains pin register address
0x28, 0x03, // l32i.n a2, a3, 0
// A2 contains data in pin register
0x20, 0x25, 0x20, // or a2, a5, a2
// set pinID bit
0x29, 0x03, // s32i.n a2, a3, 0
// store new pin data in register
0x60, 0x22, 0x10, // and a2, a2, a6
// clear pinID bit
0x29, 0x03, // s32i.n a2, a3, 0
// store new pin data in register
0x0b, 0x44, // addi.n a4, a4, -1
// decrement loop counter
0x46, 0xfa, 0xff, // j 19 // start of loop
0x20, 0x60, 0x00, // rsil a2, 0
0x0d, 0xf0, // ret.n
//0x3D, 0xF0, // nop.n
};
First I thought this was a problem of endianess, so I inverted the bytes of every instruction, and I also tried to keep only the ret.i instruction. I actually don't know if the instruction fetch unit takes the bytes one my one (and thus I shall not use little endian) or not.
Also, I wonder if the issue is due to the fact my code is in a static region of the code, and need to be placed elsewhere so it can be executed (the PC register points to an invalid location, as the exception message may suggest)
I'll try coping the binary code in a dynamically allocated region and execute it from here to see if that fixes my problem (runtime generated code will be in heap memory anyways), while waiting for some help.
Does someone have an idea of what is actually wrong? Do you know documentation or information I may use to make this work? Thanks in advance!