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))
43 static char cs
[SECSIZE
]; /* code segment */
45 static char ds
[SECSIZE
]; /* data segment */
47 static long bsslen
; /* bss segment size */
49 static long sp
; /* stack pointer offset from R_RBP */
50 static long sp_max
; /* maximum stack pointer offset */
51 static long sp_tmp
; /* sp for the first tmp on the stack */
52 static long func_fpsub
; /* stack pointer sub address in CS */
54 #define TMP(i) (((i) < ntmp) ? &tmps[ntmp - 1 - (i)] : NULL)
59 long off
; /* offset from a symbol or a local */
60 unsigned loc
; /* variable location */
61 unsigned bt
; /* type of address; zero when not a pointer */
65 /* arch-specific functions */
66 static void i_ldr(int l
, int rd
, int rn
, int off
, int bt
);
67 static void i_mov(int rd
, int rn
, int bt
);
68 static void i_add(int op
, int rd
, int rn
, int rm
);
69 static void i_shl(int op
, int rd
, int rm
, int rs
);
70 static void i_mul(int rd
, int rn
, int rm
);
71 static void i_div(int op
, int rd
, int rn
, int rm
);
72 static void i_cmp(int rn
, int rm
);
73 static int i_decodeable(long imm
);
74 static void i_add_imm(int op
, int rd
, int rn
, long n
);
75 static void i_shl_imm(int op
, int rd
, int rn
, long n
);
76 static void i_cmp_imm(int rn
, long n
);
77 static void i_add_anyimm(int rd
, int rn
, long n
);
78 static void i_num(int rd
, long n
);
79 static void i_sym(int rd
, char *sym
, int off
);
80 static void i_set(int op
, int rd
);
81 static void i_neg(int rd
);
82 static void i_not(int rd
);
83 static void i_lnot(int rd
);
84 static void i_zx(int rd
, int bits
);
85 static void i_sx(int rd
, int bits
);
86 static void i_b(void);
87 static void i_bz(int rn
, int z
);
88 static void i_b_fill(long src
, long dst
);
89 static void i_call(char *sym
, int off
);
90 static void i_call_reg(int rd
);
91 static void i_prolog(void);
92 static void i_epilog(void);
94 static struct tmp
*regs
[N_REGS
];
95 static int tmpregs
[] = {R_RAX
, R_RSI
, R_RDI
, R_RBX
, R_RDX
, R_RCX
};
98 #define MAXJMPS (1 << 14)
100 static long labels
[MAXJMPS
];
102 static long jmp_loc
[MAXJMPS
];
103 static int jmp_goal
[MAXJMPS
];
113 static void jmp_add(int id
)
115 if (njmps
>= MAXJMPS
)
116 err("nomem: MAXJMPS reached!\n");
117 jmp_loc
[njmps
] = cslen
- 4;
118 jmp_goal
[njmps
] = id
;
122 static void jmp_fill(void)
125 for (i
= 0; i
< njmps
; i
++)
126 i_b_fill(jmp_loc
[i
], labels
[jmp_goal
[i
]]);
129 /* generating code */
131 static void putint(char *s
, long n
, int l
)
139 static void os(void *s
, int n
)
142 cs
[cslen
++] = *(char *) (s
++);
145 static void oi(long n
, int l
)
153 static long sp_push(int size
)
161 static void tmp_mem(struct tmp
*tmp
)
164 if (tmp
->loc
!= LOC_REG
)
168 tmp
->addr
= -sp_push(LONGSZ
);
169 i_ldr(0, src
, REG_FP
, tmp
->addr
, LONGSZ
);
174 static void num_cast(struct tmp
*t
, unsigned bt
)
176 if (!(bt
& BT_SIGNED
) && BT_SZ(bt
) != LONGSZ
)
177 t
->addr
&= ((1l << (long) (BT_SZ(bt
) * 8)) - 1);
178 if (bt
& BT_SIGNED
&& BT_SZ(bt
) != LONGSZ
&&
179 t
->addr
> (1l << (BT_SZ(bt
) * 8 - 1)))
180 t
->addr
= -((1l << (BT_SZ(bt
) * 8)) - t
->addr
);
183 static void tmp_reg(struct tmp
*tmp
, int dst
, int deref
)
190 if (tmp
->loc
== LOC_NUM
) {
191 i_num(dst
, tmp
->addr
);
196 if (tmp
->loc
== LOC_SYM
) {
197 i_sym(dst
, tmp
->sym
, tmp
->off
);
202 if (tmp
->loc
== LOC_REG
) {
204 i_ldr(1, dst
, tmp
->addr
, 0, bt
);
205 else if (dst
!= tmp
->addr
)
206 i_mov(dst
, tmp
->addr
, LONGSZ
);
207 regs
[tmp
->addr
] = NULL
;
209 if (tmp
->loc
== LOC_LOCAL
) {
211 i_ldr(1, dst
, REG_FP
, tmp
->addr
+ tmp
->off
, bt
);
213 i_add_anyimm(dst
, REG_FP
, tmp
->addr
+ tmp
->off
);
215 if (tmp
->loc
== LOC_MEM
) {
216 i_ldr(1, dst
, REG_FP
, tmp
->addr
, LONGSZ
);
218 i_ldr(1, dst
, dst
, 0, bt
);
225 static void reg_free(int reg
)
230 for (i
= 0; i
< N_TMPS
; i
++)
231 if (!regs
[tmpregs
[i
]]) {
232 tmp_reg(regs
[reg
], tmpregs
[i
], 0);
238 static void reg_for(int reg
, struct tmp
*t
)
240 if (regs
[reg
] && regs
[reg
] != t
)
244 static void tmp_mv(struct tmp
*t
, int reg
)
250 static void tmp_to(struct tmp
*t
, int reg
)
256 static void tmp_drop(int n
)
259 for (i
= ntmp
- n
; i
< ntmp
; i
++)
260 if (tmps
[i
].loc
== LOC_REG
)
261 regs
[tmps
[i
].addr
] = NULL
;
265 static void tmp_pop(int reg
)
267 struct tmp
*t
= TMP(0);
272 static struct tmp
*tmp_new(void)
274 return &tmps
[ntmp
++];
277 static void tmp_push(int reg
)
279 struct tmp
*t
= tmp_new();
286 void o_local(long addr
)
288 struct tmp
*t
= tmp_new();
297 struct tmp
*t
= tmp_new();
303 void o_sym(char *name
)
305 struct tmp
*t
= tmp_new();
306 strcpy(t
->sym
, name
);
312 void o_tmpdrop(int n
)
314 if (n
== -1 || n
> ntmp
)
324 /* make sure tmps remain intact after a conditional expression */
328 for (i
= 0; i
< ntmp
- 1; i
++)
332 void o_forkpush(void)
337 void o_forkjoin(void)
344 struct tmp
*t1
= TMP(0);
345 struct tmp
*t2
= TMP(1);
347 memcpy(&t
, t1
, sizeof(t
));
348 memcpy(t1
, t2
, sizeof(t
));
349 memcpy(t2
, &t
, sizeof(t
));
350 if (t1
->loc
== LOC_REG
)
352 if (t2
->loc
== LOC_REG
)
356 static int reg_get(int mask
)
359 for (i
= 0; i
< N_TMPS
; i
++)
360 if ((1 << tmpregs
[i
]) & mask
&& !regs
[tmpregs
[i
]])
362 for (i
= 0; i
< N_TMPS
; i
++)
363 if ((1 << tmpregs
[i
]) & mask
) {
364 reg_free(tmpregs
[i
]);
370 static int reg_fortmp(struct tmp
*t
, int notmask
)
372 if (t
->loc
== LOC_REG
&& !(notmask
& (1 << t
->addr
)))
374 return reg_get(~notmask
);
377 static void tmp_copy(struct tmp
*t1
)
379 struct tmp
*t2
= tmp_new();
380 memcpy(t2
, t1
, sizeof(*t1
));
381 if (!(t1
->loc
& (LOC_REG
| LOC_MEM
)))
383 if (t1
->loc
== LOC_MEM
) {
384 tmp_mv(t2
, reg_get(~0));
385 } else if (t1
->loc
== LOC_REG
) {
386 t2
->addr
= reg_fortmp(t2
, 1 << t1
->addr
);
387 i_mov(t2
->addr
, t1
->addr
, LONGSZ
);
397 void o_cast(unsigned bt
)
399 struct tmp
*t
= TMP(0);
400 if (!t
->bt
&& t
->loc
== LOC_NUM
) {
404 if (BT_SZ(bt
) != LONGSZ
) {
405 int reg
= reg_fortmp(t
, BT_SZ(bt
) > 1 ? 0 : ~R_BYTEREGS
);
408 i_sx(reg
, BT_SZ(bt
) * 8);
410 i_zx(reg
, BT_SZ(bt
) * 8);
414 void o_func_beg(char *name
, int argc
, int global
, int vararg
)
416 out_sym(name
, (global
? OUT_GLOB
: 0) | OUT_CS
, cslen
, 0);
424 memset(regs
, 0, sizeof(regs
));
427 void o_deref(unsigned bt
)
429 struct tmp
*t
= TMP(0);
431 tmp_to(t
, reg_fortmp(t
, 0));
437 struct tmp
*t
= TMP(0);
438 tmp_to(t
, reg_fortmp(t
, 0));
441 #define TMP_NUM(t) ((t)->loc == LOC_NUM && !(t)->bt)
442 #define LOCAL_PTR(t) ((t)->loc == LOC_LOCAL && !(t)->bt)
443 #define SYM_PTR(t) ((t)->loc == LOC_SYM && !(t)->bt)
445 int o_popnum(long *c
)
447 struct tmp
*t
= TMP(0);
464 void o_func_end(void)
471 long o_mklocal(int sz
)
473 return sp_push(ALIGN(sz
, LONGSZ
));
476 void o_rmlocal(long addr
, int sz
)
478 sp
= addr
- ALIGN(sz
, LONGSZ
);
481 long o_arg2loc(int i
)
483 return -LONGSZ
* (i
+ 2);
486 void o_assign(unsigned bt
)
488 struct tmp
*t1
= TMP(0);
489 struct tmp
*t2
= TMP(1);
490 int r1
= reg_fortmp(t1
, BT_SZ(bt
) > 1 ? 0 : ~R_BYTEREGS
);
491 int r2
= reg_fortmp(t2
, 1 << r1
);
496 if (t2
->loc
== LOC_LOCAL
) {
498 off
= t2
->addr
+ t2
->off
;
502 i_ldr(0, r1
, r2
, off
, bt
);
507 static long cu(int op
, long i
)
520 static int c_uop(int op
)
522 struct tmp
*t1
= TMP(0);
526 o_num(cu(op
, t1
->addr
));
530 static long cb(int op
, long a
, long b
)
555 return (unsigned long) a
>> b
;
572 static int c_bop(int op
)
574 struct tmp
*t1
= TMP(0);
575 struct tmp
*t2
= TMP(1);
576 int locs
= LOCAL_PTR(t1
) + LOCAL_PTR(t2
);
577 int syms
= SYM_PTR(t1
) + SYM_PTR(t2
);
578 int nums
= TMP_NUM(t1
) + TMP_NUM(t2
);
579 if (syms
+ locs
== 2 || syms
+ nums
+ locs
!= 2)
582 if ((op
& 0xff) != O_ADD
&& ((op
& 0xff) != O_SUB
|| TMP_NUM(t2
)))
585 long o1
= TMP_NUM(t1
) ? t1
->addr
: t1
->off
;
586 long o2
= TMP_NUM(t2
) ? t2
->addr
: t2
->off
;
587 long ret
= cb(op
, o2
, o1
);
593 long ret
= cb(op
, t2
->addr
, t1
->addr
);
602 int r1
= (op
& 0xff) == O_LNOT
? R_RAX
: reg_fortmp(TMP(0), 0);
619 static void bin_regs(int *r1
, int *r2
, int mask1
, int mask2
)
621 struct tmp
*t2
= TMP(0);
622 struct tmp
*t1
= TMP(1);
623 *r2
= reg_fortmp(t2
, ~mask1
);
625 *r1
= reg_fortmp(t1
, ~mask2
| (1 << *r2
));
630 static int bop_imm(int *r1
, long *n
, int swap
)
632 struct tmp
*t1
= TMP(0);
633 struct tmp
*t2
= TMP(1);
634 if (!TMP_NUM(t1
) && (!swap
|| !TMP_NUM(t2
)))
636 *n
= TMP_NUM(t1
) ? t1
->addr
: t2
->addr
;
637 if (!i_decodeable(*n
))
641 *r1
= reg_fortmp(t2
, 0);
647 static void bin_add(int op
)
651 if (!bop_imm(&r1
, &n
, (op
& 0xff) != O_SUB
)) {
652 i_add_imm(op
, r1
, r1
, n
);
654 bin_regs(&r1
, &r2
, R_TMPS
, R_TMPS
);
655 i_add(op
, r1
, r1
, r2
);
660 static void bin_shx(int op
)
664 if (!bop_imm(&r1
, &n
, 0)) {
665 i_shl_imm(op
, r1
, r1
, n
);
667 bin_regs(&r1
, &r2
, 1 << R_RCX
, R_TMPS
);
668 i_shl(op
, r1
, r1
, r2
);
673 static int log2a(unsigned long n
)
676 for (i
= 0; i
< LONGSZ
* 8; i
++)
679 if (i
== LONGSZ
* 8 || !(n
>> (i
+ 1)))
684 /* optimized version of mul/div/mod for powers of two */
685 static int mul_2(int op
)
687 struct tmp
*t1
= TMP(0);
688 struct tmp
*t2
= TMP(1);
692 if ((op
& 0xff) == O_MUL
&& t2
->loc
== LOC_NUM
&& !t2
->bt
)
694 if (t1
->loc
!= LOC_NUM
|| t1
->bt
)
700 if ((op
& 0xff) == O_MUL
) {
709 r2
= reg_fortmp(t2
, 0);
711 i_shl_imm(O_SHL
, r2
, r2
, p
);
718 r2
= reg_fortmp(t2
, 0);
720 i_shl_imm((op
& O_SIGNED
) | O_SHR
, r2
, r2
, p
);
730 r2
= reg_fortmp(t2
, 0);
738 static void mulop(int *r1
, int *r2
, int rop
)
740 struct tmp
*t1
= TMP(0);
741 struct tmp
*t2
= TMP(1);
742 if (t1
->loc
& LOC_REG
&& t1
->addr
!= R_RAX
&& t1
->addr
!= R_RDX
)
753 static void bin_mul(int op
)
758 mulop(&r1
, &r2
, (op
& 0xff) == O_MUL
? R_RDX
: R_RCX
);
759 if ((op
& 0xff) == O_MUL
) {
760 i_mul(R_RAX
, r1
, r2
);
763 if ((op
& 0xff) == O_DIV
) {
764 i_div(op
, R_RAX
, r1
, r2
);
767 if ((op
& 0xff) == O_MOD
) {
768 i_div(op
, R_RDX
, r1
, r2
);
773 static void bin_cmp(int op
)
777 if (!bop_imm(&r1
, &n
, (op
& 0xff) == O_EQ
|| (op
& 0xff) == O_NEQ
)) {
780 bin_regs(&r1
, &r2
, R_TMPS
, R_TMPS
);
793 if ((op
& 0xf0) == 0x00)
795 if ((op
& 0xf0) == 0x10)
797 if ((op
& 0xf0) == 0x20)
799 if ((op
& 0xf0) == 0x30)
805 struct tmp
*t0
= TMP(0);
806 struct tmp
*t1
= TMP(1);
807 struct tmp
*t2
= TMP(2);
811 os("\xfc\xf3\xa4", 3); /* cld; rep movs */
817 struct tmp
*t0
= TMP(0);
818 struct tmp
*t1
= TMP(1);
819 struct tmp
*t2
= TMP(2);
823 os("\xfc\xf3\xaa", 3); /* cld; rep stosb */
827 static void jxz(int id
, int z
)
829 int r
= reg_fortmp(TMP(0), 0);
851 void o_call(int argc
, int rets
)
855 for (i
= 0; i
< N_TMPS
; i
++)
856 if (regs
[tmpregs
[i
]] && regs
[tmpregs
[i
]] - tmps
< ntmp
- argc
)
857 tmp_mem(regs
[tmpregs
[i
]]);
858 sp_push(LONGSZ
* argc
);
859 for (i
= argc
- 1; i
>= 0; --i
) {
860 int reg
= reg_fortmp(TMP(0), 0);
862 i_ldr(0, reg
, REG_SP
, i
* LONGSZ
, LONGSZ
);
865 if (t
->loc
== LOC_SYM
&& !t
->bt
) {
866 i_call(t
->sym
, t
->off
);
869 int reg
= reg_fortmp(t
, 0);
877 void o_mkbss(char *name
, int size
, int global
)
879 out_sym(name
, OUT_BSS
| (global
? OUT_GLOB
: 0), bsslen
, size
);
880 bsslen
+= ALIGN(size
, OUT_ALIGNMENT
);
883 #define MAXDATS (1 << 10)
884 static char dat_names
[MAXDATS
][NAMELEN
];
885 static int dat_offs
[MAXDATS
];
888 void *o_mkdat(char *name
, int size
, int global
)
890 void *addr
= ds
+ dslen
;
893 err("nomem: MAXDATS reached!\n");
894 strcpy(dat_names
[idx
], name
);
895 dat_offs
[idx
] = dslen
;
896 out_sym(name
, OUT_DS
| (global
? OUT_GLOB
: 0), dslen
, size
);
897 dslen
+= ALIGN(size
, OUT_ALIGNMENT
);
901 static int dat_off(char *name
)
904 for (i
= 0; i
< ndats
; i
++)
905 if (!strcmp(name
, dat_names
[i
]))
910 void o_datset(char *name
, int off
, unsigned bt
)
912 struct tmp
*t
= TMP(0);
913 int sym_off
= dat_off(name
) + off
;
914 if (t
->loc
== LOC_NUM
&& !t
->bt
) {
916 memcpy(ds
+ sym_off
, &t
->addr
, BT_SZ(bt
));
918 if (t
->loc
== LOC_SYM
&& !t
->bt
) {
919 out_rel(t
->sym
, OUT_DS
, sym_off
);
920 memcpy(ds
+ sym_off
, &t
->off
, BT_SZ(bt
));
927 out_write(fd
, cs
, cslen
, ds
, dslen
);
930 /* X86 arch specific functions */
949 #define OP2(o2, o1) (0x010000 | ((o2) << 8) | (o1))
950 #define O2(op) (((op) >> 8) & 0xff)
951 #define O1(op) ((op) & 0xff)
952 #define MODRM(m, r1, r2) ((m) << 6 | (r1) << 3 | (r2))
954 /* for optimizing cmp + jmp */
955 #define OPT_ISCMP() (last_set + 6 == cslen)
956 #define OPT_CCOND() (cs[last_set + 1])
958 static long last_set
= -1;
960 static void op_x(int op
, int r1
, int r2
, int bt
)
967 oi(sz
== 1 ? O1(op
) & ~0x1 : O1(op
), 1);
972 /* op_*(): r=reg, m=mem, i=imm, s=sym */
973 static void op_rm(int op
, int src
, int base
, int off
, int bt
)
975 int dis
= off
== (char) off
? 1 : 4;
976 int mod
= dis
== 4 ? 2 : 1;
977 if (!off
&& (base
& 7) != R_RBP
)
979 op_x(op
, src
, base
, bt
);
980 oi(MODRM(mod
, src
& 0x07, base
& 0x07), 1);
981 if ((base
& 7) == R_RSP
)
987 static void op_rr(int op
, int src
, int dst
, int bt
)
989 op_x(op
, src
, dst
, bt
);
990 oi(MODRM(3, src
& 0x07, dst
& 0x07), 1);
993 #define movrx_bt(bt) (LONGSZ)
995 static int movrx_op(int bt
, int mov
)
999 return OP2(0x0f, bt
& BT_SIGNED
? 0xbf : 0xb7);
1001 return OP2(0x0f, bt
& BT_SIGNED
? 0xbe : 0xb6);
1005 static void mov_r2r(int r1
, int r2
, unsigned bt
)
1007 if (r1
!= r2
|| BT_SZ(bt
) != LONGSZ
)
1008 op_rr(movrx_op(bt
, I_MOV
), r1
, r2
, movrx_bt(bt
));
1011 static void mov_m2r(int dst
, int base
, int off
, int bt
)
1013 op_rm(movrx_op(bt
, I_MOVR
), dst
, base
, off
, movrx_bt(bt
));
1016 static void i_zx(int rd
, int bits
)
1019 i_shl_imm(O_SHL
, rd
, rd
, LONGSZ
* 8 - bits
);
1020 i_shl_imm(O_SHR
, rd
, rd
, LONGSZ
* 8 - bits
);
1022 mov_r2r(rd
, rd
, bits
>> 3);
1026 static void i_sx(int rd
, int bits
)
1028 mov_r2r(rd
, rd
, BT_SIGNED
| (bits
>> 3));
1031 static void i_add(int op
, int rd
, int rn
, int rm
)
1033 /* opcode for O_ADD, O_SUB, O_AND, O_OR, O_XOR */
1034 static int rx
[] = {0003, 0053, 0043, 0013, 0063};
1036 die("this is cisc!\n");
1037 op_rr(rx
[op
& 0x0f], rd
, rm
, LONGSZ
);
1040 static void i_add_imm(int op
, int rd
, int rn
, long n
)
1042 /* opcode for O_ADD, O_SUB, O_AND, O_OR, O_XOR */
1043 static int rx
[] = {0xc0, 0xe8, 0xe0, 0xc8, 0xf0};
1044 unsigned char s
[3] = {0x83, rx
[op
& 0x0f] | rd
, n
& 0xff};
1046 die("this is cisc!\n");
1050 static int i_decodeable(long imm
)
1052 return imm
<= 127 && imm
>= -128;
1055 static void i_num(int rd
, long n
)
1058 op_rr(I_XOR
, rd
, rd
, 4);
1060 op_x(I_MOVIR
+ (rd
& 7), 0, rd
, LONGSZ
);
1065 static void i_add_anyimm(int rd
, int rn
, long n
)
1067 op_rm(I_LEA
, rd
, rn
, n
, LONGSZ
);
1070 static void i_mul(int rd
, int rn
, int rm
)
1074 op_rr(I_MUL
, 4, rn
, LONGSZ
);
1077 static void i_div(int op
, int rd
, int rn
, int rm
)
1081 op_x(I_CQO
, R_RAX
, R_RDX
, LONGSZ
);
1085 op_rr(I_MUL
, op
& O_SIGNED
? 7 : 6, rn
, LONGSZ
);
1088 static void i_tst(int rn
, int rm
)
1090 op_rr(I_TST
, rn
, rm
, LONGSZ
);
1093 static void i_cmp(int rn
, int rm
)
1095 op_rr(I_CMP
, rn
, rm
, LONGSZ
);
1098 static void i_cmp_imm(int rn
, long n
)
1100 unsigned char s
[3] = {0x83, 0xf8 | rn
, n
& 0xff};
1104 static void i_set(int op
, int rd
)
1106 /* lt, gt, le, ge, eq, neq */
1107 static int ucond
[] = {0x92, 0x97, 0x96, 0x93, 0x94, 0x95};
1108 static int scond
[] = {0x9c, 0x9f, 0x9e, 0x9d, 0x94, 0x95};
1109 int cond
= op
& O_SIGNED
? scond
[op
& 0x0f] : ucond
[op
& 0x0f];
1110 char set
[] = "\x0f\x00\xc0";
1112 die("set works only with R_RAX\n");
1115 os(set
, 3); /* setl al */
1116 os("\x0f\xb6\xc0", 3); /* movzbl eax, al */
1119 static void i_shl(int op
, int rd
, int rm
, int rs
)
1122 if ((op
& 0x0f) == 1)
1123 sm
= op
& O_SIGNED
? 7 : 5;
1125 die("this is cisc!\n");
1126 op_rr(I_SHX
, sm
, rd
, LONGSZ
);
1129 static void i_shl_imm(int op
, int rd
, int rn
, long n
)
1131 int sm
= (op
& 0x1) ? (op
& O_SIGNED
? 0xf8 : 0xe8) : 0xe0 ;
1132 char s
[3] = {0xc1, sm
| rn
, n
& 0xff};
1134 die("this is cisc!\n");
1138 static void i_mov(int rd
, int rn
, int bt
)
1140 op_rr(movrx_op(bt
, I_MOVR
), rd
, rn
, movrx_bt(bt
));
1143 static void i_ldr(int l
, int rd
, int rn
, int off
, int bt
)
1146 mov_m2r(rd
, rn
, off
, bt
);
1148 op_rm(I_MOV
, rd
, rn
, off
, bt
);
1151 static void i_sym(int rd
, char *sym
, int off
)
1153 op_x(I_MOVIR
+ (rd
& 7), 0, rd
, LONGSZ
);
1154 out_rel(sym
, OUT_CS
, cslen
);
1158 static void i_neg(int rd
)
1160 op_rr(I_NOT
, 3, rd
, LONGSZ
);
1163 static void i_not(int rd
)
1165 op_rr(I_NOT
, 2, rd
, LONGSZ
);
1168 static void i_lnot(int rd
)
1171 cs
[last_set
+ 1] ^= 0x01;
1173 char cmp
[] = "\x83\xf8\x00";
1175 os(cmp
, 3); /* cmp eax, 0 */
1180 static void jx(int x
, long addr
)
1182 char op
[2] = {0x0f};
1184 os(op
, 2); /* jx $addr */
1185 oi(addr
- cslen
- 4, 4);
1188 static void i_bz(int rn
, int z
)
1191 int cond
= OPT_CCOND();
1193 jx((!z
? cond
: cond
^ 0x01) & ~0x10, 0);
1197 jx(z
? 0x84 : 0x85, 0);
1201 static void i_b(void)
1203 os("\xe9", 1); /* jmp $addr */
1207 static void i_b_fill(long src
, long dst
)
1209 putint((void *) (cs
+ src
), (dst
- src
) - 4, 4);
1212 static void i_call_reg(int rd
)
1214 op_rr(I_CALL
, 2, rd
, LONGSZ
);
1217 static void i_call(char *sym
, int off
)
1219 os("\xe8", 1); /* call $x */
1220 out_rel(sym
, OUT_CS
| OUT_REL
, cslen
);
1224 static void i_prolog(void)
1227 os("\x55", 1); /* push rbp */
1228 os("\x89\xe5", 2); /* mov rbp, rsp */
1229 os("\x53\x56\x57", 3); /* push rbx; push rsi; push rdi */
1230 os("\x81\xec", 2); /* sub rsp, $xxx */
1235 static void i_epilog(void)
1237 int diff
= ALIGN(sp_max
- 3 * LONGSZ
, LONGSZ
);
1239 os("\x81\xc4", 2); /* add $xxx, %esp */
1241 putint(cs
+ func_fpsub
, diff
, 4);
1243 os("\x5f\x5e\x5b", 3); /* pop edi; pop esi; pop ebx */
1244 os("\xc9\xc3", 2); /* leave; ret; */