6 #define TMP_ADDR 0x0001
10 #define LOC_SYM 0x0800
11 #define LOC_LOCAL 0x1000
12 #define LOC_MASK 0xff00
50 #define MIN(a, b) ((a) < (b) ? (a) : (b))
52 #define R_BYTEMASK (1 << R_RAX | 1 << R_RDX | 1 << R_RCX)
53 #define TMP_BT(t) ((t)->flags & TMP_ADDR ? 8 : (t)->bt)
54 #define TMP_REG(t) ((t)->flags & LOC_REG ? (t)->addr : reg_get(~0))
55 #define TMP_REG2(t, r) ((t)->flags & LOC_REG && (t)->addr != r ? \
56 (t)->addr : reg_get(~(1 << r)))
57 #define TMP_BYTEREG(t) ((t)->flags & LOC_REG && \
58 (1 << (t)->addr) & R_BYTEMASK ? \
59 (t)->addr : reg_get(R_BYTEMASK))
60 #define BT_TMPBT(bt) (BT_SZ(bt) >= 4 ? (bt) : (bt) & BT_SIGNED | 4)
62 static char buf
[SECSIZE
];
66 static long spsub_addr
;
69 #define TMP(i) (&tmps[ntmp - 1 - (i)])
73 long off
; /* used for LOC_SYM; offset from a symbol address */
81 static struct tmp
*regs
[NREGS
];
82 static int tmpregs
[] = {R_RAX
, R_RDI
, R_RSI
, R_RDX
, R_RCX
, R_R8
, R_R9
};
84 #define MAXRET (1 << 8)
86 static long ret
[MAXRET
];
92 static void putint(char *s
, long n
, int l
)
100 static void os(char *s
, int n
)
108 static void oi(long n
, int l
)
118 static long codeaddr(void)
123 static void o_op(int *op
, int nop
, int r1
, int r2
, unsigned bt
)
133 if (rex
|| (bt
& BT_SZMASK
) == 8)
135 if ((bt
& BT_SZMASK
) == 2)
137 if ((bt
& BT_SZMASK
) == 1)
139 for (i
= 0; i
< nop
; i
++)
143 static void memop(int *op
, int nop
, int src
, int base
, int off
, unsigned bt
)
145 int dis
= off
== (char) off
? 1 : 4;
146 int mod
= dis
== 4 ? 2 : 1;
147 o_op(op
, nop
, src
, base
, bt
);
150 oi((mod
<< 6) | ((src
& 0x07) << 3) | (base
& 0x07), 1);
155 static void memop1(int op
, int src
, int base
, int off
, unsigned bt
)
157 memop(&op
, 1, src
, base
, off
, bt
);
160 static void regop(int *op
, int nop
, int src
, int dst
, unsigned bt
)
162 o_op(op
, nop
, src
, dst
, bt
);
163 oi((3 << 6) | (src
<< 3) | (dst
& 0x07), 1);
166 static void regop1(int op
, int src
, int dst
, unsigned bt
)
168 regop(&op
, 1, src
, dst
, bt
);
171 static long sp_push(int size
)
179 #define LOC_NEW(f, l) (((f) & ~LOC_MASK) | (l))
181 static void tmp_mem(struct tmp
*tmp
)
184 if (!(tmp
->flags
& LOC_REG
))
188 tmp
->addr
= -sp_push(8);
189 memop1(MOV_R2X
, src
, R_RBP
, tmp
->addr
, BT_TMPBT(TMP_BT(tmp
)));
191 tmp
->flags
= LOC_NEW(tmp
->flags
, LOC_MEM
);
194 static int *movxx_x2r(int bt
)
196 static int movxx
[2] = {0x0f};
198 movxx
[1] = bt
& BT_SIGNED
? 0xbe : 0xb6;
200 movxx
[1] = bt
& BT_SIGNED
? 0xbf : 0xb7;
206 static void mov_r2r(int r1
, int r2
, unsigned bt1
, unsigned bt2
)
208 int s1
= bt1
& BT_SIGNED
;
209 int s2
= bt2
& BT_SIGNED
;
210 int sz1
= BT_SZ(bt1
);
211 int sz2
= BT_SZ(bt2
);
212 if (sz2
< 4 && (sz1
> sz2
|| s1
!= s2
)) {
213 regop(movxx_x2r(bt2
), 2, r1
, r2
, 4);
216 if (sz1
== 4 && sz2
== 8) {
218 regop1(MOVSXD
, r2
, r1
, sz2
);
221 if (r1
!= r2
|| sz1
> sz2
)
222 regop1(MOV_R2X
, r1
, r2
, BT_TMPBT(bt2
));
225 static void mov_m2r(int dst
, int base
, int off
, int bt1
, int bt2
)
227 if (BT_SZ(bt1
) < 4) {
228 memop(movxx_x2r(bt1
), 2, dst
, base
, off
,
229 bt1
& BT_SIGNED
&& BT_SZ(bt2
) == 8 ? 8 : 4);
230 mov_r2r(dst
, dst
, bt1
, bt2
);
232 memop1(MOV_M2R
, dst
, base
, off
, bt1
);
233 mov_r2r(dst
, dst
, bt1
, bt2
);
237 static void num_cast(struct tmp
*t
, unsigned bt
)
239 if (!(bt
& BT_SIGNED
) && BT_SZ(bt
) != 8)
240 t
->addr
&= ((1l << (long) (BT_SZ(bt
) * 8)) - 1);
241 if (bt
& BT_SIGNED
&& BT_SZ(bt
) != 8 &&
242 t
->addr
> (1l << (BT_SZ(bt
) * 8 - 1)))
243 t
->addr
= -((1l << (BT_SZ(bt
) * 8)) - t
->addr
);
247 static void num_reg(int reg
, unsigned bt
, long num
)
249 int op
= MOV_I2R
+ (reg
& 7);
250 if (BT_SZ(bt
) == 8 && num
>= 0 && num
== (unsigned) num
)
252 o_op(&op
, 1, 0, reg
, bt
);
256 static void tmp_reg(struct tmp
*tmp
, int dst
, unsigned bt
, int deref
)
258 if (deref
&& tmp
->flags
& TMP_ADDR
)
259 tmp
->flags
&= ~TMP_ADDR
;
262 if (tmp
->flags
& LOC_NUM
) {
264 tmp
->bt
= BT_TMPBT(bt
);
265 num_reg(dst
, tmp
->bt
, tmp
->addr
);
268 tmp
->flags
= LOC_NEW(tmp
->flags
, LOC_REG
);
270 if (tmp
->flags
& LOC_SYM
) {
271 regop1(MOV_I2X
, 0, dst
, 4);
273 out_rela(tmp
->addr
, codeaddr(), 0);
277 tmp
->flags
= LOC_NEW(tmp
->flags
, LOC_REG
);
279 if (tmp
->flags
& LOC_REG
) {
281 mov_m2r(dst
, tmp
->addr
, 0, tmp
->bt
, bt
);
283 mov_r2r(tmp
->addr
, dst
, TMP_BT(tmp
),
284 tmp
->flags
& TMP_ADDR
? 8 : bt
);
285 regs
[tmp
->addr
] = NULL
;
287 if (tmp
->flags
& LOC_LOCAL
) {
289 mov_m2r(dst
, R_RBP
, tmp
->addr
, tmp
->bt
, bt
);
291 memop1(LEA_M2R
, dst
, R_RBP
, tmp
->addr
, 8);
293 if (tmp
->flags
& LOC_MEM
) {
294 int nbt
= deref
? 8 : TMP_BT(tmp
);
295 mov_m2r(dst
, R_RBP
, tmp
->addr
, nbt
, nbt
);
297 mov_m2r(dst
, dst
, 0, tmp
->bt
, bt
);
300 tmp
->bt
= tmp
->flags
& TMP_ADDR
? bt
: BT_TMPBT(bt
);
302 tmp
->flags
= LOC_NEW(tmp
->flags
, LOC_REG
);
305 static void reg_free(int reg
)
310 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
311 if (!regs
[tmpregs
[i
]]) {
312 tmp_reg(regs
[reg
], tmpregs
[i
], regs
[reg
]->bt
, 0);
318 static void reg_for(int reg
, struct tmp
*t
)
320 if (regs
[reg
] && regs
[reg
] != t
)
324 static void tmp_mv(struct tmp
*t
, int reg
)
327 tmp_reg(t
, reg
, t
->bt
, 0);
330 static void tmp_to(struct tmp
*t
, int reg
, int bt
)
333 tmp_reg(t
, reg
, bt
? bt
: t
->bt
, 1);
336 static void tmp_drop(int n
)
339 for (i
= ntmp
- n
; i
< ntmp
; i
++)
340 if (tmps
[i
].flags
& LOC_REG
)
341 regs
[tmps
[i
].addr
] = NULL
;
346 static int tmp_pop(int reg
, int bt
)
348 struct tmp
*t
= TMP(0);
354 static struct tmp
*tmp_new(void)
357 return &tmps
[ntmp
++];
360 static void tmp_push(int reg
, unsigned bt
)
362 struct tmp
*t
= tmp_new();
369 void o_local(long addr
, unsigned bt
)
371 struct tmp
*t
= tmp_new();
374 t
->flags
= LOC_LOCAL
| TMP_ADDR
;
377 void o_num(long num
, unsigned bt
)
379 struct tmp
*t
= tmp_new();
385 void o_symaddr(long addr
, unsigned bt
)
387 struct tmp
*t
= tmp_new();
390 t
->flags
= LOC_SYM
| TMP_ADDR
;
394 void o_tmpdrop(int n
)
397 if (n
== -1 || n
> ntmp
)
407 #define FORK_REG R_RAX
409 /* make sure tmps remain intact after a conditional expression */
413 for (i
= 0; i
< ntmp
- 1; i
++)
417 void o_forkpush(void)
422 void o_forkjoin(void)
424 tmp_push(FORK_REG
, 0);
429 struct tmp
*t1
= TMP(0);
430 struct tmp
*t2
= TMP(1);
432 memcpy(&t
, t1
, sizeof(t
));
433 memcpy(t1
, t2
, sizeof(t
));
434 memcpy(t2
, &t
, sizeof(t
));
435 if (t1
->flags
& LOC_REG
)
437 if (t2
->flags
& LOC_REG
)
441 static int reg_get(int mask
)
444 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
445 if ((1 << tmpregs
[i
]) & mask
&& !regs
[tmpregs
[i
]])
447 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
448 if ((1 << tmpregs
[i
]) & mask
) {
449 reg_free(tmpregs
[i
]);
457 struct tmp
*t1
= TMP(0);
458 struct tmp
*t2
= tmp_new();
459 memcpy(t2
, t1
, sizeof(*t1
));
460 if (!(t1
->flags
& (LOC_REG
| LOC_MEM
)))
462 if (t1
->flags
& LOC_MEM
) {
463 tmp_reg(t2
, reg_get(~0), t2
->bt
, 0);
464 } else if (t1
->flags
& LOC_REG
) {
465 t2
->addr
= reg_get(~(1 << t1
->addr
));
466 regop1(MOV_R2X
, t1
->addr
, t2
->addr
, BT_TMPBT(TMP_BT(t1
)));
469 t2
->flags
= t1
->flags
;
472 void o_cast(unsigned bt
)
474 struct tmp
*t
= TMP(0);
478 if (t
->flags
& LOC_NUM
) {
482 reg
= BT_SZ(bt
) == 1 ? TMP_BYTEREG(t
) : TMP_REG(t
);
486 long o_func_beg(char *name
, int global
)
488 long addr
= out_func_beg(name
, global
);
490 os("\x55", 1); /* push %rbp */
491 os("\x48\x89\xe5", 3); /* mov %rsp, %rbp */
498 memset(regs
, 0, sizeof(regs
));
499 os("\x48\x81\xec", 3); /* sub $xxx, %rsp */
500 spsub_addr
= codeaddr();
505 void o_deref(unsigned bt
)
507 struct tmp
*t
= TMP(0);
508 if (t
->flags
& TMP_ADDR
)
509 tmp_to(t
, TMP_REG(t
), t
->bt
);
511 t
->flags
|= TMP_ADDR
;
516 struct tmp
*t
= TMP(0);
517 tmp_to(t
, TMP_REG(t
), t
->bt
);
520 static unsigned bt_op(unsigned bt1
, unsigned bt2
)
522 unsigned s1
= BT_SZ(bt1
);
523 unsigned s2
= BT_SZ(bt2
);
524 unsigned bt
= (bt1
| bt2
) & BT_SIGNED
| (s1
> s2
? s1
: s2
);
528 #define TMP_CONST(t) ((t)->flags & LOC_NUM && !((t)->flags & TMP_ADDR))
529 #define LOCAL_PTR(t) ((t)->flags & LOC_LOCAL && !((t)->flags & TMP_ADDR))
530 #define SYM_PTR(t) ((t)->flags & LOC_SYM && !((t)->flags & TMP_ADDR))
532 int o_popnum(long *c
)
534 struct tmp
*t
= TMP(0);
542 static int c_binop(long (*cop
)(long a
, long b
, unsigned bt
), unsigned bt
)
544 struct tmp
*t1
= TMP(0);
545 struct tmp
*t2
= TMP(1);
546 int locals
= LOCAL_PTR(t1
) + LOCAL_PTR(t2
);
547 int syms
= SYM_PTR(t1
) + SYM_PTR(t2
);
548 int nums
= TMP_CONST(t1
) + TMP_CONST(t2
);
549 if (syms
== 2 || syms
&& locals
|| syms
+ nums
+ locals
!= 2)
553 bt
= syms
? 8 : bt_op(t1
->bt
, t2
->bt
);
560 long o1
= SYM_PTR(t1
) ? t1
->off
: t1
->addr
;
561 long o2
= SYM_PTR(t2
) ? t2
->off
: t2
->addr
;
562 long ret
= cop(o2
, o1
, bt
);
568 long ret
= cop(t2
->addr
, t1
->addr
, locals
? 4 | BT_SIGNED
: bt
);
580 static int c_op(long (*cop
)(long a
, unsigned bt
), unsigned bt
)
582 struct tmp
*t1
= TMP(0);
588 ret
= cop(t1
->addr
, bt
);
594 static void shx(int uop
, int sop
)
596 struct tmp
*t2
= TMP(1);
597 int r2
= TMP_REG2(t2
, R_RCX
);
601 regop1(SHX_REG
, bt
& BT_SIGNED
? sop
: uop
, r2
, BT_TMPBT(bt
));
605 static long c_shl(long a
, long b
, unsigned bt
)
612 if (!c_binop(c_shl
, 0))
617 static long c_shr(long a
, long b
, unsigned bt
)
622 return (unsigned long) a
>> b
;
627 if (!c_binop(c_shr
, 0))
632 static int mulop(int uop
, int sop
, int reg
)
634 struct tmp
*t1
= TMP(0);
635 struct tmp
*t2
= TMP(1);
636 int bt1
= TMP_BT(t1
);
637 int bt2
= TMP_BT(t2
);
638 int bt
= bt_op(bt1
, bt2
);
639 if (t1
->flags
& LOC_REG
&& t1
->addr
!= R_RAX
&& t1
->addr
!= R_RDX
)
642 tmp_to(t2
, R_RAX
, bt
);
647 o_op(&cqo
, 1, R_RAX
, R_RDX
, bt
);
649 regop1(XOR_R2X
, R_RDX
, R_RDX
, bt
);
652 regop1(MUL_A2X
, bt
& BT_SIGNED
? sop
: uop
, reg
, BT_TMPBT(bt2
));
656 static long c_mul(long a
, long b
, unsigned bt
)
664 if (!c_binop(c_mul
, 0))
666 bt
= mulop(4, 5, R_RDX
);
670 static long c_div(long a
, long b
, unsigned bt
)
678 if (!c_binop(c_div
, 0))
680 bt
= mulop(6, 7, R_RCX
);
684 static long c_mod(long a
, long b
, unsigned bt
)
692 if (!c_binop(c_mod
, 0))
694 bt
= mulop(6, 7, R_RCX
);
700 tmps
[ntmp
- 1].flags
&= ~TMP_ADDR
;
701 tmps
[ntmp
- 1].bt
= 8;
704 void o_ret(unsigned bt
)
709 os("\x31\xc0", 2); /* xor %eax, %eax */
710 ret
[nret
++] = o_jmp(0);
713 static int binop(int op
, int *reg
)
715 struct tmp
*t1
= TMP(0);
716 struct tmp
*t2
= TMP(1);
718 unsigned bt
= bt_op(t1
->bt
, t2
->bt
);
720 r2
= TMP_REG2(t2
, r1
);
723 regop1(op
, r2
, r1
, bt
);
728 static long c_add(long a
, long b
, unsigned bt
)
737 if (!c_binop(c_add
, 0))
739 bt
= binop(ADD_R2X
, ®
);
743 static long c_xor(long a
, long b
, unsigned bt
)
752 if (!c_binop(c_xor
, 0))
754 bt
= binop(XOR_R2X
, ®
);
758 static long c_and(long a
, long b
, unsigned bt
)
767 if (!c_binop(c_and
, 0))
769 bt
= binop(AND_R2X
, ®
);
773 static long c_or(long a
, long b
, unsigned bt
)
782 if (!c_binop(c_or
, 0))
784 bt
= binop(OR_R2X
, ®
);
788 static long c_sub(long a
, long b
, unsigned bt
)
797 if (!c_binop(c_sub
, 0))
799 bt
= binop(SUB_R2X
, ®
);
803 static void o_cmp(int uop
, int sop
)
805 struct tmp
*t1
= TMP(0);
806 struct tmp
*t2
= TMP(1);
807 char set
[] = "\x0f\x00\xc0";
810 if (regs
[R_RAX
] && regs
[R_RAX
] != t1
&& regs
[R_RAX
] != t2
)
812 bt
= binop(CMP_R2X
, ®
);
813 set
[1] = bt
& BT_SIGNED
? sop
: uop
;
814 cmp_setl
= codeaddr();
815 os(set
, 3); /* setl %al */
816 os("\x0f\xb6\xc0", 3); /* movzbl %al, %eax */
817 tmp_push(R_RAX
, 4 | BT_SIGNED
);
818 cmp_last
= codeaddr();
821 static long c_lt(long a
, long b
, unsigned bt
)
828 if (!c_binop(c_lt
, 4))
833 static long c_gt(long a
, long b
, unsigned bt
)
840 if (!c_binop(c_gt
, 4))
845 static long c_le(long a
, long b
, unsigned bt
)
852 if (!c_binop(c_le
, 4))
857 static long c_ge(long a
, long b
, unsigned bt
)
864 if (!c_binop(c_ge
, 4))
869 static long c_eq(long a
, long b
, unsigned bt
)
876 if (!c_binop(c_eq
, 4))
881 static long c_neq(long a
, long b
, unsigned bt
)
888 if (!c_binop(c_neq
, 4))
893 static long c_lnot(long a
, unsigned bt
)
900 if (!c_op(c_lnot
, 4))
902 if (cmp_last
== codeaddr()) {
903 buf
[cmp_setl
+ 1] ^= 0x01;
905 o_num(0, 4 | BT_SIGNED
);
910 static long c_neg(long a
, unsigned bt
)
917 struct tmp
*t
= TMP(0);
919 unsigned bt
= BT_TMPBT(t
->bt
);
920 if (!c_op(c_neg
, t
->bt
| BT_SIGNED
))
924 regop1(NEG_REG
, 3, reg
, bt
);
927 static long c_not(long a
, unsigned bt
)
934 struct tmp
*t
= TMP(0);
936 unsigned bt
= BT_TMPBT(t
->bt
);
941 regop1(NOT_REG
, 2, reg
, bt
);
944 void o_func_end(void)
947 for (i
= 0; i
< nret
; i
++)
949 os("\xc9\xc3", 2); /* leave; ret; */
950 putint(buf
+ spsub_addr
, (maxsp
+ 7) & ~0x07, 4);
951 out_func_end(buf
, cur
- buf
);
954 long o_mklocal(int size
)
956 return sp_push((size
+ 7) & ~0x07);
959 void o_rmlocal(long addr
, int sz
)
964 static int arg_regs
[] = {R_RDI
, R_RSI
, R_RDX
, R_RCX
, R_R8
, R_R9
};
966 #define R_NARGS ARRAY_SIZE(arg_regs)
968 long o_arg(int i
, unsigned bt
)
972 addr
= o_mklocal(BT_SZ(bt
));
973 memop1(MOV_R2X
, arg_regs
[i
], R_RBP
, -addr
, bt
);
975 addr
= -8 * (i
- R_NARGS
+ 2);
980 void o_assign(unsigned bt
)
982 struct tmp
*t1
= TMP(0);
983 struct tmp
*t2
= TMP(1);
984 int r1
= BT_SZ(bt
) > 1 ? TMP_REG(t1
) : TMP_BYTEREG(t1
);
987 tmp_to(t1
, r1
, BT_TMPBT(bt
));
988 if (t2
->flags
& LOC_LOCAL
) {
992 reg
= TMP_REG2(t2
, r1
);
997 memop1(MOV_R2X
, r1
, reg
, off
, bt
);
1001 void o_memcpy(int sz
)
1003 struct tmp
*t0
= TMP(-1);
1004 struct tmp
*t1
= TMP(0);
1005 struct tmp
*t2
= TMP(1);
1007 tmp_to(t0
, R_RCX
, 0);
1010 os("\xf3\xa4", 2); /* rep movs */
1014 void o_memset(int x
, int sz
)
1016 struct tmp
*t0
= TMP(-2);
1017 struct tmp
*t1
= TMP(-1);
1018 struct tmp
*t2
= TMP(0);
1021 tmp_to(t0
, R_RAX
, 0);
1022 tmp_to(t1
, R_RCX
, 0);
1024 os("\xf3\xaa", 2); /* rep stosb */
1028 long o_mklabel(void)
1033 static long jx(int x
, long addr
)
1035 char op
[2] = {0x0f};
1037 os(op
, 2); /* jx $addr */
1038 oi(addr
- codeaddr() - 4, 4);
1039 return codeaddr() - 4;
1042 static long jxtest(int x
, long addr
)
1044 int bt
= tmp_pop(R_RAX
, 0);
1045 regop1(TEST_R2R
, R_RAX
, R_RAX
, bt
);
1049 static long jxcmp(long addr
, int inv
)
1052 if (codeaddr() != cmp_last
)
1055 cur
= buf
+ cmp_setl
;
1056 x
= (unsigned char) buf
[cmp_setl
+ 1];
1057 return jx((inv
? x
: x
^ 0x01) & ~0x10, addr
);
1060 long o_jz(long addr
)
1062 long ret
= jxcmp(addr
, 0);
1063 return ret
!= -1 ? ret
: jxtest(0x84, addr
);
1066 long o_jnz(long addr
)
1068 long ret
= jxcmp(addr
, 1);
1069 return ret
!= -1 ? ret
: jxtest(0x85, addr
);
1072 long o_jmp(long addr
)
1074 os("\xe9", 1); /* jmp $addr */
1075 oi(addr
- codeaddr() - 4, 4);
1076 return codeaddr() - 4;
1079 void o_filljmp2(long addr
, long jmpdst
)
1081 putint(buf
+ addr
, jmpdst
- addr
- 4, 4);
1084 void o_filljmp(long addr
)
1086 o_filljmp2(addr
, codeaddr());
1089 void o_call(int argc
, unsigned *bt
, unsigned ret_bt
)
1093 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
1094 if (regs
[tmpregs
[i
]] && regs
[tmpregs
[i
]] - tmps
< ntmp
- argc
)
1095 tmp_mem(regs
[tmpregs
[i
]]);
1096 if (argc
> R_NARGS
) {
1097 long addr
= sp_push(8 * (argc
- R_NARGS
));
1098 for (i
= argc
- 1; i
>= R_NARGS
; --i
) {
1099 int reg
= TMP_REG(TMP(0));
1100 tmp_pop(reg
, bt
[i
]);
1101 memop1(MOV_R2X
, reg
, R_RBP
,
1102 -(addr
- (i
- R_NARGS
) * 8), BT_TMPBT(bt
[i
]));
1105 for (i
= MIN(argc
, R_NARGS
) - 1; i
>= 0; i
--)
1106 tmp_pop(arg_regs
[i
], bt
[i
]);
1108 if (t
->flags
& LOC_SYM
) {
1109 os("\x31\xc0", 2); /* xor %eax, %eax */
1110 os("\xe8", 1); /* call $x */
1112 out_rela(t
->addr
, codeaddr(), 1);
1116 tmp_mv(TMP(0), R_RAX
);
1118 regop1(CALL_REG
, 2, R_RAX
, 4);
1121 tmp_push(R_RAX
, ret_bt
);
1134 void o_datset(long addr
, int off
, unsigned bt
)
1136 struct tmp
*t
= TMP(0);
1137 if (t
->flags
& LOC_NUM
&& !(t
->flags
& TMP_ADDR
)) {
1139 out_datcpy(addr
, off
, (void *) &t
->addr
, BT_SZ(bt
));
1141 if (t
->flags
& LOC_SYM
&& !(t
->flags
& TMP_ADDR
)) {
1142 out_datrela(t
->addr
, addr
, off
);
1143 out_datcpy(addr
, off
, (void *) &t
->off
, BT_SZ(bt
));