out: use zero st_name for unnamed symbols
[neatcc/cc.git] / gen.c
blob9d1b59d77504895c9d894248dd317eaeb5ea1b44
1 #include <stdlib.h>
2 #include <string.h>
3 #include "gen.h"
4 #include "tok.h"
6 #define TMP_ADDR 0x0001
7 #define LOC_REG 0x0100
8 #define LOC_MEM 0x0200
9 #define LOC_NUM 0x0400
10 #define LOC_SYM 0x0800
11 #define LOC_LOCAL 0x1000
12 #define LOC_MASK 0xff00
14 #define R_RAX 0x00
15 #define R_RCX 0x01
16 #define R_RDX 0x02
17 #define R_RBX 0x03
18 #define R_RSP 0x04
19 #define R_RBP 0x05
20 #define R_RSI 0x06
21 #define R_RDI 0x07
22 #define R_R8 0x08
23 #define R_R9 0x09
24 #define R_R10 0x0a
25 #define R_R11 0x0b
26 #define R_R12 0x0c
27 #define R_R13 0x0d
28 #define R_R14 0x0e
29 #define R_R15 0x0f
30 #define NREGS 0x10
32 #define MOV_M2R 0x8b
33 #define MOV_R2X 0x89
34 #define MOV_I2X 0xc7
35 #define MOV_I2R 0xb8
36 #define ADD_R2X 0x03
37 #define SUB_R2X 0x2b
38 #define SHX_REG 0xd3
39 #define CMP_R2X 0x3b
40 #define LEA_M2R 0x8d
41 #define NEG_REG 0xf7
42 #define NOT_REG 0xf7
43 #define CALL_REG 0xff
44 #define MUL_A2X 0xf7
45 #define XOR_R2X 0x33
46 #define AND_R2X 0x23
47 #define OR_R2X 0x0b
48 #define TEST_R2R 0x85
50 #define R_BYTEMASK (1 << R_RAX | 1 << R_RDX | 1 << R_RCX)
51 #define TMP_BT(t) ((t)->flags & TMP_ADDR ? 8 : (t)->bt)
52 #define TMP_REG(t) ((t)->flags & LOC_REG ? (t)->addr : reg_get(~0))
53 #define TMP_REG2(t, r) ((t)->flags & LOC_REG && (t)->addr != r ? \
54 (t)->addr : reg_get(~(1 << r)))
55 #define TMP_BYTEREG(t) ((t)->flags & LOC_REG && \
56 (1 << (t)->addr) & R_BYTEMASK ? \
57 (t)->addr : reg_get(R_BYTEMASK))
58 #define BT_TMPBT(bt) (BT_SZ(bt) >= 4 ? (bt) : (bt) & BT_SIGNED | 4)
60 static char buf[SECSIZE];
61 static char *cur;
62 static int nogen;
63 static long sp;
64 static long spsub_addr;
65 static long maxsp;
67 static struct tmp {
68 long addr;
69 unsigned flags;
70 unsigned bt;
71 } tmp[MAXTMP];
72 static int ntmp;
74 static int tmpsp;
76 static struct tmp *regs[NREGS];
77 static int tmpregs[] = {R_RAX, R_RDI, R_RSI, R_RDX, R_RCX, R_R8, R_R9};
79 #define MAXRET (1 << 8)
81 static long ret[MAXRET];
82 static int nret;
84 static long cmp_last;
85 static long cmp_setl;
87 static void putint(char *s, long n, int l)
89 if (nogen)
90 return;
91 while (l--) {
92 *s++ = n;
93 n >>= 8;
97 static void os(char *s, int n)
99 if (nogen)
100 return;
101 while (n--)
102 *cur++ = *s++;
105 static void oi(long n, int l)
107 while (l--) {
108 *cur++ = n;
109 n >>= 8;
113 static long codeaddr(void)
115 return cur - buf;
118 static void o_op(int *op, int nop, int r1, int r2, unsigned bt)
120 int rex = 0;
121 int i;
122 if (r1 & 0x8)
123 rex |= 4;
124 if (r2 & 0x8)
125 rex |= 1;
126 if (BT_SZ(bt) == 8)
127 rex |= 8;
128 if (rex || (bt & BT_SZMASK) == 8)
129 oi(0x40 | rex, 1);
130 if ((bt & BT_SZMASK) == 2)
131 oi(0x66, 1);
132 if ((bt & BT_SZMASK) == 1)
133 op[nop - 1] &= ~0x1;
134 for (i = 0; i < nop; i++)
135 oi(op[i], 1);
138 static void memop(int *op, int nop, int src, int base, int off, unsigned bt)
140 int dis = off == (char) off ? 1 : 4;
141 int mod = dis == 4 ? 2 : 1;
142 o_op(op, nop, src, base, bt);
143 if (!off)
144 mod = 0;
145 oi((mod << 6) | ((src & 0x07) << 3) | (base & 0x07), 1);
146 if (off)
147 oi(off, dis);
150 static void memop1(int op, int src, int base, int off, unsigned bt)
152 memop(&op, 1, src, base, off, bt);
155 static void regop(int *op, int nop, int src, int dst, unsigned bt)
157 o_op(op, nop, src, dst, bt);
158 oi((3 << 6) | (src << 3) | (dst & 0x07), 1);
161 static void regop1(int op, int src, int dst, unsigned bt)
163 regop(&op, 1, src, dst, bt);
166 static long sp_push(int size)
168 sp += size;
169 if (sp > maxsp)
170 maxsp = sp;
171 return sp;
174 #define LOC_NEW(f, l) (((f) & ~LOC_MASK) | (l))
176 static void tmp_mem(struct tmp *tmp)
178 int src = tmp->addr;
179 if (!(tmp->flags & LOC_REG))
180 return;
181 if (tmpsp == -1)
182 tmpsp = sp;
183 tmp->addr = sp_push(8);
184 memop1(MOV_R2X, src, R_RBP, -tmp->addr, BT_TMPBT(TMP_BT(tmp)));
185 regs[src] = NULL;
186 tmp->flags = LOC_NEW(tmp->flags, LOC_MEM);
189 static int *movxx_x2r(int bt)
191 static int movxx[2] = {0x0f};
192 if (BT_SZ(bt) == 1)
193 movxx[1] = bt & BT_SIGNED ? 0xbe : 0xb6;
194 else
195 movxx[1] = bt & BT_SIGNED ? 0xbf : 0xb7;
196 return movxx;
199 #define MOVSXD 0x63
201 static void mov_r2r(int r1, int r2, unsigned bt1, unsigned bt2)
203 int s1 = bt1 & BT_SIGNED;
204 int s2 = bt2 & BT_SIGNED;
205 int sz1 = BT_SZ(bt1);
206 int sz2 = BT_SZ(bt2);
207 if (sz2 < 4 && (sz1 >= sz2 && s1 != s2)) {
208 regop(movxx_x2r(bt2), 2, r1, r2, 4);
209 return;
211 if (sz1 == 4 && sz2 == 8) {
212 regop1(MOVSXD, r1, r2, sz2);
213 return;
215 if (r1 != r2 || sz1 > sz2)
216 regop1(MOV_R2X, r1, r2, BT_TMPBT(bt2));
219 static void mov_m2r(int dst, int base, int off, int bt1, int bt2)
221 if (BT_SZ(bt1) < 4) {
222 memop(movxx_x2r(bt1), 2, dst, base, off,
223 bt1 & BT_SIGNED && BT_SZ(bt2) == 8 ? 8 : 4);
224 mov_r2r(dst, dst, bt1, bt2);
225 } else {
226 memop1(MOV_M2R, dst, base, off, bt1);
227 mov_r2r(dst, dst, bt1, bt2);
231 static void num_cast(struct tmp *t, unsigned bt)
233 if (!(bt & BT_SIGNED) && BT_SZ(bt) != 8)
234 t->addr &= ((1l << (long) (BT_SZ(bt) * 8)) - 1);
235 t->bt = bt;
238 static void num_reg(int reg, unsigned bt, long num)
240 int op = MOV_I2R + (reg & 7);
241 if (BT_SZ(bt) == 8 && num >= 0 && num == (unsigned) num)
242 bt = 4;
243 o_op(&op, 1, 0, reg, bt);
244 oi(num, BT_SZ(bt));
247 static void tmp_reg(struct tmp *tmp, int dst, unsigned bt, int deref)
249 if (!(tmp->flags & TMP_ADDR))
250 deref = 0;
251 if (deref)
252 tmp->flags &= ~TMP_ADDR;
253 if (tmp->flags & LOC_NUM) {
254 num_cast(tmp, bt);
255 tmp->bt = BT_TMPBT(bt);
256 num_reg(dst, tmp->bt, tmp->addr);
257 tmp->addr = dst;
258 regs[dst] = tmp;
259 tmp->flags = LOC_NEW(tmp->flags, LOC_REG);
261 if (tmp->flags & LOC_SYM) {
262 regop1(MOV_I2X, 0, dst, TMP_BT(tmp));
263 if (!nogen)
264 out_rela(tmp->addr, codeaddr(), 0);
265 oi(0, 4);
266 tmp->addr = dst;
267 regs[dst] = tmp;
268 tmp->flags = LOC_NEW(tmp->flags, LOC_REG);
270 if (tmp->flags & LOC_REG) {
271 if (deref)
272 mov_m2r(dst, tmp->addr, 0, tmp->bt, bt);
273 else
274 mov_r2r(tmp->addr, dst, TMP_BT(tmp), bt);
275 regs[tmp->addr] = NULL;
276 tmp->addr = dst;
277 tmp->bt = BT_TMPBT(bt);
278 regs[dst] = tmp;
279 return;
281 if (tmp->flags & LOC_LOCAL) {
282 if (deref)
283 mov_m2r(dst, R_RBP, -tmp->addr, tmp->bt, bt);
284 else
285 memop1(LEA_M2R, dst, R_RBP, -tmp->addr, 8);
287 if (tmp->flags & LOC_MEM) {
288 mov_m2r(dst, R_RBP, -tmp->addr,
289 deref ? 8 : TMP_BT(tmp), deref ? 8 : bt);
290 if (deref)
291 mov_m2r(dst, dst, 0, tmp->bt, bt);
293 tmp->addr = dst;
294 tmp->bt = BT_TMPBT(bt);
295 regs[dst] = tmp;
296 tmp->flags = LOC_NEW(tmp->flags, LOC_REG);
299 static void reg_free(int reg)
301 int i;
302 if (!regs[reg])
303 return;
304 for (i = 0; i < ARRAY_SIZE(tmpregs); i++)
305 if (!regs[tmpregs[i]]) {
306 tmp_reg(regs[reg], tmpregs[i], regs[reg]->bt, 0);
307 return;
309 tmp_mem(regs[reg]);
312 static void reg_for(int reg, struct tmp *t)
314 if (regs[reg] && regs[reg] != t)
315 reg_free(reg);
318 static void tmp_pop_bt(unsigned bt, int reg)
320 struct tmp *t = &tmp[--ntmp];
321 reg_for(reg, t);
322 tmp_reg(t, reg, bt, 1);
323 regs[reg] = NULL;
326 static unsigned tmp_pop(int deref, int reg)
328 struct tmp *t = &tmp[--ntmp];
329 reg_for(reg, t);
330 tmp_reg(t, reg, deref ? t->bt : TMP_BT(t), deref);
331 regs[reg] = NULL;
332 return t->bt;
335 static void tmp_push_reg(unsigned bt, unsigned reg)
337 struct tmp *t = &tmp[ntmp++];
338 t->addr = reg;
339 t->bt = bt;
340 t->flags = LOC_REG;
341 regs[reg] = t;
344 void o_local(long addr, unsigned bt)
346 struct tmp *t = &tmp[ntmp++];
347 t->addr = addr;
348 t->bt = bt;
349 t->flags = LOC_LOCAL | TMP_ADDR;
352 void o_num(long num, unsigned bt)
354 struct tmp *t = &tmp[ntmp++];
355 t->addr = num;
356 t->bt = bt;
357 t->flags = LOC_NUM;
360 void o_symaddr(long addr, unsigned bt)
362 struct tmp *t = &tmp[ntmp++];
363 t->bt = bt;
364 t->addr = addr;
365 t->flags = LOC_SYM | TMP_ADDR;
368 void o_tmpdrop(int n)
370 int i;
371 if (n == -1 || n > ntmp)
372 n = ntmp;
373 ntmp -= n;
374 for (i = ntmp; i < ntmp + n; i++)
375 if (tmp[i].flags & LOC_REG)
376 regs[tmp[i].addr] = NULL;
377 if (!ntmp) {
378 if (tmpsp != -1)
379 sp = tmpsp;
380 tmpsp = -1;
384 #define FORK_REG R_RAX
386 void o_tmpfork(void)
388 struct tmp *t = &tmp[ntmp - 1];
389 reg_for(FORK_REG, t);
390 tmp_reg(t, FORK_REG, t->bt, 0);
391 o_tmpdrop(1);
394 void o_tmpjoin(void)
396 struct tmp *t = &tmp[ntmp - 1];
397 reg_for(FORK_REG, t);
398 tmp_reg(t, FORK_REG, t->bt, 0);
401 void o_tmpswap(void)
403 struct tmp *t1 = &tmp[ntmp - 1];
404 struct tmp *t2 = &tmp[ntmp - 2];
405 struct tmp t;
406 memcpy(&t, t1, sizeof(t));
407 memcpy(t1, t2, sizeof(t));
408 memcpy(t2, &t, sizeof(t));
411 static int reg_get(int mask)
413 int i;
414 for (i = 0; i < ARRAY_SIZE(tmpregs); i++)
415 if ((1 << tmpregs[i]) & mask && !regs[tmpregs[i]])
416 return tmpregs[i];
417 for (i = 0; i < ARRAY_SIZE(tmpregs); i++)
418 if ((1 << tmpregs[i]) & mask) {
419 reg_free(tmpregs[i]);
420 return tmpregs[i];
422 return 0;
425 void o_tmpcopy(void)
427 struct tmp *t1 = &tmp[ntmp - 1];
428 struct tmp *t2 = &tmp[ntmp++];
429 memcpy(t2, t1, sizeof(*t1));
430 if (!(t1->flags & (LOC_REG | LOC_MEM)))
431 return;
432 if (t1->flags & LOC_MEM) {
433 tmp_reg(t2, reg_get(~0), t2->bt, 0);
434 } else if (t1->flags & LOC_REG) {
435 t2->addr = reg_get(~t1->addr);
436 regop1(MOV_R2X, t1->addr, t2->addr, BT_TMPBT(TMP_BT(tmp)));
438 t2->flags = t1->flags;
441 void o_cast(unsigned bt)
443 struct tmp *t = &tmp[ntmp - 1];
444 int reg;
445 if (t->bt == bt)
446 return;
447 if (t->flags & LOC_NUM) {
448 num_cast(t, bt);
449 return;
451 reg = BT_SZ(bt) == 1 ? TMP_BYTEREG(t) : TMP_REG(t);
452 tmp_pop_bt(bt, reg);
453 tmp_push_reg(bt, reg);
456 long o_func_beg(char *name, int global)
458 long addr = out_func_beg(name, global);
459 cur = buf;
460 os("\x55", 1); /* push %rbp */
461 os("\x48\x89\xe5", 3); /* mov %rsp, %rbp */
462 sp = 0;
463 maxsp = 0;
464 ntmp = 0;
465 tmpsp = -1;
466 nret = 0;
467 cmp_last = -1;
468 memset(regs, 0, sizeof(regs));
469 os("\x48\x81\xec", 3); /* sub $xxx, %rsp */
470 spsub_addr = codeaddr();
471 oi(0, 4);
472 return addr;
475 void o_deref(unsigned bt)
477 struct tmp *t = &tmp[ntmp - 1];
478 if (t->flags & TMP_ADDR)
479 tmp_reg(t, TMP_REG(t), 8, 1);
480 t->bt = bt;
481 t->flags |= TMP_ADDR;
484 void o_load(void)
486 struct tmp *t = &tmp[ntmp - 1];
487 tmp_reg(t, TMP_REG(t), t->bt, 1);
490 static unsigned bt_op(unsigned bt1, unsigned bt2)
492 unsigned s1 = BT_SZ(bt1);
493 unsigned s2 = BT_SZ(bt2);
494 unsigned bt = (bt1 | bt2) & BT_SIGNED | (s1 > s2 ? s1 : s2);
495 return BT_TMPBT(bt);
498 #define TMP_CONST(t) ((t)->flags & LOC_NUM && !((t)->flags & TMP_ADDR))
500 int o_popnum(long *c)
502 struct tmp *t = &tmp[ntmp - 1];
503 if (!TMP_CONST(t))
504 return 1;
505 *c = t->addr;
506 o_tmpdrop(1);
507 return 0;
510 static int c_binop(long (*cop)(long a, long b, unsigned bt), unsigned bt)
512 struct tmp *t1 = &tmp[ntmp - 1];
513 struct tmp *t2 = &tmp[ntmp - 2];
514 long ret;
515 if (!TMP_CONST(t1) || !TMP_CONST(t2))
516 return 1;
517 if (!bt)
518 bt = bt_op(t1->bt, t2->bt);
519 ret = cop(t2->addr, t1->addr, bt);
520 o_tmpdrop(2);
521 o_num(ret, bt);
522 return 0;
525 static int c_op(long (*cop)(long a, unsigned bt), unsigned bt)
527 struct tmp *t1 = &tmp[ntmp - 1];
528 long ret;
529 if (!TMP_CONST(t1))
530 return 1;
531 if (!bt)
532 bt = t1->bt;
533 ret = cop(t1->addr, bt);
534 o_tmpdrop(1);
535 o_num(ret, bt);
536 return 0;
539 static void shx(int uop, int sop)
541 struct tmp *t = &tmp[ntmp - 2];
542 unsigned bt;
543 unsigned reg = TMP_REG2(t, R_RCX);
544 tmp_pop(1, R_RCX);
545 bt = tmp_pop(1, reg);
546 regop1(SHX_REG, bt & BT_SIGNED ? sop : uop, reg, BT_TMPBT(bt));
547 tmp_push_reg(bt, reg);
550 static long c_shl(long a, long b, unsigned bt)
552 return a << b;
555 void o_shl(void)
557 if (!c_binop(c_shl, 0))
558 return;
559 shx(4, 4);
562 static long c_shr(long a, long b, unsigned bt)
564 if (bt & BT_SIGNED)
565 return a >> b;
566 else
567 return (unsigned long) a >> b;
570 void o_shr(void)
572 if (!c_binop(c_shr, 0))
573 return;
574 shx(5, 7);
577 static int mulop(int uop, int sop, int reg)
579 struct tmp *t1 = &tmp[ntmp - 1];
580 struct tmp *t2 = &tmp[ntmp - 2];
581 int bt1 = TMP_BT(t1);
582 int bt2 = TMP_BT(t2);
583 int bt = bt_op(bt1, bt2);
584 if (t1->flags & LOC_REG && t1->addr != R_RAX && t1->addr != R_RDX)
585 reg = t1->addr;
586 reg_for(reg, t1);
587 tmp_reg(t1, reg, bt, 1);
588 reg_for(R_RAX, t2);
589 tmp_reg(t2, R_RAX, bt, 1);
590 if (reg != R_RDX)
591 reg_free(R_RDX);
592 o_tmpdrop(2);
593 regop1(MUL_A2X, bt & BT_SIGNED ? sop : uop, reg, BT_TMPBT(bt2));
594 return bt;
597 static long c_mul(long a, long b, unsigned bt)
599 return a * b;
602 void o_mul(void)
604 int bt;
605 if (!c_binop(c_mul, 0))
606 return;
607 bt = mulop(4, 5, R_RDX);
608 tmp_push_reg(bt, R_RAX);
611 static long c_div(long a, long b, unsigned bt)
613 return a / b;
616 void o_div(void)
618 int bt;
619 if (!c_binop(c_div, 0))
620 return;
621 bt = mulop(6, 7, R_RCX);
622 tmp_push_reg(bt, R_RAX);
625 static long c_mod(long a, long b, unsigned bt)
627 return a % b;
630 void o_mod(void)
632 int bt;
633 if (!c_binop(c_mod, 0))
634 return;
635 bt = mulop(6, 7, R_RCX);
636 tmp_push_reg(bt, R_RDX);
639 void o_addr(void)
641 tmp[ntmp - 1].flags &= ~TMP_ADDR;
642 tmp[ntmp - 1].bt = 8;
645 void o_ret(unsigned bt)
647 if (bt)
648 tmp_pop_bt(bt, R_RAX);
649 else
650 os("\x31\xc0", 2); /* xor %eax, %eax */
651 ret[nret++] = o_jmp(0);
654 static int binop(int op, int *reg)
656 struct tmp *t1 = &tmp[ntmp - 1];
657 struct tmp *t2 = &tmp[ntmp - 2];
658 int r1;
659 unsigned bt;
660 r1 = TMP_REG(t1);
661 *reg = TMP_REG2(t2, r1);
662 bt = bt_op(t1->bt, t2->bt);
663 tmp_pop_bt(bt, r1);
664 tmp_pop_bt(bt, *reg);
665 regop1(op, *reg, r1, bt);
666 return bt;
669 static long c_add(long a, long b, unsigned bt)
671 return a + b;
674 void o_add(void)
676 int reg;
677 int bt;
678 if (!c_binop(c_add, 0))
679 return;
680 bt = binop(ADD_R2X, &reg);
681 tmp_push_reg(bt, reg);
684 static long c_xor(long a, long b, unsigned bt)
686 return a ^ b;
689 void o_xor(void)
691 int reg;
692 int bt;
693 if (!c_binop(c_xor, 0))
694 return;
695 bt = binop(XOR_R2X, &reg);
696 tmp_push_reg(bt, reg);
699 static long c_and(long a, long b, unsigned bt)
701 return a & b;
704 void o_and(void)
706 int reg;
707 int bt;
708 if (!c_binop(c_and, 0))
709 return;
710 bt = binop(AND_R2X, &reg);
711 tmp_push_reg(bt, reg);
714 static long c_or(long a, long b, unsigned bt)
716 return a | b;
719 void o_or(void)
721 int reg;
722 int bt;
723 if (!c_binop(c_or, 0))
724 return;
725 bt = binop(OR_R2X, &reg);
726 tmp_push_reg(bt, reg);
729 static long c_sub(long a, long b, unsigned bt)
731 return a - b;
734 void o_sub(void)
736 int reg;
737 int bt;
738 if (!c_binop(c_sub, 0))
739 return;
740 bt = binop(SUB_R2X, &reg);
741 tmp_push_reg(bt, reg);
744 static void o_cmp(int uop, int sop)
746 char set[] = "\x0f\x00\xc0";
747 int reg;
748 int bt = binop(CMP_R2X, &reg);
749 set[1] = bt & BT_SIGNED ? sop : uop;
750 reg_free(R_RAX);
751 cmp_setl = codeaddr();
752 os(set, 3); /* setl %al */
753 os("\x0f\xb6\xc0", 3); /* movzbl %al, %eax */
754 tmp_push_reg(4 | BT_SIGNED, R_RAX);
755 cmp_last = codeaddr();
758 static long c_lt(long a, long b, unsigned bt)
760 return a < b;
763 void o_lt(void)
765 if (!c_binop(c_lt, 4))
766 return;
767 o_cmp(0x92, 0x9c);
770 static long c_gt(long a, long b, unsigned bt)
772 return a > b;
775 void o_gt(void)
777 if (!c_binop(c_gt, 4))
778 return;
779 o_cmp(0x97, 0x9f);
782 static long c_le(long a, long b, unsigned bt)
784 return a <= b;
787 void o_le(void)
789 if (!c_binop(c_le, 4))
790 return;
791 o_cmp(0x96, 0x9e);
794 static long c_ge(long a, long b, unsigned bt)
796 return a >= b;
799 void o_ge(void)
801 if (!c_binop(c_ge, 4))
802 return;
803 o_cmp(0x93, 0x9d);
806 static long c_eq(long a, long b, unsigned bt)
808 return a == b;
811 void o_eq(void)
813 if (!c_binop(c_eq, 4))
814 return;
815 o_cmp(0x94, 0x94);
818 static long c_neq(long a, long b, unsigned bt)
820 return a != b;
823 void o_neq(void)
825 if (!c_binop(c_neq, 4))
826 return;
827 o_cmp(0x95, 0x95);
830 static long c_lnot(long a, unsigned bt)
832 return !a;
835 void o_lnot(void)
837 if (!c_op(c_lnot, 4))
838 return;
839 if (cmp_last == codeaddr()) {
840 buf[cmp_setl + 1] ^= 0x10;
841 } else {
842 o_num(0, 4 | BT_SIGNED);
843 o_eq();
847 static long c_neg(long a, unsigned bt)
849 return -a;
852 void o_neg(void)
854 struct tmp *t = &tmp[ntmp - 1];
855 int reg;
856 unsigned bt = BT_TMPBT(t->bt);
857 if (!c_op(c_neg, t->bt | BT_SIGNED))
858 return;
859 reg = TMP_REG(t);
860 tmp_pop_bt(bt, reg);
861 regop1(NEG_REG, 3, reg, bt);
862 tmp_push_reg(bt, reg);
865 static long c_not(long a, unsigned bt)
867 return ~a;
870 void o_not(void)
872 struct tmp *t = &tmp[ntmp - 1];
873 int reg;
874 unsigned bt = BT_TMPBT(t->bt);
875 if (!c_op(c_not, 0))
876 return;
877 reg = TMP_REG(t);
878 tmp_pop_bt(bt, reg);
879 regop1(NOT_REG, 2, reg, bt);
880 tmp_push_reg(t->bt, reg);
883 void o_func_end(void)
885 int i;
886 for (i = 0; i < nret; i++)
887 o_filljmp(ret[i]);
888 os("\xc9\xc3", 2); /* leave; ret; */
889 putint(buf + spsub_addr, (maxsp + 7) & ~0x07, 4);
890 out_func_end(buf, cur - buf);
893 long o_mklocal(int size)
895 return sp_push((size + 7) & ~0x07);
898 void o_rmlocal(long addr, int sz)
900 sp = addr - sz;
903 static int arg_regs[] = {R_RDI, R_RSI, R_RDX, R_RCX, R_R8, R_R9};
905 long o_arg(int i, unsigned bt)
907 long addr = o_mklocal(BT_SZ(bt));
908 memop1(MOV_R2X, arg_regs[i], R_RBP, -addr, bt);
909 return addr;
912 void o_assign(unsigned bt)
914 struct tmp *t1 = &tmp[ntmp - 1];
915 struct tmp *t2 = &tmp[ntmp - 2];
916 int r1 = BT_SZ(bt) > 1 ? TMP_REG(t1) : TMP_BYTEREG(t1);
917 int reg;
918 int off;
919 tmp_pop_bt(BT_TMPBT(bt), r1);
920 if (t2->flags & LOC_LOCAL) {
921 reg = R_RBP;
922 off = -t2->addr;
923 o_tmpdrop(1);
924 } else {
925 reg = TMP_REG2(t2, r1);
926 off = 0;
927 tmp_pop(0, reg);
929 memop1(MOV_R2X, r1, reg, off, bt);
930 tmp_push_reg(bt, r1);
933 long o_mklabel(void)
935 return codeaddr();
938 static long jx(int x, long addr)
940 char op[2] = {0x0f};
941 op[1] = x;
942 os(op, 2); /* jx $addr */
943 oi(addr - codeaddr() - 4, 4);
944 return codeaddr() - 4;
947 static long jxtest(int x, long addr)
949 int bt = tmp_pop(1, R_RAX);
950 regop1(TEST_R2R, R_RAX, R_RAX, bt);
951 return jx(x, addr);
954 static long jxcmp(long addr, int inv)
956 int x;
957 if (codeaddr() != cmp_last)
958 return -1;
959 o_tmpdrop(1);
960 cur = buf + cmp_setl;
961 x = (unsigned char) buf[cmp_setl + 1];
962 return jx((inv ? x : x ^ 0x01) & ~0x10, addr);
965 long o_jz(long addr)
967 long ret = jxcmp(addr, 0);
968 return ret != -1 ? ret : jxtest(0x84, addr);
971 long o_jnz(long addr)
973 long ret = jxcmp(addr, 1);
974 return ret != -1 ? ret : jxtest(0x85, addr);
977 long o_jmp(long addr)
979 os("\xe9", 1); /* jmp $addr */
980 oi(addr - codeaddr() - 4, 4);
981 return codeaddr() - 4;
984 void o_filljmp2(long addr, long jmpdst)
986 putint(buf + addr, jmpdst - addr - 4, 4);
989 void o_filljmp(long addr)
991 o_filljmp2(addr, codeaddr());
994 void o_call(int argc, unsigned *bt, unsigned ret_bt)
996 int i;
997 struct tmp *t;
998 for (i = 0; i < argc; i++)
999 tmp_pop_bt(bt[argc - i - 1], arg_regs[argc - i - 1]);
1000 t = &tmp[ntmp - 1];
1001 if (t->flags & LOC_SYM) {
1002 os("\x31\xc0", 2); /* xor %eax, %eax */
1003 os("\xe8", 1); /* call $x */
1004 if (!nogen)
1005 out_rela(t->addr, codeaddr(), 1);
1006 oi(-4, 4);
1007 o_tmpdrop(1);
1008 } else {
1009 tmp_pop(0, R_RAX);
1010 regop1(CALL_REG, 2, R_RAX, 4);
1012 for (i = 0; i < ARRAY_SIZE(tmpregs); i++)
1013 if (regs[i])
1014 tmp_mem(regs[i]);
1015 if (ret_bt)
1016 tmp_push_reg(ret_bt, R_RAX);
1019 int o_nogen(void)
1021 return nogen++;
1024 void o_dogen(void)
1026 nogen = 0;