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