[NTLK] Einstein 64-bit

Matthias Melcher mm at matthiasm.com
Wed Dec 3 15:50:00 EST 2014

> On Dec 3, 2014, at 7:11 PM, Steven Frank <stevenf at panic.com> wrote:
>> On Dec 3, 2014, at 8:55 AM, Morgan Aldridge <morgant at makkintosshu.com> wrote:
>> While I haven't looked at the Einstein source to confirm, the fact
>> that Paul Guyot contributed NativeCalls to NEWT/0 and that the
>> functionality mimics the "Relativity" feature he built for Einstein
>> (see <http://wwnc.newtontalk.net/resources/WWNC2006_Guyot_EinsteinRelativity.pdf>),
>> I'd guess that would be at least on reason for the use.
> After spending some quality time with the Einstein source last night,

It's always quality time with Pauls code. Mine, I am not so sure about :-P

> I learned that there are several ways that functions can be patched and bridged between the virtual Newton and the host OS.
> -- TROMPatch (defined in TROMImage.h)
> These appear to just overwrite the ARM opcodes in ROM with new ARM opcodes.

> For example, in TROMImage.cp, we see this:
> TROMPatch p000db0dc(0x000db0dc, 0xe1a0f00e, "BeaconDetect (2/2)"); // #  mov pc, lr
> This writes the 32-bit value 0xe1a0f00e at ROM address 0x000dbodc, overwriting its previous value.  0xe1a0f00e is an ARM opcode for "mov pc, lr" (as mentioned in the comment), which is the way ARM returns from function calls.  So, if Einstein tries to execute ROM code at 0x000dbodc, it just returns immediately instead of trying to do whatever it does on a real Newton.

Correct. There are two different interfaces of native code into Newton ARM code. The TROMPatch way and all its decedents work by either simply replacing one assembler Word with another one (TROMPatch), or by replacing a Word with an SWI call with the high bits set. That way, I can transparently inject native code into the ROM (after running the native code, the original instruction at the patched location is executed). Or an entire function can be replace by native code. In that case, the original code is no longer executed.

My current local version includes SIM patches. These patches allow native code anywhere which in turn can call emulated code again. But that still needs to be committed to the repository.

> -- Virtualization patches
> These appear to be a means of transferring control to a host-native function when the emulated ARM processor goes to execute code at a certain address.  These are defined in a table called k717006VirtualizationPatches at the top of TROMImage.cp.  A single virtualization patch looks something like this:
> const KUInt32 k717006VirtualizationPatches[] = {
> 	/* ... */
> 	0x00358C9C / sizeof(KUInt32),	TVirtualizedCallsPatches::ksymcmp__FPcT1,
> };	
> Here, 0x00358C9C is the address of the ROM function symcmp(char*, char*).  When Einstein goes to execute code at address 0x00358C9C, it sees this patch and transfers control to TVirtualizedCalls::Execute() (in TVirtualizedCalls.cp) which then dispatches it to symcmp__FPcT1(), which provides a host-native implementation of symcmp() that doesn't require ARM emulation.

This is Pauls original way to patch the ROM. It does something very similar to what I do, but I hadn't understood the code, needed a quick fix, and so I wrote my own - bad habit, sorry about that. The advantage of my version is the launch time instantiation of the patches. So by simply linking another module, all patches in that module are activated. There is no need to change any code.

> -- T_ROM_INJECTION (defined in TROMImage.h)
> ROM injections appear to allow some host-native code to execute before (or after?) running the original ROM code,

Correct. The native code runs first. Then the original ARM instruction is executed. 

> -- TNativeCalls
> This is where ffi appears...
> I think what this does is load a host-native dylib/DLL and expose the functions it contains to the virtual Newton.  So, if you have a library (I notice that libresolv is included in the Xcode project), it'll load that and bridge those functions into the virtual Newton with the same function names?
> Am I close?  :)

That is pretty much it, yes. libffi translates from one way to call library function into another way. In this case, NewtonOS can directly load, link, and call any external library without Einstein needing to know about that. In the example, you can write a NewtonScript app that call "FILE" style function on the host (fopen, fread, etc.)


More information about the NewtonTalk mailing list