12 #define LOC_LOCAL 0x10
16 #define REG_PC 15 /* program counter */
17 #define REG_LR 14 /* link register */
18 #define REG_SP 13 /* stack pointer */
19 #define REG_TMP 12 /* temporary register */
20 #define REG_FP 11 /* frame pointer register */
21 #define REG_DP 10 /* data pointer register */
22 #define REG_RET 0 /* returned value register */
24 #define MIN(a, b) ((a) < (b) ? (a) : (b))
25 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
27 #define TMP_REG(t) ((t)->loc == LOC_REG ? (t)->addr : reg_get(~0))
28 #define TMP_REG2(t, r) ((t)->loc == LOC_REG && (t)->addr != (r) ? \
29 (t)->addr : reg_get(~(1 << (r))))
30 #define TMP_REG3(t, r1, r2) ((t)->loc == LOC_REG && (t)->addr != (r1) && (t)->addr != (r2) ? \
31 (t)->addr : reg_get(~((1 << (r1)) | (1 << (r2)))))
33 static char cs
[SECSIZE
]; /* code segment */
35 static char ds
[SECSIZE
]; /* data segment */
37 static long bsslen
; /* bss segment size */
44 #define TMP(i) (&tmps[ntmp - 1 - (i)])
49 long off
; /* offset from a symbol or a local */
50 unsigned loc
; /* variable location */
51 unsigned bt
; /* type of address; zero when not a pointer */
57 static struct tmp
*regs
[NREGS
];
58 static int tmpregs
[] = {4, 5, 6, 7, 8, 9, 0, 1, 2, 3};
59 static int argregs
[] = {0, 1, 2, 3};
72 #define MAXRET (1 << 8)
74 static long ret
[MAXRET
];
77 /* for optimizing cmp + bcc */
78 static long last_cmp
= -1;
79 static long last_set
= -1;
80 static long last_cond
;
82 static void oi(long n
)
86 *(int *) (cs
+ cslen
) = n
;
93 static long num_offs
[NDATS
]; /* data immediate value */
94 static char num_names
[NDATS
][NAMELEN
]; /* relocation data symbol name */
97 static int pool_num(long num
)
101 num_names
[idx
][0] = '\0';
105 static int pool_reloc(char *name
, long off
)
109 strcpy(num_names
[idx
], name
);
113 static void pool_write(void)
116 for (i
= 0; i
< ndats
; i
++) {
118 out_rel(num_names
[i
], OUT_CS
, cslen
);
125 * +---------------------------------------+
126 * |COND|00|I| op |S| Rn | Rd | operand2 |
127 * +---------------------------------------+
129 * S: set condition code
131 * Rd: destination operand
133 * I=0 operand2=| shift | Rm |
134 * I=1 operand2=|rota| imm |
136 #define ADD(op, rd, rn, s, i, cond) \
137 (((cond) << 28) | ((i) << 25) | ((s) << 20) | \
138 ((op) << 21) | ((rn) << 16) | ((rd) << 12))
140 static void i_add(int op
, int rd
, int rn
, int rm
)
142 oi(ADD(op
, rd
, rn
, 0, 0, 14) | rm
);
145 static int add_encimm(unsigned n
)
148 while (i
< 12 && (n
>> ((4 + i
) << 1)))
150 return (n
>> (i
<< 1)) | (((16 - i
) & 0x0f) << 8);
153 static int add_decimm(unsigned n
)
155 int rot
= (16 - ((n
>> 8) & 0x0f)) & 0x0f;
156 return (n
& 0xff) << (rot
<< 1);
159 static int add_rndimm(unsigned n
)
161 int rot
= (n
>> 8) & 0x0f;
167 rot
= (rot
+ 12) & 0x0f;
169 return ((num
+ 1) & 0xff) | (rot
<< 8);
172 static void i_ldr(int l
, int rd
, int rn
, int off
, int bt
);
174 static void i_num(int rd
, long n
)
177 int p
= neg
? -n
- 1 : n
;
178 int enc
= add_encimm(p
);
179 if (p
== add_decimm(enc
)) {
180 oi(ADD(neg
? I_MVN
: I_MOV
, rd
, 0, 0, 1, 14) | enc
);
183 int off
= pool_num(n
);
184 i_ldr(1, rd
, REG_DP
, off
, LONGSZ
);
189 static void i_add_imm(int op
, int rd
, int rn
, int n
)
192 int imm
= add_encimm(neg
? -n
: n
);
193 if (imm
== add_decimm(neg
? -n
: n
)) {
194 oi(ADD(neg
? I_SUB
: I_ADD
, rd
, rn
, 0, 1, 14) | imm
);
197 i_add(I_ADD
, rd
, rd
, rn
);
203 * +----------------------------------------+
204 * |COND|000000|A|S| Rd | Rn | Rs |1001| Rm |
205 * +----------------------------------------+
209 * C: set condition codes
211 * I=0 operand2=| shift | Rm |
212 * I=1 operand2=|rota| imm |
214 #define MUL(rd, rn, rs) \
215 ((14 << 28) | ((rd) << 16) | ((0) << 12) | ((rn) << 8) | ((9) << 4) | (rm))
217 static void i_mul(int rd
, int rn
, int rm
)
222 static void i_cmp(int op
, int rn
, int rm
)
224 oi(ADD(op
, 0, rn
, 1, 0, 14) | rm
);
228 static void i_set(int cond
, int rd
)
232 oi(ADD(I_MOV
, rd
, 0, 0, 1, 14));
233 oi(ADD(I_MOV
, rd
, 0, 0, 1, cond
) | 1);
240 static void i_shl(int sm
, int rd
, int rm
, int rs
)
242 oi(ADD(I_MOV
, rd
, 0, 0, 0, 14) | (rs
<< 8) | (sm
<< 5) | (1 << 4) | rm
);
245 static void i_shl_imm(int sm
, int rd
, int n
)
247 oi(ADD(I_MOV
, rd
, 0, 0, 0, 14) | (n
<< 7) | (sm
<< 5) | rd
);
250 static void i_mov(int op
, int rd
, int rn
)
252 oi(ADD(op
, rd
, 0, 0, 0, 14) | rn
);
256 * single data transfer:
257 * +------------------------------------------+
258 * |COND|01|I|P|U|B|W|L| Rn | Rd | offset |
259 * +------------------------------------------+
261 * I: immediate/offset
262 * P: post/pre indexing
268 * Rd: source/destination register
270 * I=0 offset=| immediate |
271 * I=1 offset=| shift | Rm |
273 * halfword and signed data transfer
274 * +----------------------------------------------+
275 * |COND|000|P|U|0|W|L| Rn | Rd |0000|1|S|H|1| Rm |
276 * +----------------------------------------------+
278 * +----------------------------------------------+
279 * |COND|000|P|U|1|W|L| Rn | Rd |off1|1|S|H|1|off2|
280 * +----------------------------------------------+
285 #define LDR(l, rd, rn, b, u, p, w) \
286 ((14 << 28) | (1 << 26) | ((p) << 24) | ((b) << 22) | ((u) << 23) | \
287 ((w) << 21) | ((l) << 20) | ((rn) << 16) | ((rd) << 12))
288 #define LDRH(l, rd, rn, s, h, u, i) \
289 ((14 << 28) | (1 << 24) | ((u) << 23) | ((i) << 22) | ((l) << 20) | \
290 ((rn) << 16) | ((rd) << 12) | ((s) << 6) | ((h) << 5) | (9 << 4))
292 static void i_ldr(int l
, int rd
, int rn
, int off
, int bt
)
294 int b
= BT_SZ(bt
) == 1;
295 int h
= BT_SZ(bt
) == 2;
296 int s
= l
&& (bt
& BT_SIGNED
);
297 int half
= h
|| (b
&& s
);
298 int maximm
= half
? 0x100 : 0x1000;
302 while (off
>= maximm
) {
303 int imm
= add_encimm(off
);
304 oi(ADD(neg
? I_SUB
: I_ADD
, rd
, rn
, 0, 1, 14) | imm
);
306 off
-= add_decimm(imm
);
309 oi(LDR(l
, rd
, rn
, b
, !neg
, 1, 0) | off
);
311 oi(LDRH(l
, rd
, rn
, s
, h
, !neg
, 1) |
312 ((off
& 0xf0) << 4) | (off
& 0x0f));
315 static void i_sym(int rd
, char *sym
, int off
)
318 int doff
= pool_reloc(sym
, off
);
319 i_ldr(1, rd
, REG_DP
, doff
, LONGSZ
);
323 static void i_neg(int rd
)
325 oi(ADD(I_RSB
, rd
, rd
, 0, 1, 14));
328 static void i_not(int rd
)
330 oi(ADD(I_MVN
, rd
, 0, rd
, 1, 14));
333 static void i_lnot(int rd
)
335 i_cmp(I_TST
, rd
, rd
);
336 oi(ADD(I_MOV
, rd
, 0, 0, 1, 14));
337 oi(ADD(I_MOV
, rd
, 0, 0, 1, 0) | 1);
340 /* rd = rd & ((1 << bits) - 1) */
341 static void i_zx(int rd
, int bits
)
344 oi(ADD(I_AND
, rd
, rd
, 0, 1, 14) | add_encimm((1 << bits
) - 1));
346 i_shl_imm(SM_LSL
, rd
, 32 - bits
);
347 i_shl_imm(SM_LSR
, rd
, 32 - bits
);
351 static void i_sx(int rd
, int bits
)
353 i_shl_imm(SM_LSL
, rd
, 32 - bits
);
354 i_shl_imm(SM_ASR
, rd
, 32 - bits
);
359 * +-----------------------------------+
360 * |COND|101|L| offset |
361 * +-----------------------------------+
365 #define BL(cond, l, o) (((cond) << 28) | (5 << 25) | ((l) << 24) | \
366 ((((o) - 8) >> 2) & 0x00ffffff))
368 static void i_b(long addr
)
370 oi(BL(14, 0, addr
- cslen
));
373 static void i_b_if(long addr
, int rn
, int z
)
375 static int nots
[] = {1, 0, -1, -1, -1, -1, -1, -1, -1, -1, 11, 10, 13, 12, -1};
376 if (last_cmp
+ 8 != cslen
|| last_set
!= last_cmp
) {
377 i_cmp(I_TST
, rn
, rn
);
378 oi(BL(z
? 0 : 1, 0, addr
- cslen
));
382 oi(BL(z
? nots
[last_cond
] : last_cond
, 0, addr
- cslen
));
385 static void i_b_fill(long *dst
, int diff
)
387 *dst
= (*dst
& 0xff000000) | (((diff
- 8) >> 2) & 0x00ffffff);
390 static void i_memcpy(int rd
, int rs
, int rn
)
392 oi(ADD(I_TST
, 0, rn
, 1, 0, 14) | rn
);
394 oi(LDR(1, REG_TMP
, rs
, 1, 1, 0, 0) | 1);
395 oi(LDR(0, REG_TMP
, rd
, 1, 1, 0, 0) | 1);
396 oi(ADD(I_SUB
, rn
, rn
, 0, 1, 14) | 1);
400 static void i_memset(int rd
, int rs
, int rn
)
402 oi(ADD(I_TST
, 0, rn
, 1, 0, 14) | rn
);
404 oi(LDR(0, rs
, rd
, 1, 1, 0, 0) | 1);
405 oi(ADD(I_SUB
, rn
, rn
, 0, 1, 14) | 1);
409 static void i_call_reg(int rd
)
411 i_mov(I_MOV
, REG_LR
, REG_PC
);
412 i_mov(I_MOV
, REG_PC
, rd
);
415 static void i_call(char *sym
)
418 out_rel(sym
, OUT_CS
| OUT_REL24
, cslen
);
422 static void i_prolog(void)
426 oi(0xe1a0c00d); /* mov r12, sp */
427 oi(0xe92d000f); /* stmfd sp!, {r0-r3} */
428 oi(0xe92d5ff0); /* stmfd sp!, {r0-r11, r12, lr} */
429 oi(0xe1a0b00d); /* mov fp, sp */
430 oi(0xe24dd000); /* sub sp, sp, xx */
431 oi(0xe28fa000); /* add dp, pc, xx */
434 static void i_epilog(void)
437 oi(0xe89baff0); /* ldmfd fp, {r4-r11, sp, pc} */
438 dpoff
= add_decimm(add_rndimm(add_encimm(cslen
- func_beg
- 28)));
439 cslen
= func_beg
+ dpoff
+ 28;
440 maxsp
= ALIGN(maxsp
, 8);
441 maxsp
= add_decimm(add_rndimm(add_encimm(maxsp
)));
442 /* fill stack sub: sp = sp - xx */
443 *(long *) (cs
+ func_beg
+ 16) |= add_encimm(maxsp
);
444 /* fill data ptr addition: dp = pc + xx */
445 *(long *) (cs
+ func_beg
+ 20) |= add_encimm(dpoff
);
449 static long sp_push(int size
)
457 static void tmp_mem(struct tmp
*tmp
)
460 if (!(tmp
->loc
== LOC_REG
))
464 tmp
->addr
= -sp_push(LONGSZ
);
465 i_ldr(0, src
, REG_FP
, tmp
->addr
, LONGSZ
);
470 static void num_cast(struct tmp
*t
, unsigned bt
)
472 if (!(bt
& BT_SIGNED
) && BT_SZ(bt
) != LONGSZ
)
473 t
->addr
&= ((1l << (long) (BT_SZ(bt
) * 8)) - 1);
474 if (bt
& BT_SIGNED
&& BT_SZ(bt
) != LONGSZ
&&
475 t
->addr
> (1l << (BT_SZ(bt
) * 8 - 1)))
476 t
->addr
= -((1l << (BT_SZ(bt
) * 8)) - t
->addr
);
479 static void tmp_reg(struct tmp
*tmp
, int dst
, int deref
)
486 if (tmp
->loc
== LOC_NUM
) {
487 i_num(dst
, tmp
->addr
);
492 if (tmp
->loc
== LOC_SYM
) {
493 i_sym(dst
, tmp
->sym
, tmp
->off
);
498 if (tmp
->loc
== LOC_REG
) {
500 i_ldr(1, dst
, tmp
->addr
, 0, bt
);
501 else if (dst
!= tmp
->addr
)
502 i_mov(I_MOV
, dst
, tmp
->addr
);
503 regs
[tmp
->addr
] = NULL
;
505 if (tmp
->loc
== LOC_LOCAL
) {
507 i_ldr(1, dst
, REG_FP
, tmp
->addr
+ tmp
->off
, bt
);
509 i_add_imm(I_ADD
, dst
, REG_FP
, tmp
->addr
+ tmp
->off
);
511 if (tmp
->loc
== LOC_MEM
) {
512 i_ldr(1, dst
, REG_FP
, tmp
->addr
, LONGSZ
);
514 i_ldr(1, dst
, dst
, 0, bt
);
521 static void reg_free(int reg
)
526 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
527 if (!regs
[tmpregs
[i
]]) {
528 tmp_reg(regs
[reg
], tmpregs
[i
], 0);
534 static void reg_for(int reg
, struct tmp
*t
)
536 if (regs
[reg
] && regs
[reg
] != t
)
540 static void tmp_mv(struct tmp
*t
, int reg
)
546 static void tmp_to(struct tmp
*t
, int reg
)
552 static void tmp_drop(int n
)
555 for (i
= ntmp
- n
; i
< ntmp
; i
++)
556 if (tmps
[i
].loc
== LOC_REG
)
557 regs
[tmps
[i
].addr
] = NULL
;
561 static void tmp_pop(int reg
)
563 struct tmp
*t
= TMP(0);
568 static struct tmp
*tmp_new(void)
570 return &tmps
[ntmp
++];
573 static void tmp_push(int reg
)
575 struct tmp
*t
= tmp_new();
582 void o_local(long addr
)
584 struct tmp
*t
= tmp_new();
593 struct tmp
*t
= tmp_new();
599 void o_sym(char *name
)
601 struct tmp
*t
= tmp_new();
602 strcpy(t
->sym
, name
);
608 void o_tmpdrop(int n
)
610 if (n
== -1 || n
> ntmp
)
620 #define FORK_REG 0x00
622 /* make sure tmps remain intact after a conditional expression */
626 for (i
= 0; i
< ntmp
- 1; i
++)
630 void o_forkpush(void)
635 void o_forkjoin(void)
642 struct tmp
*t1
= TMP(0);
643 struct tmp
*t2
= TMP(1);
645 memcpy(&t
, t1
, sizeof(t
));
646 memcpy(t1
, t2
, sizeof(t
));
647 memcpy(t2
, &t
, sizeof(t
));
648 if (t1
->loc
== LOC_REG
)
650 if (t2
->loc
== LOC_REG
)
654 static int reg_get(int mask
)
657 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
658 if ((1 << tmpregs
[i
]) & mask
&& !regs
[tmpregs
[i
]])
660 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
661 if ((1 << tmpregs
[i
]) & mask
) {
662 reg_free(tmpregs
[i
]);
668 static void tmp_copy(struct tmp
*t1
)
670 struct tmp
*t2
= tmp_new();
671 memcpy(t2
, t1
, sizeof(*t1
));
672 if (!(t1
->loc
& (LOC_REG
| LOC_MEM
)))
674 if (t1
->loc
== LOC_MEM
) {
675 tmp_reg(t2
, reg_get(~0), 0);
676 } else if (t1
->loc
== LOC_REG
) {
677 t2
->addr
= TMP_REG2(t2
, t1
->addr
);
678 i_mov(I_MOV
, t2
->addr
, t1
->addr
);
688 void o_cast(unsigned bt
)
690 struct tmp
*t
= TMP(0);
695 if (t
->loc
== LOC_NUM
) {
699 if (BT_SZ(bt
) != LONGSZ
) {
700 int reg
= TMP_REG(t
);
703 i_sx(reg
, BT_SZ(bt
) * 8);
705 i_zx(reg
, BT_SZ(bt
) * 8);
709 void o_func_beg(char *name
, int global
)
711 out_sym(name
, (global
? OUT_GLOB
: 0) | OUT_CS
, cslen
, 0);
718 memset(regs
, 0, sizeof(regs
));
721 void o_deref(unsigned bt
)
723 struct tmp
*t
= TMP(0);
725 tmp_to(t
, TMP_REG(t
));
731 struct tmp
*t
= TMP(0);
732 tmp_to(t
, TMP_REG(t
));
735 #define TMP_NUM(t) ((t)->loc == LOC_NUM && !(t)->bt)
736 #define LOCAL_PTR(t) ((t)->loc == LOC_LOCAL && !(t)->bt)
737 #define SYM_PTR(t) ((t)->loc == LOC_SYM && !(t)->bt)
739 int o_popnum(long *c
)
741 struct tmp
*t
= TMP(0);
755 ret
[nret
++] = o_jmp(0);
758 void o_func_end(void)
761 for (i
= 0; i
< nret
; i
++)
766 long o_mklocal(int size
)
768 return sp_push(ALIGN(size
, LONGSZ
));
771 void o_rmlocal(long addr
, int sz
)
778 return -(10 + i
) << 2;
781 void o_assign(unsigned bt
)
783 struct tmp
*t1
= TMP(0);
784 struct tmp
*t2
= TMP(1);
785 int r1
= TMP_REG(t1
);
786 int r2
= TMP_REG2(t2
, r1
);
791 if (t2
->loc
== LOC_LOCAL
) {
793 off
= t2
->addr
+ t2
->off
;
798 i_ldr(0, r1
, r2
, off
, bt
);
802 static long cu(int op
, long i
)
815 static int c_uop(int op
)
817 struct tmp
*t1
= TMP(0);
821 o_num(cu(op
, t1
->addr
));
825 static long cb(int op
, long a
, long b
)
847 return (unsigned long) a
>> b
;
866 static int c_bop(int op
)
868 struct tmp
*t1
= TMP(0);
869 struct tmp
*t2
= TMP(1);
870 int locals
= LOCAL_PTR(t1
) + LOCAL_PTR(t2
);
871 int syms
= SYM_PTR(t1
) + SYM_PTR(t2
);
872 int nums
= TMP_NUM(t1
) + TMP_NUM(t2
);
873 if (syms
+ locals
== 2 || syms
+ nums
+ locals
!= 2)
876 if ((op
!= O_ADD
&& op
!= O_SUB
) || (op
== O_SUB
&& TMP_NUM(t2
)))
879 long o1
= TMP_NUM(t1
) ? t1
->addr
: t1
->off
;
880 long o2
= TMP_NUM(t2
) ? t2
->addr
: t2
->off
;
881 long ret
= cb(op
, o2
, o1
);
887 long ret
= cb(op
, t2
->addr
, t1
->addr
);
896 int r1
= TMP_REG(TMP(0));
913 static void bin_regs(int *r1
, int *r2
)
915 struct tmp
*t2
= TMP(0);
916 struct tmp
*t1
= TMP(1);
919 *r1
= TMP_REG2(t1
, *r2
);
924 static void bin_add(int op
)
926 /* opcode for O_ADD, O_SUB, O_AND, O_OR, O_XOR */
927 static int rx
[] = {I_ADD
, I_SUB
, I_AND
, I_ORR
, I_EOR
};
930 i_add(rx
[op
], r1
, r1
, r2
);
934 static void bin_shx(int op
)
937 int shx
[] = {SM_LSL
, SM_LSR
, SM_ASR
};
940 i_shl(shx
[op
& 0x0f], r1
, r1
, r2
);
944 static int log2a(unsigned long n
)
947 for (i
= 0; i
< LONGSZ
* 8; i
++)
950 if (i
== LONGSZ
* 8 || !(n
>> (i
+ 1)))
955 /* optimized version of mul/div/mod for powers of two */
956 static int mul_2(int op
)
958 struct tmp
*t1
= TMP(0);
959 struct tmp
*t2
= TMP(1);
963 if (op
== O_MUL
&& t2
->loc
== LOC_NUM
&& !t2
->bt
)
965 if (t1
->loc
!= LOC_NUM
|| t1
->bt
)
982 i_shl_imm(SM_LSL
, r2
, p
);
991 i_shl_imm(SM_LSR
, r2
, p
);
1009 static void bin_mul(int op
)
1015 if (op
== O_DIV
|| op
== O_MOD
)
1016 printf("div not implemented\n");
1021 static void bin_cmp(int op
)
1023 /* lt, gt, le, ge, eq, neq */
1024 static int cond
[] = {11, 12, 13, 10, 0, 1};
1027 i_cmp(I_CMP
, r1
, r2
);
1028 i_set(cond
[op
& 0x0f], r1
);
1036 if ((op
& 0xf0) == 0x00)
1038 if ((op
& 0xf0) == 0x10)
1040 if ((op
& 0xf0) == 0x20)
1042 if ((op
& 0xf0) == 0x30)
1046 static void load_regs2(int *r0
, int *r1
, int *r2
)
1048 struct tmp
*t0
= TMP(0);
1049 struct tmp
*t1
= TMP(1);
1050 struct tmp
*t2
= TMP(2);
1052 *r1
= TMP_REG2(t1
, *r0
);
1053 *r2
= TMP_REG3(t2
, *r0
, *r1
);
1062 load_regs2(&rn
, &rs
, &rd
);
1063 i_memcpy(rd
, rs
, rn
);
1070 load_regs2(&rn
, &rs
, &rd
);
1071 i_memset(rd
, rs
, rn
);
1075 long o_mklabel(void)
1080 static long jxz(long addr
, int z
)
1082 int r
= TMP_REG(TMP(0));
1088 long o_jz(long addr
)
1090 return jxz(addr
, 1);
1093 long o_jnz(long addr
)
1095 return jxz(addr
, 0);
1098 long o_jmp(long addr
)
1104 void o_filljmp2(long addr
, long jmpdst
)
1106 i_b_fill((void *) cs
+ addr
, jmpdst
- addr
);
1109 void o_filljmp(long addr
)
1111 o_filljmp2(addr
, cslen
);
1114 void o_call(int argc
, int rets
)
1118 int aregs
= MIN(ARRAY_SIZE(argregs
), argc
);
1119 for (i
= 0; i
< ARRAY_SIZE(tmpregs
); i
++)
1120 if (regs
[tmpregs
[i
]] && regs
[tmpregs
[i
]] - tmps
< ntmp
- argc
)
1121 tmp_mem(regs
[tmpregs
[i
]]);
1123 sp_push(LONGSZ
* (argc
- aregs
));
1124 for (i
= argc
- 1; i
>= aregs
; --i
) {
1125 int reg
= TMP_REG(TMP(0));
1127 i_ldr(0, reg
, REG_SP
, (i
- aregs
) * LONGSZ
, LONGSZ
);
1130 for (i
= aregs
- 1; i
>= 0; --i
)
1131 tmp_to(TMP(aregs
- i
- 1), argregs
[i
]);
1134 if (t
->loc
== LOC_SYM
&& !t
->bt
) {
1138 int reg
= t
->loc
== LOC_REG
? t
->addr
: REG_TMP
;
1156 void dat_bss(char *name
, int size
, int global
)
1158 out_sym(name
, OUT_BSS
| (global
? OUT_GLOB
: 0), bsslen
, size
);
1159 bsslen
+= ALIGN(size
, LONGSZ
);
1162 #define MAXDATS (1 << 10)
1163 static char dat_names
[MAXDATS
][NAMELEN
];
1164 static int dat_offs
[MAXDATS
];
1167 void err(char *msg
);
1168 void *dat_dat(char *name
, int size
, int global
)
1170 void *addr
= ds
+ dslen
;
1173 err("nomem: MAXDATS reached!\n");
1174 strcpy(dat_names
[idx
], name
);
1175 dat_offs
[idx
] = dslen
;
1176 out_sym(name
, OUT_DS
| (global
? OUT_GLOB
: 0), dslen
, size
);
1177 dslen
+= ALIGN(size
, LONGSZ
);
1181 static int dat_off(char *name
)
1184 for (i
= 0; i
< ndats
; i
++)
1185 if (!strcmp(name
, dat_names
[i
]))
1190 void o_datset(char *name
, int off
, unsigned bt
)
1192 struct tmp
*t
= TMP(0);
1193 int sym_off
= dat_off(name
) + off
;
1194 if (t
->loc
== LOC_NUM
&& !t
->bt
) {
1196 memcpy(ds
+ sym_off
, &t
->addr
, BT_SZ(bt
));
1198 if (t
->loc
== LOC_SYM
&& !t
->bt
) {
1199 out_rel(t
->sym
, OUT_DS
, sym_off
);
1200 memcpy(ds
+ sym_off
, &t
->off
, BT_SZ(bt
));
1205 void o_write(int fd
)
1207 out_write(fd
, cs
, cslen
, ds
, dslen
);