We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Porting Go to netbsd/ arm 64

00:00

Formale Metadaten

Titel
Porting Go to netbsd/ arm 64
Serientitel
Anzahl der Teile
34
Autor
Lizenz
CC-Namensnennung 3.0 Unported:
Sie dürfen das Werk bzw. den Inhalt zu jedem legalen Zweck nutzen, verändern und in unveränderter oder veränderter Form vervielfältigen, verbreiten und öffentlich zugänglich machen, sofern Sie den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
Identifikatoren
Herausgeber
Erscheinungsjahr
Sprache

Inhaltliche Metadaten

Fachgebiet
Genre
Abstract
Starting out with no knowledge in Go or ARM64, how do you begin porting a language? Go might be one of the hardest languages to port. Having done that, I came back to tell the tale of how. Unusual characteristics of Go Rules to write the 400 lines of assembly code necessary for a port Debugging in the absence of a functional debugger The talk will describe how to start on such a large project, how to find your way around a large unfamiliar codebase, what's a calling convention, how to debug mistakes in your Go port, and some notes about why Go chose to make such strange choices.
DokumentenverwaltungssystemImplementierungProgrammierungFormale SpracheROM <Informatik>Mathematische LogikGebäude <Mathematik>DatenparallelitätBinärdatenHydrostatikDefaultArchitektur <Informatik>Kernel <Informatik>Virtuelle MaschineAssemblerDatenstrukturCompilerBinder <Informatik>CodeStatechartMereologieEreignishorizontGoogolLeistung <Physik>SystemzusammenbruchWort <Informatik>BestimmtheitsmaßSpywareZweiExtreme programmingWellenpaketProjektive EbeneGraphfärbungGüte der AnpassungMAPDatenfeldProzess <Informatik>SystemaufrufARM <Computerarchitektur>Produkt <Mathematik>Formale SpracheKonditionszahlPartikelsystemRelativitätstheorieGesetz <Physik>ImplementierungUmwandlungsenthalpieCompilerBinärcodeNP-hartes ProblemUmsetzung <Informatik>InformationMultiplikationsoperatorQuellcodeInstantiierungProgrammierungCMM <Software Engineering>Vorzeichen <Mathematik>BitWeb SiteBootenAutomatische HandlungsplanungMereologieBinder <Informatik>Lesen <Datenverarbeitung>CodeGebäude <Mathematik>AssemblerAuswahlaxiomSoftwareVersionsverwaltungBildgebendes VerfahrenKernel <Informatik>Minkowski-MetrikBeobachtungsstudieComputeranimationXMLJSON
MereologieVirtuelle MaschineCodeKernel <Informatik>AssemblerCompilerBinder <Informatik>DokumentenverwaltungssystemKoroutineThreadRegulärer GraphOverhead <Kommunikationstechnik>CoprozessorParallelrechnerVerschlingungStrebeSystemaufrufMeterLaufzeitfehlerNichtunterscheidbarkeitInformationsspeicherungStellenringZeiger <Informatik>SchnittmengeFunktion <Mathematik>Interface <Schaltung>Ordnung <Mathematik>InformationGebäude <Mathematik>Message-PassingGemeinsamer SpeicherGüte der AnpassungFamilie <Mathematik>GefangenendilemmaARM <Computerarchitektur>TabelleSystemaufrufGesetz <Physik>InformationsspeicherungResultanteStabilitätstheorie <Logik>StellenringHypermediaBitKonfiguration <Informatik>DreizehnVideo GenieBenutzerschnittstellenverwaltungssystemComputerspielWeg <Topologie>ParametersystemMatchingGoogolCodeKoroutineDifferenteArithmetisches MittelFunktionalEinfügungsdämpfungCompilerGanze FunktionThreadInverser LimesAutomatische HandlungsplanungVerschlingungOverhead <Kommunikationstechnik>Keller <Informatik>URLKernel <Informatik>AssemblerSchedulingGrenzschichtablösungBinder <Informatik>NormalvektorRichtungJensen-MaßJSON
SystemaufrufSpeicherbereinigungOverhead <Kommunikationstechnik>DokumentenverwaltungssystemFehlermeldungZeichenketteEreignishorizontThreadProgrammbibliothekMailing-ListeGanze FunktionLaufzeitfehlerMagnetooptischer SpeicherSupport-Vektor-MaschineImplementierungMUDBildschirmfensterSpeicherabzugSynchronisierungMenütechnikFlächeninhaltBenutzerschnittstellenverwaltungssystemSystemaufrufGruppenoperationGeradeSpieltheoriePhysikalisches SystemObjekt <Kategorie>Konstruktor <Informatik>Fächer <Mathematik>BitrateOrdnung <Mathematik>HypermediaGraphfärbungBildverstehenEinfügungsdämpfungInternetworkingStrömungsrichtungArithmetisches MittelBitParametersystemSingularität <Mathematik>Einfach zusammenhängender RaumAutorisierungElektronischer FingerabdruckCASE <Informatik>MultiplikationsoperatorArithmetischer AusdruckMehrschichten-PerzeptronFunktionalComputerarchitekturSystem FDatensatzTermersetzungssystemKeller <Informatik>CodeThreadPlastikkarteQuaderBootstrap-AggregationE-MailMailing-ListeZahlenbereichElektronische PublikationKorrelationskoeffizientProzess <Informatik>ZweiNormalvektorDatenstrukturCodierungMessage-PassingProgrammbibliothekComputeranimation
DokumentenverwaltungssystemFlächeninhaltKernel <Informatik>ARM <Computerarchitektur>SpielkonsoleGenerizitätBefehlsprozessorWarteschlangeRechenwerkBootenSpeicherabzugWurzel <Mathematik>Physikalisches SystemBimodulEmulatorVersionsverwaltungComputerarchitekturStapeldateiBootstrap-AggregationComputeranimation
DokumentenverwaltungssystemGebäude <Mathematik>Interface <Schaltung>SystemprogrammierungSpeicherabzugCachingDämon <Informatik>Komponente <Software>InformationWurzel <Mathematik>SystemprogrammDatenflussSkriptspracheStapeldateiMathematische LogikBildgebendes VerfahrenGruppenoperationAdressraumRechter WinkelWurzel <Mathematik>Bootstrap-AggregationComputeranimation
DokumentenverwaltungssystemWurzel <Mathematik>VersionsverwaltungVerschlingungARM <Computerarchitektur>Familie <Mathematik>MAPGeradeKartesische KoordinatenCodeBefehl <Informatik>Computeranimation
DokumentenverwaltungssystemVersionsverwaltungCodeVersionsverwaltungStellenringSpeicherabzugRechter WinkelMathematikComputeranimation
DokumentenverwaltungssystemVersionsverwaltungSingularität <Mathematik>ProgrammGanze FunktionLaufzeitfehlerSystemaufrufMagnetooptischer SpeicherSupport-Vektor-MaschineImplementierungEreignishorizontThreadMailing-ListeFunktion <Mathematik>Interface <Schaltung>CodeMereologieVirtuelle MaschineKernel <Informatik>AssemblerCompilerBinder <Informatik>Regulärer GraphOverhead <Kommunikationstechnik>KoroutineSpieltheorieBitHypermediaÄquivalenzklasseAbstimmung <Frequenz>ComputervirusSystemprogrammKette <Mathematik>Amenable GruppeGraphfärbungProgrammierungMereologieIdeal <Mathematik>GruppenoperationNormalvektorTrennschärfe <Statistik>InformationObjekt <Kategorie>Total <Mathematik>Gemeinsamer SpeicherNeuroinformatikZirkel <Instrument>EinfügungsdämpfungOrdnung <Mathematik>Leistung <Physik>KreisflächeBillard <Mathematik>VererbungshierarchieCodeMathematikSchlüsselverwaltungVersionsverwaltungHardwareMultiplikationsoperatorSystemaufrufAssemblerLesen <Datenverarbeitung>Offene MengeVerzweigendes ProgrammPhysikalischer EffektProgrammierspracheCASE <Informatik>GenerizitätFunktion <Mathematik>HilfesystemParametersystemProjektive EbeneZahlenbereichQuick-SortBootstrap-AggregationBinärcodeKartesische KoordinatenRechter WinkelComputeranimation
DokumentenverwaltungssystemWort <Informatik>LaufzeitfehlerDelisches ProblemCodeSoftwareentwicklerSystemplattformBAYESMehrrechnersystemGrundsätze ordnungsmäßiger DatenverarbeitungNichtlinearer OperatorTermComputeranimation
Computeranimation
Transkript: Englisch(automatisch erzeugt)
Okay, I'm here to talk about floating goals and NFT-R54.
When I started this, I didn't know Go. I can't claim to know Go right now. I didn't know much about R54. Maybe I can claim to know a little bit about it now. I didn't know NFT-R54. Is that right? I'll say Go is one of the other languages to go to a new OS.
But it made a good effort. I gave the same talk at the HPMT conference in the middle of the world. I was hoping to come to this conference and be like, Hey, I did all the work right now. Unfortunately, I did 90% of the work and then I found the remaining 90% of the hard part.
I could cover the original four, but I had to learn a little bit more about how Go works for the remaining ones. So I tried to squeeze some information. It's a bit of a nothing.
Who am I? I'm a teacher. I'm a deputy developer. I'm a curator. I also have some other editor. That's me. As I qualify for this talk, I only talk about the main Go documentation.
That's the one that's GitHub. Search Go language. Search Go. There are other implementations. There's the GCC Go. There's the TinyGo, which is LVM-based. Having an introduction talk and mentioning,
Oh, and the conversation is different and will be kind of hard. Especially since the LVM talk process is what everyone needs. So Go, when you introduce a problem, you're going to have to check the space. I'll make a few things about this. Go is a compiler. This means that you have your source code.
You might want to check your source code. You can run a compiler. Then you get an executable and you run that. There are many compiler images. It's strong inside. That means that it does a lot of time checking when you compile it. Because it has all these extra compartments. So when you check the code, it makes sense.
Apparently, I just realized when I was writing the software for that time, that most of the languages that are from the site are also interested in. Because it costs time, at run time, to check the site. So they don't. We have compartments.
One of the things about Go, Go is written in Go. It's usually a bad thing, I guess. Or some people think it's a sign of maturity. You might have a compiler in that language. Usually it's a bad thing. But it's not so bad because you can build Go with Go 1.1 and 1.4.
And you don't need Go to build that particular version. Most of the issues with the self-hosted language, the language itself, are solved by the boot traffic. But if you are the new performer, if you saw the instance in Go 1.4,
you have the compiler in it. There are a lot of basic languages. If you want to do an outbound instance, it works like cross data, and you need questions. And more recent languages. It comes with its own build logic. You don't have to use it. It doesn't work. You still have to.
But it has all these classes. You don't have to reinvent off-hand and CMake and everything. You can just use what Go gives you. And it works for most people. So for most cases, you can just use the generic Go build stuff. You don't have to reinvent it all the time.
Other things about Go. The more usual. Go has a very lightweight currency. I'll talk more about the second. It has very small stacks. It has Go theme. I'll talk more about what they are. The next step is to study binaries by default,
which is not a real choice. It has some benefits. I can compile a binary. There's not anything else going around this time. You don't have to. You can make the binary better than before. Put the name for the static. And it's extremely easy to call Wingle. Before, I was a crazy person.
I wanted to build for Plan 9 now. Just do that. Just specify Go as Plan 9. Go out. And even though, I mean, I think you can do it even for Wingles, but it's crazy. You can just build a binary. If you're making a new program,
let's look at the full C, which you can see. You've got your C code. You pass it to the compiler. You can assemble it for me. By the way, human readable assembly. You give it to the assembler. It gives you in readable assembly. It's executable.
And then you give it to the breaker. It makes the read executable come out. And you can go through some new code. In this case, one time Nick had a call. And he saw the glue code. He knows how to call libc. And libc knows how to call. It has some code specific knowledge.
If you're making a new program image, most likely, you wouldn't want to reinvent the maker. And you wouldn't want to reinvent in some way. Suppose you're C++. You have all these tools that are for C. And your name, they are all verbose that you see.
You have this really big thing. And why don't you encode it in some C legible way? It's really nice. I mean, my rule, you don't want to, if you have a method of encoding, I suppose you didn't.
How do you encode this? Suppose you do it just to cut it. But you don't want the, whenever you add a new thing for your programming languages, to edit the assembler linker for every kind. So it's really nice. Just encode it in a simple, optimal way. This is very weird, encoding the C++ kingdom.
C++ fields can tell you what it is. It's not a basic thing. Something I don't want to speak of thus. So you don't need to write your assembler and maker. What is your goal?
The last thing there, I think the goal has its own implementation of it. It has its own implementation of the assembler, its own implementation of the linker, and it even has its own implementation of the legacy. So you need to know all about your OS and how to talk to the kernel.
Well, that seemed totally insane. But they had some design goals. GCC is notorious for being hard to cross-build. They had their plan 9 stuff that I guess it could do it better. And they wanted to use the plan 9 stuff.
But for now, only goal uses plan 9. So it might as well be maintained by goal. So there are my things on assembler, linker. But it comes from plan 9. And that's one of the reasons that can easily cross-build. If they're doing their own thing.
So, goal routine. Let's compare a goal routine to a normal thread. If you want to switch between threads, what switches you? If you want to switch between goal things, you can go directly. That saves you the thread through the kernel. That's the lower overhead. One of the things that goal has.
Now, if you, and this is very important information, if you have to fix your files, you have these three letters, P, M, G. Very conveniently, goal gave you one letter and eight. So you can even search for it in the goal. Good luck.
So this is how goal called link is. The G is the goal routine. The M is an OS thread. And the P, there are several goal things for OS thread. Yes. This picture, I finally found someone that explained how the goal scheduling works. And he finally explained what the M and G are.
Obviously, if you have a goal routine, it has some information, and it's stored in a struct called G. So what it means, it's the struct for the goal. Let's look at the goal calling convention.
As compared to the normal one called C or whatever. So for C, you have your register six to R54, R0 to R7, pressing parameters, then returning them, you have a step pointer, you have some registers that are generated, and you have some registers, and if you touch them,
you have to save the preview to new goal, because the previous function expected to be saved. So, call the same register. In a goal, we don't have that. Apparently, that's a limitation.
They have a proposal to change it. I guess it has to be updated to a new goal version, to obtain some cost for not having it. But in goal, all the registers are passed on the stack, and all registers are considered temporary. So if you call a function, you can't expect your registers to say where they are.
You can say something different. If you want to use the data, you better save it on the stack. One important thing that I kept thinking about, let's return to the data, R28 for ARM64, ARM Go is the struct G.
I already had this problem. When I was an agent in system, this is the first I got. I had my code failure to run. It's more complicated code. I couldn't say hello world. When I tried to be a BMP person, what I wanted to do is see what it's up to.
When it's not running, I'll try to control-T, and then it crashed. What happens when you control-T, you pass a signal, and I couldn't pass it. So it's crashing, and ultimately, I have GDB. It told me that G.m is null,
and then I'm dereferencing it. So what's G? That's the Go routine struct. So we know it's a Go routine struct. You know, Go routine,
sounds like thread loss of storage, thread loss of storage. We have this thing called, I don't know how many people think IDR is null. It's somewhere in place where you can put stuff, and for normal threaded code,
that's where it puts the thread loss of stuff. And it sounds similar. And then I have to think about it, to set it up, because obviously something is wrong. Probably it's thread loss of storage, because G is the Go routine. It has its own storage, and something is wrong with it. Who sets it up?
To write it, you have two methods. You have the architected specific way, that's the MRF, GPIDL, that's the way to call it from Go. It depends on assembler, and on assembler syntax. You can also use Cisco.
As I said, private, or get private to get it, and store location. You don't have to use, have an architected specific way. So, GPIDL is the thread pointer, you set it up, I don't know, just think about it, because it wasn't being set up,
and think about it more. If Go can call C function, who owns this stuff? I have this thread pointer, does it belong to me? How do I cooperate with the C code? Apparently, while I'm looking at this, I found out in the middle that,
if you are potentially calling C, you also need to have a C compiler, and an entirely different code path. In C Go, I was cross compiling, and I didn't have the cross compiler for C set up, so it was disabled.
That would explain why some of my code wasn't running entirely. All the code paths checking for C Go, not false. How do you interoperate? I don't know. Who owns this path? I said, when I went back,
I finally found out that path 28 is the start G, and why am I failing to deliver signals? Because let me be helpfully cross this register for me. When you deliver a signal, you say, oh, if you put in the arguments
the signal number, the step pointer, and the meaning thing, it could override alpha D8, which is the thing I need. And now it's a step pointer, which looks like a valid address, but it's not a G.
When you go, Go has its own big C for calling the column. Why is it doing that? As you see, Go has its own coding convention. It has its own parameters differently. When you call the C function, it has to translate all the registers to the C way of calling stuff.
It has to say G and things like that. Go has a lot of small stacks, so C doesn't expect to have a small stack. So if you want to run C code, you better have a big stack ready for it. And it has some accounting that you need to
it doesn't know much about the C code. It wants to do its own accounting for figuring out how to schedule its own thing. So that's what you do with a vehicle and its C function. So you probably don't want to do that very often. No.
So what do you want to do with regular stuff? I really don't want to put it in. Why does it exist? It's just doing the assembly, everything in assembly. Why not? So you have all the libc stuff re-implemented in Go assembly.
Very nice. How do you start? Do you want to do your parts? Do you accept that you need to rewrite libc for fresh? So how do you start? Well, big code, right? Why don't we just pretend it's working?
Oh, it's like the Go OS, Go OS bootstrap. This is what it does when it succeeds. But when it's early, you can figure out where the URL is coming from. Then you have some lib where to go in the code. So you don't have to read a million lines of code just to know where to start, that kind of thing.
So at this stage, you pretend you are working. You have a whole remaining OS box. Why not? So that's how you find your beginning. So this is the list of things for libc to implement. It's a very long list. How to create an OS thread that the NWP create.
How to, you have a, when you call a new thread, you have to tell it where to start. So you need to set up some things before you can run Go code. So with the trampoline, you have to make a trampoline. You have to write how to exit it.
How to look at the time. So that's why there's a function in writing Go or something. Let's look at an example of Go or something. This is the text in the text. I called all the stuff to R64. It did 90% and then I had the other 90%.
You will see we're passing a code, zero FP, the argument. We move it to R0 because the system calls the UND normal
call convention and they expect the register to be in R0, the first one, second one in R1. And R's come from the stack. So both we need to move them from the stack to the register. And then we go to the system call. And for some reason, we're like, it's exiting itself.
It's crash. I don't know why we're doing it. But it's in the system call. It's in the system call. Let's give up. That's what it's doing. The argument we're passing is the exit code anyway. So we found out that it's the exit code. I looked at the cc code header file
and it told me that it returns a void and it gets an int. So if you get an int, it's an input. It's probably now zero, the first one. That's how we figure out how to pass the argument,
in case the card is copying from exit 6.1. And if we compare to leaveC, we see that the exit function for leaveC is a lot nicer than our function just because when exit gets called,
the first parameter to exit is the exit argument. But for us, we need to translate from the row calling convention to the normal one that the syscall understands. Something that's not very obvious. I don't know how to translate it.
Eventually they figure out they want to have all the syscalls available. They don't want to work something whenever they want to use something for all the OSes and architectures and stuff like that. Very sustainable way of doing things. So they have the syscall instruction. It's a more implicit and extra argument,
which is a syscall number. To that, it's slightly easier to test parameters. So they can auto-generate it. Auto-generating is a big part, but that means for a family, you have to write multiple learning structures with four arguments.
Instead of having four arguments, they have one for three arguments, one for six arguments, one for nine. The extra arguments are taken out. So we just start from the start. The process is, I think, three arguments.
The first one is probably the syscall system call. It's more easy. You don't need to generate every system call instruction.
You don't have to generate something. You just have to generate it and write it by hand. Then you can generate the other part, which is a bit better. So that's how they have access to all the other system calls. We're asking them to implement in the system. So we may have said that the system calls use the C calling convention.
So there's actually no guarantee that, again, they don't have to. You're not calling C code. You're calling comma. You can define whatever you want. So you're trying to run your code.
It doesn't work. So you're trying to catch it. That's a really nice thing for when you're doing something like the goal is 60. So it will tell you what you're passing in the argument. So you can figure out what you want. Apparently, the system call, it doesn't pass the syscall number in the first argument.
Even though it's the first argument to the function, it passes it on some other register. So let me show you a demo. Now, I did all this work. I was hoping that I'll finish things.
But conveniently, I have upstreamed my walk. Because I have upstreamed, someone else will walk. So I have a slightly outdated version. Show the emulator. I did the before, just because it takes a while.
Go OS, let me see, go architecture on 64, bootstrap batch. Because it's using batch scripts for the reference of the logic.
And it does, I passed it to the emulator, so it would have it internally. Just so we could skip doing that right now. Very important to have that finished.
That's how we know it should be on the computer, right? Right. Okay, yeah.
Bootstrap resolves, I infected the root directory, which we have. And go binary, see? If you look closely, you can tell it's a go binary. Oh, that's really complex.
Because it says it's $5.99. Because go doesn't use any external chain, it never learned that we've gone beyond $5.99. It just followed this version and everything. Other application for doing that.
That's how you know it's a go binary. Also, it tells you go busy. So I had, and this is an out-of-date statement. I could run some basic stuff for the debug code that I had left. It could tell you that I have the go version, some in code that might need it.
I have a lot of local changes, and that's how it was. I could run this. I couldn't run more complicated code. It's a shame I don't have a code to build right now. I can't make it crash.
Oh, I did. So now it's not printing the go version. Because if I control T instead of it used to crash, now it just exits. That took too much to do.
I finally extremely. I had to do some ninter for fixing stuff. I don't know what it is, but I fixed it.
So they accepted it upstream. Because it's upstream for a month. Other people contributed to it, which is great. This is a really good advice because I heard that some people are working on a previous version. I know that one guy started working, and another guy worked on his version.
The third guy started contacting me and telling me that my version had bugs. So I think he's not using the version that the same guy did before. So having the other three is a problem. It's really hard to cooperate. People don't know about each other. So having it upstream is a big help.
Thanks to Thomas Klauser, which isn't Thomas Klauser. That's the extra n. That's another guy, and he works on a goal. He did some stuff, and I think it was yesterday or two days ago, John Singh got fixed about the bugs, including the one that we're trying to fix. Yay! So now it should work better than what I've shown.
I didn't update my own version, which has a lot of local changes. I've never seen how far away it's going. I've had a slow version before. I could bring home versions. Maybe it's better. I haven't tried it. I've had too much fun painting it.
Any questions? What was the motivation behind this work? Did you have any co-programs that you wanted to run? No, I just stopped working in programming languages. Or anything. Okay, yeah. No question.
What does it take? Well, if you know what you're doing... I'm sure it's very easy for the people that won't go to another OS. Yes, but I guess I did maybe two months of work in Go,
and it's not... I wish I could say right now that it's been all the time, and they're asking me to go to another OS. But people that understand Go and maybe know how to read information about Go and not just read the code might have a better time.
Maybe they know R64 ahead of time. That would help too. Yeah. Yeah, just a lot of failed attempts. R64 question, but more or less a generic Go libc question.
If, say for example, NetDSD or whatever project has updated a libc call or a syscall, in the case of the previous update of i.32 to i.64,
which has caused some other programming languages such as DMD's D language, a lot of GAS. How would you handle that? Yeah, it's a problem. You're implementing those syscalls in the Go libc, okay?
And in the case of the D language, they implemented the syscall to hold in their libc and that caused... Yeah. It still causes more and more problems. Yeah, for open basic.
I know that the open basic is changing Go 1.4 because they stopped and they don't edit in a backwards compatible way. So Go is the ultimate backwards compatible checker. We found out the hardware in NetDSD. Okay. So it's the same problem? Yeah.
We have an action key request to go with the syscall file. Okay. Because it's stuck in unconventional ways. It found out that way. And it found out that we're more competitive in CPA. In theory, we're supposed to be syscall random compatible.
We make a new number for a new syscall. Try to... What's syscall versioning? Right. You can always version the calls in libc, right? Yeah. So it's going to be the same. It's a convenient thing for everything.
Whenever we change the syscall parameters, we make a new syscall. So if you gave up on the old ones, then it will be immediately obvious. In this case, we didn't change the... We didn't change the syscall for i.64.
We didn't change the version selection. The syscall was still the same. But libc would detect whether an old version of the program or a new version of the application like this called the API. Yeah. I heard that song. We changed for that. That's why everyone likes to bootstrap.
Because if you have just a binary bootstrap, then now you're screwed. Because you need to... You know, in Rust, you have to use an old binary. And you have the binary now.
Fundly Go allows you to bootstrap non-form Go. So you can change the Go 1.4. And then change the normal Go. Hopefully it works. And I did see someone having to change for i.64. For previously. Yes. What is special about Go 1.4 that makes it work
as a bootstrap or anything? Is it written in C? Yeah. So we can see. And now keeping it alive. You can bootstrap directly from 1.4 to the latest version. Making sure it's possible. So you keep it alive in the bootstrap like you do essentially.
Yes. There's a sort of tiny co-applementation that you can see. And that's still being maintained actively. And you just kept the version number as the name. Like this is called Go 1.4 forever. Or the way I put it was I have Go 1.4.1.2.3. I don't know how to version it.
I think I actually accept this question. But I haven't tried. To the old branch. Any more questions? Did Go already have an erm64 code generator? Yes. Fortunately. I'm really glad. Look at this. If you had to write it yourself, would you have given up at that point?
Not only that, the assembler has a custom syntax. They don't use the un64 known stuff. They want to pass the parameters in a particular way. I mentioned for TPI,
either they actually didn't write an instruction for this. They just put the text output. They forgot about that one. So now an LRS instruction? They don't. Let me show you what they have instead.
That seems crappy. Oh, what's that? Okay, yeah. That's not a very good idea. If you let me see, we shall go. I made a funny joke. Next,
ARM can be big-end to BSC whether you want to care about it. So that's more for big-end. I think it can run in big-end. Yeah. On some IOT channel, like I see some guy once a year say, hey, I have an edge to boot in big-end,
but it breaks here. So yeah, it works. It's hard to boot. Yeah, I think it's amazing. I haven't tried ARM6 before big-end, but I think they're friendly enough to try. They really like their big-end. There's someone we tried with some of the, one of the big-end developers.
Yeah, there's this one guy. He loves having hard life. He loves having the work platform. But we have lots of other big-end platforms, so the rest of the code base should be good. More questions.
Thank you.