1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package arch defines architecture-specific information and support functions.
6package arch
7
8import (
9	"cmd/internal/obj"
10	"cmd/internal/obj/arm"
11	"cmd/internal/obj/arm64"
12	"cmd/internal/obj/loong64"
13	"cmd/internal/obj/mips"
14	"cmd/internal/obj/ppc64"
15	"cmd/internal/obj/riscv"
16	"cmd/internal/obj/s390x"
17	"cmd/internal/obj/wasm"
18	"cmd/internal/obj/x86"
19	"fmt"
20	"strings"
21)
22
23// Pseudo-registers whose names are the constant name without the leading R.
24const (
25	RFP = -(iota + 1)
26	RSB
27	RSP
28	RPC
29)
30
31// Arch wraps the link architecture object with more architecture-specific information.
32type Arch struct {
33	*obj.LinkArch
34	// Map of instruction names to enumeration.
35	Instructions map[string]obj.As
36	// Map of register names to enumeration.
37	Register map[string]int16
38	// Table of register prefix names. These are things like R for R(0) and SPR for SPR(268).
39	RegisterPrefix map[string]bool
40	// RegisterNumber converts R(10) into arm.REG_R10.
41	RegisterNumber func(string, int16) (int16, bool)
42	// Instruction is a jump.
43	IsJump func(word string) bool
44}
45
46// nilRegisterNumber is the register number function for architectures
47// that do not accept the R(N) notation. It always returns failure.
48func nilRegisterNumber(name string, n int16) (int16, bool) {
49	return 0, false
50}
51
52// Set configures the architecture specified by GOARCH and returns its representation.
53// It returns nil if GOARCH is not recognized.
54func Set(GOARCH string, shared bool) *Arch {
55	switch GOARCH {
56	case "386":
57		return archX86(&x86.Link386)
58	case "amd64":
59		return archX86(&x86.Linkamd64)
60	case "arm":
61		return archArm()
62	case "arm64":
63		return archArm64()
64	case "loong64":
65		return archLoong64(&loong64.Linkloong64)
66	case "mips":
67		return archMips(&mips.Linkmips)
68	case "mipsle":
69		return archMips(&mips.Linkmipsle)
70	case "mips64":
71		return archMips64(&mips.Linkmips64)
72	case "mips64le":
73		return archMips64(&mips.Linkmips64le)
74	case "ppc64":
75		return archPPC64(&ppc64.Linkppc64)
76	case "ppc64le":
77		return archPPC64(&ppc64.Linkppc64le)
78	case "riscv64":
79		return archRISCV64(shared)
80	case "s390x":
81		return archS390x()
82	case "wasm":
83		return archWasm()
84	}
85	return nil
86}
87
88func jumpX86(word string) bool {
89	return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
90}
91
92func jumpRISCV(word string) bool {
93	switch word {
94	case "BEQ", "BEQZ", "BGE", "BGEU", "BGEZ", "BGT", "BGTU", "BGTZ", "BLE", "BLEU", "BLEZ",
95		"BLT", "BLTU", "BLTZ", "BNE", "BNEZ", "CALL", "JAL", "JALR", "JMP":
96		return true
97	}
98	return false
99}
100
101func jumpWasm(word string) bool {
102	return word == "JMP" || word == "CALL" || word == "Call" || word == "Br" || word == "BrIf"
103}
104
105func archX86(linkArch *obj.LinkArch) *Arch {
106	register := make(map[string]int16)
107	// Create maps for easy lookup of instruction names etc.
108	for i, s := range x86.Register {
109		register[s] = int16(i + x86.REG_AL)
110	}
111	// Pseudo-registers.
112	register["SB"] = RSB
113	register["FP"] = RFP
114	register["PC"] = RPC
115	if linkArch == &x86.Linkamd64 {
116		// Alias g to R14
117		register["g"] = x86.REGG
118	}
119	// Register prefix not used on this architecture.
120
121	instructions := make(map[string]obj.As)
122	for i, s := range obj.Anames {
123		instructions[s] = obj.As(i)
124	}
125	for i, s := range x86.Anames {
126		if obj.As(i) >= obj.A_ARCHSPECIFIC {
127			instructions[s] = obj.As(i) + obj.ABaseAMD64
128		}
129	}
130	// Annoying aliases.
131	instructions["JA"] = x86.AJHI   /* alternate */
132	instructions["JAE"] = x86.AJCC  /* alternate */
133	instructions["JB"] = x86.AJCS   /* alternate */
134	instructions["JBE"] = x86.AJLS  /* alternate */
135	instructions["JC"] = x86.AJCS   /* alternate */
136	instructions["JCC"] = x86.AJCC  /* carry clear (CF = 0) */
137	instructions["JCS"] = x86.AJCS  /* carry set (CF = 1) */
138	instructions["JE"] = x86.AJEQ   /* alternate */
139	instructions["JEQ"] = x86.AJEQ  /* equal (ZF = 1) */
140	instructions["JG"] = x86.AJGT   /* alternate */
141	instructions["JGE"] = x86.AJGE  /* greater than or equal (signed) (SF = OF) */
142	instructions["JGT"] = x86.AJGT  /* greater than (signed) (ZF = 0 && SF = OF) */
143	instructions["JHI"] = x86.AJHI  /* higher (unsigned) (CF = 0 && ZF = 0) */
144	instructions["JHS"] = x86.AJCC  /* alternate */
145	instructions["JL"] = x86.AJLT   /* alternate */
146	instructions["JLE"] = x86.AJLE  /* less than or equal (signed) (ZF = 1 || SF != OF) */
147	instructions["JLO"] = x86.AJCS  /* alternate */
148	instructions["JLS"] = x86.AJLS  /* lower or same (unsigned) (CF = 1 || ZF = 1) */
149	instructions["JLT"] = x86.AJLT  /* less than (signed) (SF != OF) */
150	instructions["JMI"] = x86.AJMI  /* negative (minus) (SF = 1) */
151	instructions["JNA"] = x86.AJLS  /* alternate */
152	instructions["JNAE"] = x86.AJCS /* alternate */
153	instructions["JNB"] = x86.AJCC  /* alternate */
154	instructions["JNBE"] = x86.AJHI /* alternate */
155	instructions["JNC"] = x86.AJCC  /* alternate */
156	instructions["JNE"] = x86.AJNE  /* not equal (ZF = 0) */
157	instructions["JNG"] = x86.AJLE  /* alternate */
158	instructions["JNGE"] = x86.AJLT /* alternate */
159	instructions["JNL"] = x86.AJGE  /* alternate */
160	instructions["JNLE"] = x86.AJGT /* alternate */
161	instructions["JNO"] = x86.AJOC  /* alternate */
162	instructions["JNP"] = x86.AJPC  /* alternate */
163	instructions["JNS"] = x86.AJPL  /* alternate */
164	instructions["JNZ"] = x86.AJNE  /* alternate */
165	instructions["JO"] = x86.AJOS   /* alternate */
166	instructions["JOC"] = x86.AJOC  /* overflow clear (OF = 0) */
167	instructions["JOS"] = x86.AJOS  /* overflow set (OF = 1) */
168	instructions["JP"] = x86.AJPS   /* alternate */
169	instructions["JPC"] = x86.AJPC  /* parity clear (PF = 0) */
170	instructions["JPE"] = x86.AJPS  /* alternate */
171	instructions["JPL"] = x86.AJPL  /* non-negative (plus) (SF = 0) */
172	instructions["JPO"] = x86.AJPC  /* alternate */
173	instructions["JPS"] = x86.AJPS  /* parity set (PF = 1) */
174	instructions["JS"] = x86.AJMI   /* alternate */
175	instructions["JZ"] = x86.AJEQ   /* alternate */
176	instructions["MASKMOVDQU"] = x86.AMASKMOVOU
177	instructions["MOVD"] = x86.AMOVQ
178	instructions["MOVDQ2Q"] = x86.AMOVQ
179	instructions["MOVNTDQ"] = x86.AMOVNTO
180	instructions["MOVOA"] = x86.AMOVO
181	instructions["PSLLDQ"] = x86.APSLLO
182	instructions["PSRLDQ"] = x86.APSRLO
183	instructions["PADDD"] = x86.APADDL
184	// Spellings originally used in CL 97235.
185	instructions["MOVBELL"] = x86.AMOVBEL
186	instructions["MOVBEQQ"] = x86.AMOVBEQ
187	instructions["MOVBEWW"] = x86.AMOVBEW
188
189	return &Arch{
190		LinkArch:       linkArch,
191		Instructions:   instructions,
192		Register:       register,
193		RegisterPrefix: nil,
194		RegisterNumber: nilRegisterNumber,
195		IsJump:         jumpX86,
196	}
197}
198
199func archArm() *Arch {
200	register := make(map[string]int16)
201	// Create maps for easy lookup of instruction names etc.
202	// Note that there is no list of names as there is for x86.
203	for i := arm.REG_R0; i < arm.REG_SPSR; i++ {
204		register[obj.Rconv(i)] = int16(i)
205	}
206	// Avoid unintentionally clobbering g using R10.
207	delete(register, "R10")
208	register["g"] = arm.REG_R10
209	for i := 0; i < 16; i++ {
210		register[fmt.Sprintf("C%d", i)] = int16(i)
211	}
212
213	// Pseudo-registers.
214	register["SB"] = RSB
215	register["FP"] = RFP
216	register["PC"] = RPC
217	register["SP"] = RSP
218	registerPrefix := map[string]bool{
219		"F": true,
220		"R": true,
221	}
222
223	// special operands for DMB/DSB instructions
224	register["MB_SY"] = arm.REG_MB_SY
225	register["MB_ST"] = arm.REG_MB_ST
226	register["MB_ISH"] = arm.REG_MB_ISH
227	register["MB_ISHST"] = arm.REG_MB_ISHST
228	register["MB_NSH"] = arm.REG_MB_NSH
229	register["MB_NSHST"] = arm.REG_MB_NSHST
230	register["MB_OSH"] = arm.REG_MB_OSH
231	register["MB_OSHST"] = arm.REG_MB_OSHST
232
233	instructions := make(map[string]obj.As)
234	for i, s := range obj.Anames {
235		instructions[s] = obj.As(i)
236	}
237	for i, s := range arm.Anames {
238		if obj.As(i) >= obj.A_ARCHSPECIFIC {
239			instructions[s] = obj.As(i) + obj.ABaseARM
240		}
241	}
242	// Annoying aliases.
243	instructions["B"] = obj.AJMP
244	instructions["BL"] = obj.ACALL
245	// MCR differs from MRC by the way fields of the word are encoded.
246	// (Details in arm.go). Here we add the instruction so parse will find
247	// it, but give it an opcode number known only to us.
248	instructions["MCR"] = aMCR
249
250	return &Arch{
251		LinkArch:       &arm.Linkarm,
252		Instructions:   instructions,
253		Register:       register,
254		RegisterPrefix: registerPrefix,
255		RegisterNumber: armRegisterNumber,
256		IsJump:         jumpArm,
257	}
258}
259
260func archArm64() *Arch {
261	register := make(map[string]int16)
262	// Create maps for easy lookup of instruction names etc.
263	// Note that there is no list of names as there is for 386 and amd64.
264	register[obj.Rconv(arm64.REGSP)] = int16(arm64.REGSP)
265	for i := arm64.REG_R0; i <= arm64.REG_R31; i++ {
266		register[obj.Rconv(i)] = int16(i)
267	}
268	// Rename R18 to R18_PLATFORM to avoid accidental use.
269	register["R18_PLATFORM"] = register["R18"]
270	delete(register, "R18")
271	for i := arm64.REG_F0; i <= arm64.REG_F31; i++ {
272		register[obj.Rconv(i)] = int16(i)
273	}
274	for i := arm64.REG_V0; i <= arm64.REG_V31; i++ {
275		register[obj.Rconv(i)] = int16(i)
276	}
277
278	// System registers.
279	for i := 0; i < len(arm64.SystemReg); i++ {
280		register[arm64.SystemReg[i].Name] = arm64.SystemReg[i].Reg
281	}
282
283	register["LR"] = arm64.REGLINK
284
285	// Pseudo-registers.
286	register["SB"] = RSB
287	register["FP"] = RFP
288	register["PC"] = RPC
289	register["SP"] = RSP
290	// Avoid unintentionally clobbering g using R28.
291	delete(register, "R28")
292	register["g"] = arm64.REG_R28
293	registerPrefix := map[string]bool{
294		"F": true,
295		"R": true,
296		"V": true,
297	}
298
299	instructions := make(map[string]obj.As)
300	for i, s := range obj.Anames {
301		instructions[s] = obj.As(i)
302	}
303	for i, s := range arm64.Anames {
304		if obj.As(i) >= obj.A_ARCHSPECIFIC {
305			instructions[s] = obj.As(i) + obj.ABaseARM64
306		}
307	}
308	// Annoying aliases.
309	instructions["B"] = arm64.AB
310	instructions["BL"] = arm64.ABL
311
312	return &Arch{
313		LinkArch:       &arm64.Linkarm64,
314		Instructions:   instructions,
315		Register:       register,
316		RegisterPrefix: registerPrefix,
317		RegisterNumber: arm64RegisterNumber,
318		IsJump:         jumpArm64,
319	}
320
321}
322
323func archPPC64(linkArch *obj.LinkArch) *Arch {
324	register := make(map[string]int16)
325	// Create maps for easy lookup of instruction names etc.
326	// Note that there is no list of names as there is for x86.
327	for i := ppc64.REG_R0; i <= ppc64.REG_R31; i++ {
328		register[obj.Rconv(i)] = int16(i)
329	}
330	for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
331		register[obj.Rconv(i)] = int16(i)
332	}
333	for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ {
334		register[obj.Rconv(i)] = int16(i)
335	}
336	for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ {
337		register[obj.Rconv(i)] = int16(i)
338	}
339	for i := ppc64.REG_A0; i <= ppc64.REG_A7; i++ {
340		register[obj.Rconv(i)] = int16(i)
341	}
342	for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
343		register[obj.Rconv(i)] = int16(i)
344	}
345	for i := ppc64.REG_MSR; i <= ppc64.REG_CR; i++ {
346		register[obj.Rconv(i)] = int16(i)
347	}
348	for i := ppc64.REG_CR0LT; i <= ppc64.REG_CR7SO; i++ {
349		register[obj.Rconv(i)] = int16(i)
350	}
351	register["CR"] = ppc64.REG_CR
352	register["XER"] = ppc64.REG_XER
353	register["LR"] = ppc64.REG_LR
354	register["CTR"] = ppc64.REG_CTR
355	register["FPSCR"] = ppc64.REG_FPSCR
356	register["MSR"] = ppc64.REG_MSR
357	// Pseudo-registers.
358	register["SB"] = RSB
359	register["FP"] = RFP
360	register["PC"] = RPC
361	// Avoid unintentionally clobbering g using R30.
362	delete(register, "R30")
363	register["g"] = ppc64.REG_R30
364	registerPrefix := map[string]bool{
365		"CR":  true,
366		"F":   true,
367		"R":   true,
368		"SPR": true,
369	}
370
371	instructions := make(map[string]obj.As)
372	for i, s := range obj.Anames {
373		instructions[s] = obj.As(i)
374	}
375	for i, s := range ppc64.Anames {
376		if obj.As(i) >= obj.A_ARCHSPECIFIC {
377			instructions[s] = obj.As(i) + obj.ABasePPC64
378		}
379	}
380	// The opcodes generated by x/arch's ppc64map are listed in
381	// a separate slice, add them too.
382	for i, s := range ppc64.GenAnames {
383		instructions[s] = obj.As(i) + ppc64.AFIRSTGEN
384	}
385	// Annoying aliases.
386	instructions["BR"] = ppc64.ABR
387	instructions["BL"] = ppc64.ABL
388
389	return &Arch{
390		LinkArch:       linkArch,
391		Instructions:   instructions,
392		Register:       register,
393		RegisterPrefix: registerPrefix,
394		RegisterNumber: ppc64RegisterNumber,
395		IsJump:         jumpPPC64,
396	}
397}
398
399func archMips(linkArch *obj.LinkArch) *Arch {
400	register := make(map[string]int16)
401	// Create maps for easy lookup of instruction names etc.
402	// Note that there is no list of names as there is for x86.
403	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
404		register[obj.Rconv(i)] = int16(i)
405	}
406
407	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
408		register[obj.Rconv(i)] = int16(i)
409	}
410	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
411		register[obj.Rconv(i)] = int16(i)
412	}
413	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
414		register[obj.Rconv(i)] = int16(i)
415	}
416	register["HI"] = mips.REG_HI
417	register["LO"] = mips.REG_LO
418	// Pseudo-registers.
419	register["SB"] = RSB
420	register["FP"] = RFP
421	register["PC"] = RPC
422	// Avoid unintentionally clobbering g using R30.
423	delete(register, "R30")
424	register["g"] = mips.REG_R30
425
426	registerPrefix := map[string]bool{
427		"F":   true,
428		"FCR": true,
429		"M":   true,
430		"R":   true,
431	}
432
433	instructions := make(map[string]obj.As)
434	for i, s := range obj.Anames {
435		instructions[s] = obj.As(i)
436	}
437	for i, s := range mips.Anames {
438		if obj.As(i) >= obj.A_ARCHSPECIFIC {
439			instructions[s] = obj.As(i) + obj.ABaseMIPS
440		}
441	}
442	// Annoying alias.
443	instructions["JAL"] = mips.AJAL
444
445	return &Arch{
446		LinkArch:       linkArch,
447		Instructions:   instructions,
448		Register:       register,
449		RegisterPrefix: registerPrefix,
450		RegisterNumber: mipsRegisterNumber,
451		IsJump:         jumpMIPS,
452	}
453}
454
455func archMips64(linkArch *obj.LinkArch) *Arch {
456	register := make(map[string]int16)
457	// Create maps for easy lookup of instruction names etc.
458	// Note that there is no list of names as there is for x86.
459	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
460		register[obj.Rconv(i)] = int16(i)
461	}
462	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
463		register[obj.Rconv(i)] = int16(i)
464	}
465	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
466		register[obj.Rconv(i)] = int16(i)
467	}
468	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
469		register[obj.Rconv(i)] = int16(i)
470	}
471	for i := mips.REG_W0; i <= mips.REG_W31; i++ {
472		register[obj.Rconv(i)] = int16(i)
473	}
474	register["HI"] = mips.REG_HI
475	register["LO"] = mips.REG_LO
476	// Pseudo-registers.
477	register["SB"] = RSB
478	register["FP"] = RFP
479	register["PC"] = RPC
480	// Avoid unintentionally clobbering g using R30.
481	delete(register, "R30")
482	register["g"] = mips.REG_R30
483	// Avoid unintentionally clobbering RSB using R28.
484	delete(register, "R28")
485	register["RSB"] = mips.REG_R28
486	registerPrefix := map[string]bool{
487		"F":   true,
488		"FCR": true,
489		"M":   true,
490		"R":   true,
491		"W":   true,
492	}
493
494	instructions := make(map[string]obj.As)
495	for i, s := range obj.Anames {
496		instructions[s] = obj.As(i)
497	}
498	for i, s := range mips.Anames {
499		if obj.As(i) >= obj.A_ARCHSPECIFIC {
500			instructions[s] = obj.As(i) + obj.ABaseMIPS
501		}
502	}
503	// Annoying alias.
504	instructions["JAL"] = mips.AJAL
505
506	return &Arch{
507		LinkArch:       linkArch,
508		Instructions:   instructions,
509		Register:       register,
510		RegisterPrefix: registerPrefix,
511		RegisterNumber: mipsRegisterNumber,
512		IsJump:         jumpMIPS,
513	}
514}
515
516func archLoong64(linkArch *obj.LinkArch) *Arch {
517	register := make(map[string]int16)
518	// Create maps for easy lookup of instruction names etc.
519	// Note that there is no list of names as there is for x86.
520	for i := loong64.REG_R0; i <= loong64.REG_R31; i++ {
521		register[obj.Rconv(i)] = int16(i)
522	}
523	for i := loong64.REG_F0; i <= loong64.REG_F31; i++ {
524		register[obj.Rconv(i)] = int16(i)
525	}
526	for i := loong64.REG_FCSR0; i <= loong64.REG_FCSR31; i++ {
527		register[obj.Rconv(i)] = int16(i)
528	}
529	for i := loong64.REG_FCC0; i <= loong64.REG_FCC31; i++ {
530		register[obj.Rconv(i)] = int16(i)
531	}
532	// Pseudo-registers.
533	register["SB"] = RSB
534	register["FP"] = RFP
535	register["PC"] = RPC
536	// Avoid unintentionally clobbering g using R22.
537	delete(register, "R22")
538	register["g"] = loong64.REG_R22
539	registerPrefix := map[string]bool{
540		"F":    true,
541		"FCSR": true,
542		"FCC":  true,
543		"R":    true,
544	}
545
546	instructions := make(map[string]obj.As)
547	for i, s := range obj.Anames {
548		instructions[s] = obj.As(i)
549	}
550	for i, s := range loong64.Anames {
551		if obj.As(i) >= obj.A_ARCHSPECIFIC {
552			instructions[s] = obj.As(i) + obj.ABaseLoong64
553		}
554	}
555	// Annoying alias.
556	instructions["JAL"] = loong64.AJAL
557
558	return &Arch{
559		LinkArch:       linkArch,
560		Instructions:   instructions,
561		Register:       register,
562		RegisterPrefix: registerPrefix,
563		RegisterNumber: loong64RegisterNumber,
564		IsJump:         jumpLoong64,
565	}
566}
567
568func archRISCV64(shared bool) *Arch {
569	register := make(map[string]int16)
570
571	// Standard register names.
572	for i := riscv.REG_X0; i <= riscv.REG_X31; i++ {
573		// Disallow X3 in shared mode, as this will likely be used as the
574		// GP register, which could result in problems in non-Go code,
575		// including signal handlers.
576		if shared && i == riscv.REG_GP {
577			continue
578		}
579		if i == riscv.REG_TP || i == riscv.REG_G {
580			continue
581		}
582		name := fmt.Sprintf("X%d", i-riscv.REG_X0)
583		register[name] = int16(i)
584	}
585	for i := riscv.REG_F0; i <= riscv.REG_F31; i++ {
586		name := fmt.Sprintf("F%d", i-riscv.REG_F0)
587		register[name] = int16(i)
588	}
589
590	// General registers with ABI names.
591	register["ZERO"] = riscv.REG_ZERO
592	register["RA"] = riscv.REG_RA
593	register["SP"] = riscv.REG_SP
594	register["GP"] = riscv.REG_GP
595	register["TP"] = riscv.REG_TP
596	register["T0"] = riscv.REG_T0
597	register["T1"] = riscv.REG_T1
598	register["T2"] = riscv.REG_T2
599	register["S0"] = riscv.REG_S0
600	register["S1"] = riscv.REG_S1
601	register["A0"] = riscv.REG_A0
602	register["A1"] = riscv.REG_A1
603	register["A2"] = riscv.REG_A2
604	register["A3"] = riscv.REG_A3
605	register["A4"] = riscv.REG_A4
606	register["A5"] = riscv.REG_A5
607	register["A6"] = riscv.REG_A6
608	register["A7"] = riscv.REG_A7
609	register["S2"] = riscv.REG_S2
610	register["S3"] = riscv.REG_S3
611	register["S4"] = riscv.REG_S4
612	register["S5"] = riscv.REG_S5
613	register["S6"] = riscv.REG_S6
614	register["S7"] = riscv.REG_S7
615	register["S8"] = riscv.REG_S8
616	register["S9"] = riscv.REG_S9
617	register["S10"] = riscv.REG_S10
618	// Skip S11 as it is the g register.
619	register["T3"] = riscv.REG_T3
620	register["T4"] = riscv.REG_T4
621	register["T5"] = riscv.REG_T5
622	register["T6"] = riscv.REG_T6
623
624	// Go runtime register names.
625	register["g"] = riscv.REG_G
626	register["CTXT"] = riscv.REG_CTXT
627	register["TMP"] = riscv.REG_TMP
628
629	// ABI names for floating point register.
630	register["FT0"] = riscv.REG_FT0
631	register["FT1"] = riscv.REG_FT1
632	register["FT2"] = riscv.REG_FT2
633	register["FT3"] = riscv.REG_FT3
634	register["FT4"] = riscv.REG_FT4
635	register["FT5"] = riscv.REG_FT5
636	register["FT6"] = riscv.REG_FT6
637	register["FT7"] = riscv.REG_FT7
638	register["FS0"] = riscv.REG_FS0
639	register["FS1"] = riscv.REG_FS1
640	register["FA0"] = riscv.REG_FA0
641	register["FA1"] = riscv.REG_FA1
642	register["FA2"] = riscv.REG_FA2
643	register["FA3"] = riscv.REG_FA3
644	register["FA4"] = riscv.REG_FA4
645	register["FA5"] = riscv.REG_FA5
646	register["FA6"] = riscv.REG_FA6
647	register["FA7"] = riscv.REG_FA7
648	register["FS2"] = riscv.REG_FS2
649	register["FS3"] = riscv.REG_FS3
650	register["FS4"] = riscv.REG_FS4
651	register["FS5"] = riscv.REG_FS5
652	register["FS6"] = riscv.REG_FS6
653	register["FS7"] = riscv.REG_FS7
654	register["FS8"] = riscv.REG_FS8
655	register["FS9"] = riscv.REG_FS9
656	register["FS10"] = riscv.REG_FS10
657	register["FS11"] = riscv.REG_FS11
658	register["FT8"] = riscv.REG_FT8
659	register["FT9"] = riscv.REG_FT9
660	register["FT10"] = riscv.REG_FT10
661	register["FT11"] = riscv.REG_FT11
662
663	// Pseudo-registers.
664	register["SB"] = RSB
665	register["FP"] = RFP
666	register["PC"] = RPC
667
668	instructions := make(map[string]obj.As)
669	for i, s := range obj.Anames {
670		instructions[s] = obj.As(i)
671	}
672	for i, s := range riscv.Anames {
673		if obj.As(i) >= obj.A_ARCHSPECIFIC {
674			instructions[s] = obj.As(i) + obj.ABaseRISCV
675		}
676	}
677
678	return &Arch{
679		LinkArch:       &riscv.LinkRISCV64,
680		Instructions:   instructions,
681		Register:       register,
682		RegisterPrefix: nil,
683		RegisterNumber: nilRegisterNumber,
684		IsJump:         jumpRISCV,
685	}
686}
687
688func archS390x() *Arch {
689	register := make(map[string]int16)
690	// Create maps for easy lookup of instruction names etc.
691	// Note that there is no list of names as there is for x86.
692	for i := s390x.REG_R0; i <= s390x.REG_R15; i++ {
693		register[obj.Rconv(i)] = int16(i)
694	}
695	for i := s390x.REG_F0; i <= s390x.REG_F15; i++ {
696		register[obj.Rconv(i)] = int16(i)
697	}
698	for i := s390x.REG_V0; i <= s390x.REG_V31; i++ {
699		register[obj.Rconv(i)] = int16(i)
700	}
701	for i := s390x.REG_AR0; i <= s390x.REG_AR15; i++ {
702		register[obj.Rconv(i)] = int16(i)
703	}
704	register["LR"] = s390x.REG_LR
705	// Pseudo-registers.
706	register["SB"] = RSB
707	register["FP"] = RFP
708	register["PC"] = RPC
709	// Avoid unintentionally clobbering g using R13.
710	delete(register, "R13")
711	register["g"] = s390x.REG_R13
712	registerPrefix := map[string]bool{
713		"AR": true,
714		"F":  true,
715		"R":  true,
716	}
717
718	instructions := make(map[string]obj.As)
719	for i, s := range obj.Anames {
720		instructions[s] = obj.As(i)
721	}
722	for i, s := range s390x.Anames {
723		if obj.As(i) >= obj.A_ARCHSPECIFIC {
724			instructions[s] = obj.As(i) + obj.ABaseS390X
725		}
726	}
727	// Annoying aliases.
728	instructions["BR"] = s390x.ABR
729	instructions["BL"] = s390x.ABL
730
731	return &Arch{
732		LinkArch:       &s390x.Links390x,
733		Instructions:   instructions,
734		Register:       register,
735		RegisterPrefix: registerPrefix,
736		RegisterNumber: s390xRegisterNumber,
737		IsJump:         jumpS390x,
738	}
739}
740
741func archWasm() *Arch {
742	instructions := make(map[string]obj.As)
743	for i, s := range obj.Anames {
744		instructions[s] = obj.As(i)
745	}
746	for i, s := range wasm.Anames {
747		if obj.As(i) >= obj.A_ARCHSPECIFIC {
748			instructions[s] = obj.As(i) + obj.ABaseWasm
749		}
750	}
751
752	return &Arch{
753		LinkArch:       &wasm.Linkwasm,
754		Instructions:   instructions,
755		Register:       wasm.Register,
756		RegisterPrefix: nil,
757		RegisterNumber: nilRegisterNumber,
758		IsJump:         jumpWasm,
759	}
760}
761