4 #define MAXTEMP (1 << 12)
26 #define TMP_BT(t) ((t)->type == TMP_ADDR ? 8 : (t)->bt)
28 static char buf
[SECSIZE
];
31 static long spsub_addr
;
40 static void putint(char *s
, long n
, int l
)
48 static void os(char *s
, int n
)
54 static void oi(long n
, int l
)
62 static void o_op(int op
, int r1
, int r2
, unsigned bt
)
69 if (rex
|| (bt
& BT_SZMASK
) == 8)
71 if ((bt
& BT_SZMASK
) == 2)
73 if ((bt
& BT_SZMASK
) == 1)
78 static void memop(int op
, int src
, int base
, int off
, unsigned bt
)
80 int dis
= off
== (char) off
? 1 : 4;
81 int mod
= off
== 4 ? 2 : 1;
82 o_op(op
, src
, base
, bt
);
85 oi((mod
<< 6) | ((src
& 0x07) << 3) | (base
& 0x07), 1);
90 static void regop(int op
, int src
, int dst
, unsigned bt
)
92 o_op(op
, src
, dst
, bt
);
93 oi((3 << 6) | (src
<< 3) | (dst
& 0x07), 1);
96 static long sp_push(int size
)
105 static void deref(unsigned bt
)
107 memop(MOV_M2R
, R_RAX
, R_RAX
, 0, bt
);
110 static unsigned tmp_pop(int rval
)
112 struct tmp
*t
= &tmp
[--ntmp
];
113 memop(MOV_M2R
, R_RAX
, R_RBP
, -t
->addr
, TMP_BT(t
));
115 if (!rval
&& t
->type
== TMP_ADDR
)
120 static void tmp_push(int type
, unsigned bt
)
122 struct tmp
*t
= &tmp
[ntmp
++];
123 t
->addr
= sp_push(8);
126 memop(MOV_R2X
, R_RAX
, R_RBP
, -t
->addr
, TMP_BT(t
));
136 static long codeaddr(void)
141 void o_func_beg(char *name
)
145 os("\x55", 1); /* push %rbp */
146 os("\x48\x89\xe5", 3); /* mov %rsp, %rbp */
150 os("\x48\x81\xec", 3); /* sub $xxx, %rsp */
151 spsub_addr
= codeaddr();
155 void o_num(int n
, unsigned bt
)
159 tmp_push(TMP_CONST
, bt
);
162 void o_deref(unsigned bt
)
165 tmp_push(TMP_ADDR
, bt
);
168 void o_ret(unsigned bt
)
173 os("\x31\xc0", 3); /* xor %eax, %eax */
174 os("\xc9\xc3", 2); /* leave; ret; */
177 static int binop(void)
181 regop(MOV_R2X
, R_RAX
, R_RBX
, vs1
);
189 regop(ADD_R2R
, R_RBX
, R_RAX
, bt
);
190 tmp_push(TMP_CONST
, bt
);
196 regop(SUB_R2R
, R_RBX
, R_RAX
, bt
);
197 tmp_push(TMP_CONST
, bt
);
200 void o_func_end(void)
202 os("\xc9\xc3", 2); /* leave; ret; */
203 out_func_end(buf
, cur
- buf
);
204 putint(buf
+ spsub_addr
, maxsp
+ 8, 4);
207 void o_local(long addr
, unsigned bt
)
209 os("\x48\x89\xe8", 3); /* mov %rbp, %rax */
210 os("\x48\x05", 2); /* add $addr, %rax */
212 tmp_push(TMP_ADDR
, bt
);
215 long o_mklocal(unsigned bt
)
220 static int arg_regs
[] = {R_RDI
, R_RSI
, R_RDX
, R_RCX
, R_R8
, R_R9
};
222 long o_arg(int i
, unsigned bt
)
224 long addr
= o_mklocal(bt
);
225 memop(MOV_R2X
, arg_regs
[i
], R_RBP
, -addr
, bt
);
229 void o_assign(unsigned bt
)
231 int vs2
= tmp_pop(0);
232 regop(MOV_R2X
, R_RAX
, R_RBX
, vs2
);
234 memop(MOV_R2X
, R_RBX
, R_RAX
, 0, bt
);
244 os("\x48\x85\xc0", 3); /* test %rax, %rax */
245 os("\x0f\x84", 2); /* jz $addr */
246 oi(codeaddr() - addr
- 4, 4);
252 return cur
- buf
- 4;
255 void o_filljz(long addr
)
257 putint(buf
+ addr
, codeaddr() - addr
- 4, 4);
260 void o_symaddr(char *name
, unsigned bt
)
262 os("\x48\xc7\xc0", 3); /* mov $addr, %rax */
263 out_rela(name
, codeaddr());
265 tmp_push(TMP_ADDR
, bt
);
268 void o_call(int argc
, unsigned *bt
, unsigned ret_bt
)
271 for (i
= 0; i
< argc
; i
++) {
273 regop(MOV_R2X
, R_RAX
, arg_regs
[i
], bt
[i
]);
276 os("\xff\xd0", 2); /* callq *%rax */
278 tmp_push(TMP_CONST
, ret_bt
);