MONO crosscompile mit Freetz

@RalfFrieldl: Scheint so, aber es kümmert sich wohl auch keiner darum. Ist ja community gepflegt.

Was habe ich getan:
ACHTUNG: Das ist nur zum Test gewesen und ist nicht als Empfehlung gedacht. Denn die Änderung zerstört andere Platformen:

Code:
 case OP_LMOVE:
 case OP_LCONV_TO_U8:
 case OP_LCONV_TO_I8:
 case OP_LCONV_TO_OVF_U8_UN:
 case OP_LCONV_TO_OVF_I8:
    MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 1, tree->sreg1 + 2);
    MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, tree->dreg + 2, tree->sreg1 + 1);
    break;
decompose.c ca. Zeile 580.

Die Korrektur wird definitiv anders aussehen.
 
Ich kenne mich mit Mono und der dazugehörigen Maschine nicht so aus, aber das sieht nach einem Word Swap aus.
Die Lösung wäre, die Anweisungen, die generiert werden, dazu zu bringen, dass sie das richtige Ergebnis produzieren, nicht Anweisungen dahinter zu setzen, die das wieder in Ordnung bringen.
 
@RalfFriedl: Der Decomposer hat die Aufgabe die CIL-Stack-Maschine in die Zielplatform zu konvertieren. Sprich hier wird der gedachte Stack aufgelöst. Es wird hier nichts getauscht, sondern nur eine Variable bewegt (8 byte). Ich hab jetzt gemeinerweise ms und ls getauscht. Wie ich gesagt habe das ist vermutl. nicht die Lösung. Da damit die z.B. x86-Platform nicht mehr funktionieren würde.
 
Nur mal aus Neugierde, was passiert mit der Änderung bei diesem Programm:
Code:
int i = 1;
long a = i;
long b = a;
Console.WriteLine ("Test: 0x{0:X8}, 0x{1:X8}", a, b);
 
Ergebnis auf meiner Box:
Code:
Test: 0x00000001, 0x00000001

CIL:
Code:
	IL_0016: ldc.i4.1
	IL_0017: stloc.0
	IL_0018: ldloc.0
	IL_0019: conv.i8 <-- hier setze ich an
	IL_001a: stloc.1
	IL_001b: ldloc.1
	IL_001c: stloc.2
	IL_001d: ldstr "Test: 0x{0:X8}, 0x{1:X8}"
	IL_0022: ldloc.1
	IL_0023: box [mscorlib]System.Int64
	IL_0028: ldloc.2
	IL_0029: box [mscorlib]System.Int64
	IL_002e: call void [mscorlib]System.Console::WriteLine(string, object, object)
Ich lese aber noch Code und Doku.
 
Ich hätte vermutet, dass OP_LMOVE verwendet wird, um long zuzuweisen, es sieht aber nicht so aus.
Was ist denn das Ergebnis von ldc.i4.1 und was muss bei der Konvertierung überhaupt noch geändert werden?
 
Das ist der CIL das hat noch nix mit dem OP_LMOVE zu tun.

Der Composer hat ja die Aufgabe jeden Stackbefehl in eine Registerform zu bringen. Das geschieht über einige Iterationen (z.B. automatische long -> int Konvertierung).

Die OP_LMOVE Sequence wird vom conv.i8 erzeugt. Ist ja logisch; ldc.i4.1 legt eine 1 auf den Stack/Register (4byte). Wir brauchen aber einen 8byte Wert (conv.i8 ), also müssen noch mal 4 byte aufgeschoben werden. Also wird eine 4 byte 0 generiert (OP_?) und die werden dem 8 byte zugewiesen, die zwei OP_LMOVE Befehle.

Auf Windows läuft es meist so CIL (conv.i8 ) -> Zwischencode (OP_MOVE) -> Platformcode (mov eax, ecx, ...). Scheint ähnlich zu sein.

Literaturhinweis:
http://en.wikipedia.org/wiki/Dragon_Book
 
Zuletzt bearbeitet:
Ich hätte vermutet, dass conv.i8 ein OP_LCONV_TO_U8 erzeugt. ldc.i4.1 bringt etwas auf den Stack, das mit stloc.0 gelesen wird. Das scheint der gleiche Befehl zu sein wie stloc.1, also keine Unterscheidung zwischen i4 und i8. Die ursprüngliche Form, also bevor Du die Hälften getauscht hast, nimmt auch nur die beiden Hälften von der Quelle und speichert sie unverändert ins Ziel. So wie es aussieht, erwartet Mono als Ergebnis vom ldc.i4.1 direkt einen i8 Wert, den es bei conv.i8 unverändert übernehmen kann. Das ist aber hier nicht der Fall.
 
