1
16
17 package abi
18
19 import (
20 `fmt`
21 `reflect`
22 `unsafe`
23
24 . `github.com/chenzhuoyu/iasm/x86_64`
25 )
26
27 const (
28 PtrSize = 8
29 PtrAlign = 8
30 )
31
32 var iregOrderC = []Register{
33 RDI,
34 RSI,
35 RDX,
36 RCX,
37 R8,
38 R9,
39 }
40
41 var xregOrderC = []Register{
42 XMM0,
43 XMM1,
44 XMM2,
45 XMM3,
46 XMM4,
47 XMM5,
48 XMM6,
49 XMM7,
50 }
51
52 var (
53 intType = reflect.TypeOf(0)
54 ptrType = reflect.TypeOf(unsafe.Pointer(nil))
55 )
56
57 func (self *Frame) argv(i int) *MemoryOperand {
58 return Ptr(RSP, int32(self.Prev() + self.desc.Args[i].Mem))
59 }
60
61
62 func (self *Frame) spillv(i int) *MemoryOperand {
63
64 return Ptr(RSP, PtrSize + int32(self.desc.Args[i].Mem))
65 }
66
67 func (self *Frame) retv(i int) *MemoryOperand {
68 return Ptr(RSP, int32(self.Prev() + self.desc.Rets[i].Mem))
69 }
70
71 func (self *Frame) resv(i int) *MemoryOperand {
72 return Ptr(RSP, int32(self.Offs() - uint32((i+1) * PtrSize)))
73 }
74
75 func (self *Frame) emitGrowStack(p *Program, entry *Label) {
76
77 for i, v := range self.desc.Args {
78 if v.InRegister {
79 if v.IsFloat == floatKind64 {
80 p.MOVSD(v.Reg, self.spillv(i))
81 } else if v.IsFloat == floatKind32 {
82 p.MOVSS(v.Reg, self.spillv(i))
83 }else {
84 p.MOVQ(v.Reg, self.spillv(i))
85 }
86 }
87 }
88
89
90 p.MOVQ(F_morestack_noctxt, R12)
91 p.CALLQ(R12)
92
93 for i, v := range self.desc.Args {
94 if v.InRegister {
95 if v.IsFloat == floatKind64 {
96 p.MOVSD(self.spillv(i), v.Reg)
97 } else if v.IsFloat == floatKind32 {
98 p.MOVSS(self.spillv(i), v.Reg)
99 }else {
100 p.MOVQ(self.spillv(i), v.Reg)
101 }
102 }
103 }
104
105
106 p.JMP(entry)
107 }
108
109 func (self *Frame) GrowStackTextSize() uint32 {
110 p := DefaultArch.CreateProgram()
111
112 for i, v := range self.desc.Args {
113 if v.InRegister {
114 if v.IsFloat == floatKind64 {
115 p.MOVSD(v.Reg, self.spillv(i))
116 } else if v.IsFloat == floatKind32 {
117 p.MOVSS(v.Reg, self.spillv(i))
118 }else {
119 p.MOVQ(v.Reg, self.spillv(i))
120 }
121 }
122 }
123
124
125 p.MOVQ(F_morestack_noctxt, R12)
126 p.CALLQ(R12)
127
128 for i, v := range self.desc.Args {
129 if v.InRegister {
130 if v.IsFloat == floatKind64 {
131 p.MOVSD(self.spillv(i), v.Reg)
132 } else if v.IsFloat == floatKind32 {
133 p.MOVSS(self.spillv(i), v.Reg)
134 } else {
135 p.MOVQ(self.spillv(i), v.Reg)
136 }
137 }
138 }
139
140
141 l := CreateLabel("")
142 p.Link(l)
143 p.JMP(l)
144
145 return uint32(len(p.Assemble(0)))
146 }
147
148 func (self *Frame) emitPrologue(p *Program) {
149 p.SUBQ(self.Size(), RSP)
150 p.MOVQ(RBP, Ptr(RSP, int32(self.Offs())))
151 p.LEAQ(Ptr(RSP, int32(self.Offs())), RBP)
152 }
153
154 func (self *Frame) emitEpilogue(p *Program) {
155 p.MOVQ(Ptr(RSP, int32(self.Offs())), RBP)
156 p.ADDQ(self.Size(), RSP)
157 p.RET()
158 }
159
160 func (self *Frame) emitReserveRegs(p *Program) {
161
162 for i, r := range ReservedRegs(self.ccall) {
163 switch r.(type) {
164 case Register64:
165 p.MOVQ(r, self.resv(i))
166 case XMMRegister:
167 p.MOVSD(r, self.resv(i))
168 default:
169 panic(fmt.Sprintf("unsupported register type %t to reserve", r))
170 }
171 }
172 }
173
174 func (self *Frame) emitSpillPtrs(p *Program) {
175
176 for i, r := range self.desc.Args {
177 if r.InRegister && r.IsPointer {
178 p.MOVQ(r.Reg, self.argv(i))
179 }
180 }
181 }
182
183 func (self *Frame) emitClearPtrs(p *Program) {
184
185 for i, r := range self.desc.Args {
186 if r.InRegister && r.IsPointer {
187 p.MOVQ(int64(0), self.argv(i))
188 }
189 }
190 }
191
192 func (self *Frame) emitCallC(p *Program, addr uintptr) {
193 p.MOVQ(addr, RAX)
194 p.CALLQ(RAX)
195 }
196
197 type floatKind uint8
198
199 const (
200 notFloatKind floatKind = iota
201 floatKind32
202 floatKind64
203 )
204
205 type Parameter struct {
206 InRegister bool
207 IsPointer bool
208 IsFloat floatKind
209 Reg Register
210 Mem uint32
211 Type reflect.Type
212 }
213
214 func mkIReg(vt reflect.Type, reg Register64) (p Parameter) {
215 p.Reg = reg
216 p.Type = vt
217 p.InRegister = true
218 p.IsPointer = isPointer(vt)
219 return
220 }
221
222 func isFloat(vt reflect.Type) floatKind {
223 switch vt.Kind() {
224 case reflect.Float32:
225 return floatKind32
226 case reflect.Float64:
227 return floatKind64
228 default:
229 return notFloatKind
230 }
231 }
232
233 func mkXReg(vt reflect.Type, reg XMMRegister) (p Parameter) {
234 p.Reg = reg
235 p.Type = vt
236 p.InRegister = true
237 p.IsFloat = isFloat(vt)
238 return
239 }
240
241 func mkStack(vt reflect.Type, mem uint32) (p Parameter) {
242 p.Mem = mem
243 p.Type = vt
244 p.InRegister = false
245 p.IsPointer = isPointer(vt)
246 p.IsFloat = isFloat(vt)
247 return
248 }
249
250 func (self Parameter) String() string {
251 if self.InRegister {
252 return fmt.Sprintf("[%%%s, Pointer(%v), Float(%v)]", self.Reg, self.IsPointer, self.IsFloat)
253 } else {
254 return fmt.Sprintf("[%d(FP), Pointer(%v), Float(%v)]", self.Mem, self.IsPointer, self.IsFloat)
255 }
256 }
257
258 func CallC(addr uintptr, fr Frame, maxStack uintptr) []byte {
259 p := DefaultArch.CreateProgram()
260
261 stack := CreateLabel("_stack_grow")
262 entry := CreateLabel("_entry")
263 p.Link(entry)
264 fr.emitStackCheck(p, stack, maxStack)
265 fr.emitPrologue(p)
266 fr.emitReserveRegs(p)
267 fr.emitSpillPtrs(p)
268 fr.emitExchangeArgs(p)
269 fr.emitCallC(p, addr)
270 fr.emitExchangeRets(p)
271 fr.emitRestoreRegs(p)
272 fr.emitEpilogue(p)
273 p.Link(stack)
274 fr.emitGrowStack(p, entry)
275
276 return p.Assemble(0)
277 }
278
279
280 func (self *Frame) emitDebug(p *Program) {
281 p.INT(3)
282 }
View as plain text