8 /* variable location */
13 #define LOC_LOCAL 0x10
15 /* special registers */
19 #define REG_FORK R_RAX
33 #define N_TMPS ARRAY_SIZE(tmpregs)
36 #define R_SAVED 0x00c8
37 #define R_BYTEREGS (1 << R_RAX | 1 << R_RDX | 1 << R_RCX)
39 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
42 static char cs
[SECSIZE
]; /* code segment */
44 static char ds
[SECSIZE
]; /* data segment */
46 static long bsslen
; /* bss segment size */
48 static long sp
; /* stack pointer offset from R_RBP */
49 static long sp_max
; /* maximum stack pointer offset */
50 static long sp_tmp
; /* sp for the first tmp on the stack */
51 static long func_fpsub
; /* stack pointer sub address in CS */
53 #define TMP(i) (((i) < ntmp) ? &tmps[ntmp - 1 - (i)] : NULL)
58 long off
; /* offset from a symbol or a local */
59 unsigned loc
; /* variable location */
60 unsigned bt
; /* type of address; zero when not a pointer */
64 /* arch-specific functions */
65 static void i_ldr(int l
, int rd
, int rn
, int off
, int bt
);
66 static void i_mov(int rd
, int rn
, int bt
);
67 static void i_add(int op
, int rd
, int rn
, int rm
);
68 static void i_shl(int op
, int rd
, int rm
, int rs
);
69 static void i_mul(int rd
, int rn
, int rm
);
70 static void i_div(int op
, int rd
, int rn
, int rm
);
71 static void i_cmp(int rn
, int rm
);
72 static int i_decodeable(long imm
);
73 static void i_add_imm(int op
, int rd
, int rn
, long n
);
74 static void i_shl_imm(int op
, int rd
, int rn
, long n
);
75 static void i_cmp_imm(int rn
, long n
);
76 static void i_add_anyimm(int rd
, int rn
, long n
);
77 static void i_num(int rd
, long n
);
78 static void i_sym(int rd
, char *sym
, int off
);
79 static void i_set(int op
, int rd
);
80 static void i_neg(int rd
);
81 static void i_not(int rd
);
82 static void i_lnot(int rd
);
83 static void i_zx(int rd
, int bits
);
84 static void i_sx(int rd
, int bits
);
85 static void i_b(long addr
);
86 static void i_b_fill(long *dst
, int diff
);
87 static void i_b_if(long addr
, int rn
, int z
);
88 static void i_call(char *sym
, int off
);
89 static void i_call_reg(int rd
);
90 static void i_prolog(void);
91 static void i_epilog(void);
93 static struct tmp
*regs
[N_REGS
];
94 static int tmpregs
[] = {R_RAX
, R_RSI
, R_RDI
, R_RBX
, R_RDX
, R_RCX
};
96 #define MAXRET (1 << 8)
98 static long ret
[MAXRET
];
101 static void putint(char *s
, long n
, int l
)
109 static void os(void *s
, int n
)
112 cs
[cslen
++] = *(char *) (s
++);
115 static void oi(long n
, int l
)
123 static long sp_push(int size
)
131 static void tmp_mem(struct tmp
*tmp
)
134 if (tmp
->loc
!= LOC_REG
)
138 tmp
->addr
= -sp_push(LONGSZ
);
139 i_ldr(0, src
, REG_FP
, tmp
->addr
, LONGSZ
);
144 static void num_cast(struct tmp
*t
, unsigned bt
)
146 if (!(bt
& BT_SIGNED
) && BT_SZ(bt
) != LONGSZ
)
147 t
->addr
&= ((1l << (long) (BT_SZ(bt
) * 8)) - 1);
148 if (bt
& BT_SIGNED
&& BT_SZ(bt
) != LONGSZ
&&
149 t
->addr
> (1l << (BT_SZ(bt
) * 8 - 1)))
150 t
->addr
= -((1l << (BT_SZ(bt
) * 8)) - t
->addr
);
153 static void tmp_reg(struct tmp
*tmp
, int dst
, int deref
)
160 if (tmp
->loc
== LOC_NUM
) {
161 i_num(dst
, tmp
->addr
);
166 if (tmp
->loc
== LOC_SYM
) {
167 i_sym(dst
, tmp
->sym
, tmp
->off
);
172 if (tmp
->loc
== LOC_REG
) {
174 i_ldr(1, dst
, tmp
->addr
, 0, bt
);
175 else if (dst
!= tmp
->addr
)
176 i_mov(dst
, tmp
->addr
, LONGSZ
);
177 regs
[tmp
->addr
] = NULL
;
179 if (tmp
->loc
== LOC_LOCAL
) {
181 i_ldr(1, dst
, REG_FP
, tmp
->addr
+ tmp
->off
, bt
);
183 i_add_anyimm(dst
, REG_FP
, tmp
->addr
+ tmp
->off
);
185 if (tmp
->loc
== LOC_MEM
) {
186 i_ldr(1, dst
, REG_FP
, tmp
->addr
, LONGSZ
);
188 i_ldr(1, dst
, dst
, 0, bt
);
195 static void reg_free(int reg
)
200 for (i
= 0; i
< N_TMPS
; i
++)
201 if (!regs
[tmpregs
[i
]]) {
202 tmp_reg(regs
[reg
], tmpregs
[i
], 0);
208 static void reg_for(int reg
, struct tmp
*t
)
210 if (regs
[reg
] && regs
[reg
] != t
)
214 static void tmp_mv(struct tmp
*t
, int reg
)
220 static void tmp_to(struct tmp
*t
, int reg
)
226 static void tmp_drop(int n
)
229 for (i
= ntmp
- n
; i
< ntmp
; i
++)
230 if (tmps
[i
].loc
== LOC_REG
)
231 regs
[tmps
[i
].addr
] = NULL
;
235 static void tmp_pop(int reg
)
237 struct tmp
*t
= TMP(0);
242 static struct tmp
*tmp_new(void)
244 return &tmps
[ntmp
++];
247 static void tmp_push(int reg
)
249 struct tmp
*t
= tmp_new();
256 void o_local(long addr
)
258 struct tmp
*t
= tmp_new();
267 struct tmp
*t
= tmp_new();
273 void o_sym(char *name
)
275 struct tmp
*t
= tmp_new();
276 strcpy(t
->sym
, name
);
282 void o_tmpdrop(int n
)
284 if (n
== -1 || n
> ntmp
)
294 /* make sure tmps remain intact after a conditional expression */
298 for (i
= 0; i
< ntmp
- 1; i
++)
302 void o_forkpush(void)
307 void o_forkjoin(void)
314 struct tmp
*t1
= TMP(0);
315 struct tmp
*t2
= TMP(1);
317 memcpy(&t
, t1
, sizeof(t
));
318 memcpy(t1
, t2
, sizeof(t
));
319 memcpy(t2
, &t
, sizeof(t
));
320 if (t1
->loc
== LOC_REG
)
322 if (t2
->loc
== LOC_REG
)
326 static int reg_get(int mask
)
329 for (i
= 0; i
< N_TMPS
; i
++)
330 if ((1 << tmpregs
[i
]) & mask
&& !regs
[tmpregs
[i
]])
332 for (i
= 0; i
< N_TMPS
; i
++)
333 if ((1 << tmpregs
[i
]) & mask
) {
334 reg_free(tmpregs
[i
]);
340 static int reg_fortmp(struct tmp
*t
, int notmask
)
342 if (t
->loc
== LOC_REG
&& !(notmask
& (1 << t
->addr
)))
344 return reg_get(~notmask
);
347 static void tmp_copy(struct tmp
*t1
)
349 struct tmp
*t2
= tmp_new();
350 memcpy(t2
, t1
, sizeof(*t1
));
351 if (!(t1
->loc
& (LOC_REG
| LOC_MEM
)))
353 if (t1
->loc
== LOC_MEM
) {
354 tmp_mv(t2
, reg_get(~0));
355 } else if (t1
->loc
== LOC_REG
) {
356 t2
->addr
= reg_fortmp(t2
, 1 << t1
->addr
);
357 i_mov(t2
->addr
, t1
->addr
, LONGSZ
);
367 void o_cast(unsigned bt
)
369 struct tmp
*t
= TMP(0);
370 if (!t
->bt
&& t
->loc
== LOC_NUM
) {
374 if (BT_SZ(bt
) != LONGSZ
) {
375 int reg
= reg_fortmp(t
, BT_SZ(bt
) > 1 ? 0 : ~R_BYTEREGS
);
378 i_sx(reg
, BT_SZ(bt
) * 8);
380 i_zx(reg
, BT_SZ(bt
) * 8);
384 void o_func_beg(char *name
, int argc
, int global
, int vararg
)
386 out_sym(name
, (global
? OUT_GLOB
: 0) | OUT_CS
, cslen
, 0);
393 memset(regs
, 0, sizeof(regs
));
396 void o_deref(unsigned bt
)
398 struct tmp
*t
= TMP(0);
400 tmp_to(t
, reg_fortmp(t
, 0));
406 struct tmp
*t
= TMP(0);
407 tmp_to(t
, reg_fortmp(t
, 0));
410 #define TMP_NUM(t) ((t)->loc == LOC_NUM && !(t)->bt)
411 #define LOCAL_PTR(t) ((t)->loc == LOC_LOCAL && !(t)->bt)
412 #define SYM_PTR(t) ((t)->loc == LOC_SYM && !(t)->bt)
414 int o_popnum(long *c
)
416 struct tmp
*t
= TMP(0);
430 ret
[nret
++] = o_jmp(0);
433 void o_func_end(void)
436 for (i
= 0; i
< nret
; i
++)
441 long o_mklocal(int sz
)
443 return sp_push(ALIGN(sz
, LONGSZ
));
446 void o_rmlocal(long addr
, int sz
)
448 sp
= addr
- ALIGN(sz
, LONGSZ
);
451 long o_arg2loc(int i
)
453 return -LONGSZ
* (i
+ 2);
456 void o_assign(unsigned bt
)
458 struct tmp
*t1
= TMP(0);
459 struct tmp
*t2
= TMP(1);
460 int r1
= reg_fortmp(t1
, BT_SZ(bt
) > 1 ? 0 : ~R_BYTEREGS
);
461 int r2
= reg_fortmp(t2
, 1 << r1
);
466 if (t2
->loc
== LOC_LOCAL
) {
468 off
= t2
->addr
+ t2
->off
;
472 i_ldr(0, r1
, r2
, off
, bt
);
477 static long cu(int op
, long i
)
490 static int c_uop(int op
)
492 struct tmp
*t1
= TMP(0);
496 o_num(cu(op
, t1
->addr
));
500 static long cb(int op
, long a
, long b
)
525 return (unsigned long) a
>> b
;
542 static int c_bop(int op
)
544 struct tmp
*t1
= TMP(0);
545 struct tmp
*t2
= TMP(1);
546 int locs
= LOCAL_PTR(t1
) + LOCAL_PTR(t2
);
547 int syms
= SYM_PTR(t1
) + SYM_PTR(t2
);
548 int nums
= TMP_NUM(t1
) + TMP_NUM(t2
);
549 if (syms
+ locs
== 2 || syms
+ nums
+ locs
!= 2)
552 if ((op
& 0xff) != O_ADD
&& ((op
& 0xff) != O_SUB
|| TMP_NUM(t2
)))
555 long o1
= TMP_NUM(t1
) ? t1
->addr
: t1
->off
;
556 long o2
= TMP_NUM(t2
) ? t2
->addr
: t2
->off
;
557 long ret
= cb(op
, o2
, o1
);
563 long ret
= cb(op
, t2
->addr
, t1
->addr
);
572 int r1
= (op
& 0xff) == O_LNOT
? R_RAX
: reg_fortmp(TMP(0), 0);
589 static void bin_regs(int *r1
, int *r2
, int mask1
, int mask2
)
591 struct tmp
*t2
= TMP(0);
592 struct tmp
*t1
= TMP(1);
593 *r2
= reg_fortmp(t2
, ~mask1
);
595 *r1
= reg_fortmp(t1
, ~mask2
| (1 << *r2
));
600 static int bop_imm(int *r1
, long *n
, int swap
)
602 struct tmp
*t1
= TMP(0);
603 struct tmp
*t2
= TMP(1);
604 if (!TMP_NUM(t1
) && (!swap
|| !TMP_NUM(t2
)))
606 *n
= TMP_NUM(t1
) ? t1
->addr
: t2
->addr
;
607 if (!i_decodeable(*n
))
611 *r1
= reg_fortmp(t2
, 0);
617 static void bin_add(int op
)
621 if (!bop_imm(&r1
, &n
, (op
& 0xff) != O_SUB
)) {
622 i_add_imm(op
, r1
, r1
, n
);
624 bin_regs(&r1
, &r2
, R_TMPS
, R_TMPS
);
625 i_add(op
, r1
, r1
, r2
);
630 static void bin_shx(int op
)
634 if (!bop_imm(&r1
, &n
, 0)) {
635 i_shl_imm(op
, r1
, r1
, n
);
637 bin_regs(&r1
, &r2
, 1 << R_RCX
, R_TMPS
);
638 i_shl(op
, r1
, r1
, r2
);
643 static int log2a(unsigned long n
)
646 for (i
= 0; i
< LONGSZ
* 8; i
++)
649 if (i
== LONGSZ
* 8 || !(n
>> (i
+ 1)))
654 /* optimized version of mul/div/mod for powers of two */
655 static int mul_2(int op
)
657 struct tmp
*t1
= TMP(0);
658 struct tmp
*t2
= TMP(1);
662 if ((op
& 0xff) == O_MUL
&& t2
->loc
== LOC_NUM
&& !t2
->bt
)
664 if (t1
->loc
!= LOC_NUM
|| t1
->bt
)
670 if ((op
& 0xff) == O_MUL
) {
679 r2
= reg_fortmp(t2
, 0);
681 i_shl_imm(O_SHL
, r2
, r2
, p
);
688 r2
= reg_fortmp(t2
, 0);
690 i_shl_imm((op
& O_SIGNED
) | O_SHR
, r2
, r2
, p
);
700 r2
= reg_fortmp(t2
, 0);
708 static void mulop(int *r1
, int *r2
, int rop
)
710 struct tmp
*t1
= TMP(0);
711 struct tmp
*t2
= TMP(1);
712 if (t1
->loc
& LOC_REG
&& t1
->addr
!= R_RAX
&& t1
->addr
!= R_RDX
)
723 static void bin_mul(int op
)
728 mulop(&r1
, &r2
, (op
& 0xff) == O_MUL
? R_RDX
: R_RCX
);
729 if ((op
& 0xff) == O_MUL
) {
730 i_mul(R_RAX
, r1
, r2
);
733 if ((op
& 0xff) == O_DIV
) {
734 i_div(op
, R_RAX
, r1
, r2
);
737 if ((op
& 0xff) == O_MOD
) {
738 i_div(op
, R_RDX
, r1
, r2
);
743 static void bin_cmp(int op
)
747 if (!bop_imm(&r1
, &n
, (op
& 0xff) == O_EQ
|| (op
& 0xff) == O_NEQ
)) {
750 bin_regs(&r1
, &r2
, R_TMPS
, R_TMPS
);
763 if ((op
& 0xf0) == 0x00)
765 if ((op
& 0xf0) == 0x10)
767 if ((op
& 0xf0) == 0x20)
769 if ((op
& 0xf0) == 0x30)
775 struct tmp
*t0
= TMP(0);
776 struct tmp
*t1
= TMP(1);
777 struct tmp
*t2
= TMP(2);
781 os("\xfc\xf3\xa4", 3); /* cld; rep movs */
787 struct tmp
*t0
= TMP(0);
788 struct tmp
*t1
= TMP(1);
789 struct tmp
*t2
= TMP(2);
793 os("\xfc\xf3\xaa", 3); /* cld; rep stosb */
802 static long jxz(long addr
, int z
)
804 int r
= reg_fortmp(TMP(0), 0);
815 long o_jnz(long addr
)
820 long o_jmp(long addr
)
826 void o_filljmp2(long addr
, long jmpdst
)
828 i_b_fill((void *) cs
+ addr
, jmpdst
- addr
);
831 void o_filljmp(long addr
)
833 o_filljmp2(addr
, cslen
);
836 void o_call(int argc
, int rets
)
840 for (i
= 0; i
< N_TMPS
; i
++)
841 if (regs
[tmpregs
[i
]] && regs
[tmpregs
[i
]] - tmps
< ntmp
- argc
)
842 tmp_mem(regs
[tmpregs
[i
]]);
843 sp_push(LONGSZ
* argc
);
844 for (i
= argc
- 1; i
>= 0; --i
) {
845 int reg
= reg_fortmp(TMP(0), 0);
847 i_ldr(0, reg
, REG_SP
, i
* LONGSZ
, LONGSZ
);
850 if (t
->loc
== LOC_SYM
&& !t
->bt
) {
851 i_call(t
->sym
, t
->off
);
854 int reg
= reg_fortmp(t
, 0);
862 void o_mkbss(char *name
, int size
, int global
)
864 out_sym(name
, OUT_BSS
| (global
? OUT_GLOB
: 0), bsslen
, size
);
865 bsslen
+= ALIGN(size
, OUT_ALIGNMENT
);
868 #define MAXDATS (1 << 10)
869 static char dat_names
[MAXDATS
][NAMELEN
];
870 static int dat_offs
[MAXDATS
];
874 void *o_mkdat(char *name
, int size
, int global
)
876 void *addr
= ds
+ dslen
;
879 err("nomem: MAXDATS reached!\n");
880 strcpy(dat_names
[idx
], name
);
881 dat_offs
[idx
] = dslen
;
882 out_sym(name
, OUT_DS
| (global
? OUT_GLOB
: 0), dslen
, size
);
883 dslen
+= ALIGN(size
, OUT_ALIGNMENT
);
887 static int dat_off(char *name
)
890 for (i
= 0; i
< ndats
; i
++)
891 if (!strcmp(name
, dat_names
[i
]))
896 void o_datset(char *name
, int off
, unsigned bt
)
898 struct tmp
*t
= TMP(0);
899 int sym_off
= dat_off(name
) + off
;
900 if (t
->loc
== LOC_NUM
&& !t
->bt
) {
902 memcpy(ds
+ sym_off
, &t
->addr
, BT_SZ(bt
));
904 if (t
->loc
== LOC_SYM
&& !t
->bt
) {
905 out_rel(t
->sym
, OUT_DS
, sym_off
);
906 memcpy(ds
+ sym_off
, &t
->off
, BT_SZ(bt
));
913 out_write(fd
, cs
, cslen
, ds
, dslen
);
916 /* X86 arch specific functions */
935 #define OP2(o2, o1) (0x010000 | ((o2) << 8) | (o1))
936 #define O2(op) (((op) >> 8) & 0xff)
937 #define O1(op) ((op) & 0xff)
938 #define MODRM(m, r1, r2) ((m) << 6 | (r1) << 3 | (r2))
940 /* for optimizing cmp + jmp */
941 #define OPT_ISCMP() (last_set + 6 == cslen)
942 #define OPT_CCOND() (cs[last_set + 1])
944 static long last_set
= -1;
946 static void op_x(int op
, int r1
, int r2
, int bt
)
953 oi(sz
== 1 ? O1(op
) & ~0x1 : O1(op
), 1);
958 /* op_*(): r=reg, m=mem, i=imm, s=sym */
959 static void op_rm(int op
, int src
, int base
, int off
, int bt
)
961 int dis
= off
== (char) off
? 1 : 4;
962 int mod
= dis
== 4 ? 2 : 1;
963 if (!off
&& (base
& 7) != R_RBP
)
965 op_x(op
, src
, base
, bt
);
966 oi(MODRM(mod
, src
& 0x07, base
& 0x07), 1);
967 if ((base
& 7) == R_RSP
)
973 static void op_rr(int op
, int src
, int dst
, int bt
)
975 op_x(op
, src
, dst
, bt
);
976 oi(MODRM(3, src
& 0x07, dst
& 0x07), 1);
979 #define movrx_bt(bt) (LONGSZ)
981 static int movrx_op(int bt
, int mov
)
985 return OP2(0x0f, bt
& BT_SIGNED
? 0xbf : 0xb7);
987 return OP2(0x0f, bt
& BT_SIGNED
? 0xbe : 0xb6);
991 static void mov_r2r(int r1
, int r2
, unsigned bt
)
993 if (r1
!= r2
|| BT_SZ(bt
) != LONGSZ
)
994 op_rr(movrx_op(bt
, I_MOV
), r1
, r2
, movrx_bt(bt
));
997 static void mov_m2r(int dst
, int base
, int off
, int bt
)
999 op_rm(movrx_op(bt
, I_MOVR
), dst
, base
, off
, movrx_bt(bt
));
1002 static void i_zx(int rd
, int bits
)
1005 i_shl_imm(O_SHL
, rd
, rd
, LONGSZ
* 8 - bits
);
1006 i_shl_imm(O_SHR
, rd
, rd
, LONGSZ
* 8 - bits
);
1008 mov_r2r(rd
, rd
, bits
>> 3);
1012 static void i_sx(int rd
, int bits
)
1014 mov_r2r(rd
, rd
, BT_SIGNED
| (bits
>> 3));
1017 static void i_add(int op
, int rd
, int rn
, int rm
)
1019 /* opcode for O_ADD, O_SUB, O_AND, O_OR, O_XOR */
1020 static int rx
[] = {0003, 0053, 0043, 0013, 0063};
1022 die("this is cisc!\n");
1023 op_rr(rx
[op
& 0x0f], rd
, rm
, LONGSZ
);
1026 static void i_add_imm(int op
, int rd
, int rn
, long n
)
1028 /* opcode for O_ADD, O_SUB, O_AND, O_OR, O_XOR */
1029 static int rx
[] = {0xc0, 0xe8, 0xe0, 0xc8, 0xf0};
1030 unsigned char s
[3] = {0x83, rx
[op
& 0x0f] | rd
, n
& 0xff};
1032 die("this is cisc!\n");
1036 static int i_decodeable(long imm
)
1038 return imm
<= 127 && imm
>= -128;
1041 static void i_num(int rd
, long n
)
1044 op_rr(I_XOR
, rd
, rd
, 4);
1046 op_x(I_MOVIR
+ (rd
& 7), 0, rd
, LONGSZ
);
1051 static void i_add_anyimm(int rd
, int rn
, long n
)
1053 op_rm(I_LEA
, rd
, rn
, n
, LONGSZ
);
1056 static void i_mul(int rd
, int rn
, int rm
)
1060 op_rr(I_MUL
, 4, rn
, LONGSZ
);
1063 static void i_div(int op
, int rd
, int rn
, int rm
)
1067 op_x(I_CQO
, R_RAX
, R_RDX
, LONGSZ
);
1071 op_rr(I_MUL
, op
& O_SIGNED
? 7 : 6, rn
, LONGSZ
);
1074 static void i_tst(int rn
, int rm
)
1076 op_rr(I_TST
, rn
, rm
, LONGSZ
);
1079 static void i_cmp(int rn
, int rm
)
1081 op_rr(I_CMP
, rn
, rm
, LONGSZ
);
1084 static void i_cmp_imm(int rn
, long n
)
1086 unsigned char s
[3] = {0x83, 0xf8 | rn
, n
& 0xff};
1090 static void i_set(int op
, int rd
)
1092 /* lt, gt, le, ge, eq, neq */
1093 static int ucond
[] = {0x92, 0x97, 0x96, 0x93, 0x94, 0x95};
1094 static int scond
[] = {0x9c, 0x9f, 0x9e, 0x9d, 0x94, 0x95};
1095 int cond
= op
& O_SIGNED
? scond
[op
& 0x0f] : ucond
[op
& 0x0f];
1096 char set
[] = "\x0f\x00\xc0";
1098 die("set works only with R_RAX\n");
1101 os(set
, 3); /* setl al */
1102 os("\x0f\xb6\xc0", 3); /* movzbl eax, al */
1105 static void i_shl(int op
, int rd
, int rm
, int rs
)
1108 if ((op
& 0x0f) == 1)
1109 sm
= op
& O_SIGNED
? 7 : 5;
1111 die("this is cisc!\n");
1112 op_rr(I_SHX
, sm
, rd
, LONGSZ
);
1115 static void i_shl_imm(int op
, int rd
, int rn
, long n
)
1117 int sm
= (op
& 0x1) ? (op
& O_SIGNED
? 0xf8 : 0xe8) : 0xe0 ;
1118 char s
[3] = {0xc1, sm
| rn
, n
& 0xff};
1120 die("this is cisc!\n");
1124 static void i_mov(int rd
, int rn
, int bt
)
1126 op_rr(movrx_op(bt
, I_MOVR
), rd
, rn
, movrx_bt(bt
));
1129 static void i_ldr(int l
, int rd
, int rn
, int off
, int bt
)
1132 mov_m2r(rd
, rn
, off
, bt
);
1134 op_rm(I_MOV
, rd
, rn
, off
, bt
);
1137 static void i_sym(int rd
, char *sym
, int off
)
1139 op_x(I_MOVIR
+ (rd
& 7), 0, rd
, LONGSZ
);
1140 out_rel(sym
, OUT_CS
, cslen
);
1144 static void i_neg(int rd
)
1146 op_rr(I_NOT
, 3, rd
, LONGSZ
);
1149 static void i_not(int rd
)
1151 op_rr(I_NOT
, 2, rd
, LONGSZ
);
1154 static void i_lnot(int rd
)
1157 cs
[last_set
+ 1] ^= 0x01;
1159 char cmp
[] = "\x83\xf8\x00";
1161 os(cmp
, 3); /* cmp eax, 0 */
1166 static void jx(int x
, long addr
)
1168 char op
[2] = {0x0f};
1170 os(op
, 2); /* jx $addr */
1171 oi(addr
- cslen
- 4, 4);
1174 static void i_b_if(long addr
, int rn
, int z
)
1177 int cond
= OPT_CCOND();
1179 jx((!z
? cond
: cond
^ 0x01) & ~0x10, addr
);
1183 jx(z
? 0x84 : 0x85, addr
);
1187 static void i_b(long addr
)
1189 os("\xe9", 1); /* jmp $addr */
1190 oi(addr
- cslen
- 4, 4);
1193 static void i_b_fill(long *dst
, int diff
)
1195 putint((void *) dst
, diff
- 4, 4);
1198 static void i_call_reg(int rd
)
1200 op_rr(I_CALL
, 2, rd
, LONGSZ
);
1203 static void i_call(char *sym
, int off
)
1205 os("\xe8", 1); /* call $x */
1206 out_rel(sym
, OUT_CS
| OUT_REL
, cslen
);
1210 static void i_prolog(void)
1213 os("\x55", 1); /* push rbp */
1214 os("\x89\xe5", 2); /* mov rbp, rsp */
1215 os("\x53\x56\x57", 3); /* push rbx; push rsi; push rdi */
1216 os("\x81\xec", 2); /* sub rsp, $xxx */
1221 static void i_epilog(void)
1223 int diff
= ALIGN(sp_max
- 3 * LONGSZ
, LONGSZ
);
1225 os("\x81\xc4", 2); /* add $xxx, %esp */
1227 putint(cs
+ func_fpsub
, diff
, 4);
1229 os("\x5f\x5e\x5b", 3); /* pop edi; pop esi; pop ebx */
1230 os("\xc9\xc3", 2); /* leave; ret; */