... dass conv.i8 ein OP_LCONV_TO_U8 erzeugt...

Genau das hatte ich erst auch gedacht. Im CIL gibt es aber kein LMove und kein ConvToU8, ergo ist hier klassisch noch was dazwischen.

Stloc schreibt den Wert vom Stack in eine Variable (Stackposition 0).
Ldloc lädt den selbigen auf den Stack.
Ldc legt eine Konstante ab. i4 steht für 4 byte.
Conc.i8 schiebt gedanklich noch mal 4 drauf.
 
Soweit schon klar, aber das ist nicht das, was passiert. conv.i8 erzeugt keine Konvertierung von i4 nach i8, sondern kopiert i8. Folglich wird davon ausgegangen, dass ldc.i4.1 direkt aus einer i4 Konstanten einen i8 Wert auf dem Stack schreibt. Aber das passiert bei MIPS anscheinend nicht, bzw. es passiert vertauscht.
Was passiert denn bei einer Integer Multiplikation, also "i = 2; i = i * i;"?
 
Nicht vergessen wir befinden uns nur in dem Schritt, wo die 64bit Operation in 32 bit umgewandelt werden.

Ich hab jetzt auch den Übeltäter gefunden, ich versuche nur noch die Details zu verstehen.
conv.i8 erzeugt einen neuen Wert, der die fehlenden 4 Byte auffüllt, aber in der falschen Reihenfolge. Das scheint aber so weit in Ordnung, da ich vermute das die L-Operationen alle Little Endian implementiert sind und nur an den Konvertierungen geschraubt werden muss (da Schau ich noch).
 
Denkst Du es gibt Aussicht auf eine Lösung? Das wäre wirklich eine tolle Sache, wenn mono funktionieren würde....
 
Weiß ich noch nicht. Prinzipiell ja.
Ich werde mal am Wochenende ein bisschen Zeit investieren, mich interessiert wie die Ablauf vom IL zum Maschinencode ist ;).

Zur Zeit bin ich soweit, das eigentlich alles richtig aussieht (ohne meine Änderung). Genau kann ich es nicht sagen, da dieser Part extrem schwach dokumentiert ist. Man muss sich alles aus den Quellen erschließen und die sind für mich fürchterlich zu lesen.
 
Danke für Deinen Einsatz! Ich muss gestehen das übersteigt mein Niveau bei weitem. Ich habe zwar langjährige C# Erfahrung und ein bisschen C, aber keinen Plan vom Compilerbau... Deshalb bin ich Dir jetzt schon sehr dankbar, dass Du hier Zeit investierst!
 
Es sieht schlecht aus. Die Übersetzung des IL zu Maschinencode hab ich soweit durchschaut. Auf der Zwischencodebasis scheint alles sauber zu laufen. Der kleine Hack von mir ist definitiv falsch, da ich die ganzen Überläufe zerstöre.

Programm:
Code:
long b = 0x201;
int* a = (int*)(void*)&b;
int ms = *a;
int ls = *(a + 1);
Console.WriteLine ("Test: ms=0x{0:X}, ls=0x{1:X}, 0x{2:X}", ms, ls, b);

Zwischencode mit Kommentaren, vor dem Assembler:
Code:
long b
	0x10
	0x14
int ms
	0x34
int ls
	0x30

long b = 0x201;
    @ 0x4c		8  iconst v0 <- [513]
    @ 0x50		9  storei4_membase_reg [sp + 0x14] <- v0
    @ 0x54		10 storei4_membase_reg [sp + 0x10] <- zero
    
int* a = (int*)(void*)&b;
    @ 0x58		11 add_imm v0 <- sp [16]
    @ 0x5c		12 move v1 <- v0
    
int ms = *a;
    @ 0x60		13 loadi4_membase v1 <- [v1 + 0x0]
    @ 0x64		14 store_membase_reg [sp + 0x34] <- v1

a = a + 1
    @ 0x68		15 int_add_imm v0 <- v0 [4]
    
int ls = *a;
    @ 0x6c		16 loadi4_membase v0 <- [v0 + 0x0]
    @ 0x70		17 store_membase_reg [sp + 0x30] <- v0
    
