1
2
3
4
5 package asmgen
6
7 var ArchAMD64 = &Arch{
8 Name: "amd64",
9 WordBits: 64,
10 WordBytes: 8,
11
12 regs: []string{
13 "BX", "SI", "DI",
14 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
15 "AX", "DX", "CX",
16 },
17 op3: x86Op3,
18 hint: x86Hint,
19 memOK: true,
20 subCarryIsBorrow: true,
21
22
23
24
25
26 options: map[Option]func(*Asm, string){
27 OptionAltCarry: amd64JmpADX,
28 },
29
30 mov: "MOVQ",
31 adds: "ADDQ",
32 adcs: "ADCQ",
33 subs: "SUBQ",
34 sbcs: "SBBQ",
35 lsh: "SHLQ",
36 lshd: "SHLQ",
37 rsh: "SHRQ",
38 rshd: "SHRQ",
39 and: "ANDQ",
40 or: "ORQ",
41 xor: "XORQ",
42 neg: "NEGQ",
43 lea: "LEAQ",
44 addF: amd64Add,
45 mulWideF: x86MulWide,
46
47 addWords: "LEAQ (%[2]s)(%[1]s*8), %[3]s",
48
49 jmpZero: "TESTQ %[1]s, %[1]s; JZ %[2]s",
50 jmpNonZero: "TESTQ %[1]s, %[1]s; JNZ %[2]s",
51 loopBottom: "SUBQ $1, %[1]s; JNZ %[2]s",
52 loopBottomNeg: "ADDQ $1, %[1]s; JNZ %[2]s",
53 }
54
55 func amd64JmpADX(a *Asm, label string) {
56 a.Printf("\tCMPB ·hasADX(SB), $0; JNZ %s\n", label)
57 }
58
59 func amd64Add(a *Asm, src1, src2 Reg, dst Reg, carry Carry) bool {
60 if a.Enabled(OptionAltCarry) {
61
62
63
64
65
66 if carry&UseCarry != 0 && carry&(SetCarry|SmashCarry) != 0 {
67 if carry&AltCarry != 0 {
68 a.op3("ADOXQ", src1, src2, dst)
69 } else {
70 a.op3("ADCXQ", src1, src2, dst)
71 }
72 return true
73 }
74 if carry&(SetCarry|UseCarry) == SetCarry && a.IsZero(src1) && src2 == dst {
75
76 a.Printf("\tTESTQ AX, AX\n")
77 return true
78 }
79 if carry != KeepCarry {
80 a.Fatalf("unsupported carry")
81 }
82 }
83 return false
84 }
85
86
87
88 func x86Op3(name string) bool {
89
90
91 return false
92 }
93
94 func x86Hint(a *Asm, h Hint) string {
95 switch h {
96 case HintShiftCount:
97 return "CX"
98 case HintMulSrc:
99 if a.Enabled(OptionAltCarry) {
100 return "DX"
101 }
102 return "AX"
103 case HintMulHi:
104 if a.Enabled(OptionAltCarry) {
105 return ""
106 }
107 return "DX"
108 }
109 return ""
110 }
111
112 func x86Suffix(a *Asm) string {
113
114 if a.Arch.Name == "386" {
115 return "L"
116 }
117 return "Q"
118 }
119
120 func x86MulWide(a *Asm, src1, src2, dstlo, dsthi Reg) {
121 if a.Enabled(OptionAltCarry) {
122
123 if src1.name != "DX" {
124 if src2.name != "DX" {
125 a.Fatalf("mul src1 or src2 must be DX")
126 }
127 src2 = src1
128 }
129 a.Printf("\tMULXQ %s, %s, %s\n", src2, dstlo, dsthi)
130 return
131 }
132
133 if src1.name != "AX" {
134 if src2.name != "AX" {
135 a.Fatalf("mulwide src1 or src2 must be AX")
136 }
137 src2 = src1
138 }
139 if dstlo.name != "AX" {
140 a.Fatalf("mulwide dstlo must be AX")
141 }
142 if dsthi.name != "DX" {
143 a.Fatalf("mulwide dsthi must be DX")
144 }
145 a.Printf("\tMUL%s %s\n", x86Suffix(a), src2)
146 }
147
View as plain text