0x28 = box parameter arg0 ms
    @ 0x74		18 iconst a0 <- [10279780]
    @ 0x7c		19 call v0 <- [mono_object_new_ptrfree_box] [a0 <- R64] clobbers: c
    @ 0x8c		20 load_membase v1 <- [sp + 0x34]
    @ 0x90		21 storei4_membase_reg [v0 + 0x8] <- v1
    @ 0x94		22 store_membase_reg [sp + 0x28] <- v0
    
0x2C = box parameter arg1 ls
    @ 0x98		23 iconst a0 <- [10279780]
    @ 0xa0		24 call v0 <- [mono_object_new_ptrfree_box] [a0 <- R68] clobbers: c
    @ 0xb0		25 load_membase v1 <- [sp + 0x30]
    @ 0xb4		26 storei4_membase_reg [v0 + 0x8] <- v1
    @ 0xb8		27 store_membase_reg [sp + 0x2c] <- v0
    
box parameter arg2 b   
    @ 0xbc		28 loadi4_membase v0 <- [sp + 0x14]
    @ 0xc0		29 store_membase_reg [sp + 0x20] <- v0 -- 0x20 hat 0x201
    @ 0xc4		30 loadi4_membase v0 <- [sp + 0x10]
    @ 0xc8		31 store_membase_reg [sp + 0x24] <- v0
    @ 0xcc		32 iconst a0 <- [10280732]
    @ 0xd4		33 call v0 <- [mono_object_new_ptrfree_box] [a0 <- R74] clobbers: c
    @ 0xe4		34 move a3 <- v0
    @ 0xe8		35 load_membase v0 <- [sp + 0x20]
    @ 0xec		36 load_membase v1 <- [sp + 0x24]
    @ 0xf0		37 load_membase a1 <- [sp + 0x28]
    @ 0xf4		38 load_membase a2 <- [sp + 0x2c]
    @ 0xf8		39 storei4_membase_reg [a3 + 0x8] <- v1
    @ 0xfc		40 storei4_membase_reg [a3 + 0xc] <- v0
    
    @ 0x100		41 iconst a0 <- [716492640]
    @ 0x108		42 voidcall [System.Console:WriteLine (string,object,object,object)] [a0 <- R75] [a1 <- R76] [a2 <- R77] [a3 <- R78] clobbers: c

Für mich sieht das gut aus. Aber ich erhalte folgendes Ergebnis:
Code:
Hello World False!
Test: ms=0x0, ls=0x0, 0x20100000000

Die zwei 0-Werte kann ich mir nicht erklären. Sieht jemand Probleme?

Um tiefer in das Problem einzutauchen, müsste man den Maschinencode untersuchen. Dazu bräuchte man eine Box die man rein für Entwicklungszwecke präparieren müsste (Compiler, Linker, Assembler, Debugger, mini-mono). Leider brauche ich meine für das täglich Internet :(.
 
Hört sich nicht so gut an....
Kann man vielleicht per QEMU eine Fritzbox simulieren?
 
Nur die "allerersten" FBs (die ohne Nummern) lassen sich so halbwegs (q)emulieren.
Aber da es ja scheinbar ein "normales" Mips(el) Problem ist (das "gleiche Problem" im Mips Umfeld findest sich auch sonst per Goolge), könnte man es in einer "normalen" qemu Mips-Umgebung testen. Da hätte man dann z.B. ein vollständiges Debian oder so als Grundlage...
 
Für mich sieht das gut aus. Aber ich erhalte folgendes Ergebnis:
Code:
Hello World False!
Test: ms=0x0, ls=0x0, 0x20100000000
Ist das oben mit oder ohne Deinen Swap? Ändere das mal auf "b = 0x12345678", was kommt dann heraus?
Um tiefer in das Problem einzutauchen, müsste man den Maschinencode untersuchen. Dazu bräuchte man eine Box die man rein für Entwicklungszwecke präparieren müsste (Compiler, Linker, Assembler, Debugger, mini-mono).
Kann Mono denn den erzeugten Maschinencode speichern? Dann könnte man den auch auf einem anderen Gerät anschauen.

Im Link aus #40 steht auch: "Note that MIPS is not a supported mono architecture".
Von daher ist es schon seltsam, dass überhaupt etwas läuft. Vermutlich ist damit gemeint, dass es Funktionen dafür gibt, aber keiner der Entwickler sich damit groß beschäftigt.
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.