comparison mc-code-spu.c @ 661:f566ac85f2e0

*** empty log message ***
author kono
date Wed, 21 Feb 2007 20:11:23 +0900
parents
children c9df4e08da9b
comparison
equal deleted inserted replaced
660:3e1dba5758d8 661:f566ac85f2e0
1 /* Micro-C Code Generation Part for Cell SPU */
2 /* ************************************************************************
3 ** Copyright (C) 2007 Shinji Kono
4 ** 連絡先: 琉球大学情報工学科 河野 真治
5 ** (E-Mail Address: kono@ie.u-ryukyu.ac.jp)
6 **
7 ** このソースのいかなる複写,改変,修正も許諾します。ただし、
8 ** その際には、誰が貢献したを示すこの部分を残すこと。
9 ** 再配布や雑誌の付録などの問い合わせも必要ありません。
10 ** 営利利用も上記に反しない範囲で許可します。
11 ** バイナリの配布の際にはversion messageを保存することを条件とします。
12 ** このプログラムについては特に何の保証もしない、悪しからず。
13 **
14 ** Everyone is permitted to do anything on this program
15 ** including copying, modifying, improving,
16 ** as long as you don't try to pretend that you wrote it.
17 ** i.e., the above copyright notice has to appear in all copies.
18 ** Binary distribution requires original version messages.
19 ** You don't have to ask before copying, redistribution or publishing.
20 ** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
21 ***********************************************************************/
22
23 #include <stdio.h>
24 #include "mc.h"
25 #include "mc-parse.h"
26 #include "mc-code.h"
27 #include "mc-codegen.h"
28
29 char *l_include_path[]={
30 "/usr/lib/gcc/spu/4.0.2/include",
31 "/usr/spu/include",
32 0};
33
34 // va_start, va_arg is wrong, use va_arm.h
35
36 static char *init_src0 = "\
37 #define __SPU__ 1\n\
38 #define __STDC_HOSTED__ 1\n\
39 #define __GNUC__ 4\n\
40 #define __FLT_MIN_EXP__ (-125)\n\
41 #define __DBL_MIN__ 2.2250738585072014e-308\n\
42 #define __NO_INLINE__ 1\n\
43 #define __ELF__ 1\n\
44 #define __FLT_RADIX__ 2\n\
45 #define __LDBL_EPSILON__ 2.2204460492503131e-16L\n\
46 #define __vector __attribute__((spu_vector))\n\
47 #define __WCHAR_TYPE__ int\n\
48 #define __DBL_EPSILON__ 2.2204460492503131e-16\n\
49 #define __INTMAX_MAX__ 9223372036854775807LL\n\
50 #define __FLT_DENORM_MIN__ 1.40129846e-45F\n\
51 #define __FLT_MAX__ 6.80564693e+38F\n\
52 #define __FLT_MIN_10_EXP__ (-37)\n\
53 #define __INTMAX_TYPE__ long long int\n\
54 #define __GNUC_MINOR__ 0\n\
55 #define __DBL_MAX_10_EXP__ 308\n\
56 #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L\n\
57 #define __PTRDIFF_TYPE__ long int\n\
58 #define __LDBL_MIN_10_EXP__ (-307)\n\
59 #define __LDBL_DIG__ 15\n\
60 #define __WINT_TYPE__ unsigned int\n\
61 ";
62
63 int data_alignment = 0;
64
65 #define TEXT_EMIT_MODE 0
66 #define DATA_EMIT_MODE 1
67 #define RODATA_EMIT_MODE 2
68
69 #define DOT_SIZE 1
70
71 // static void data_mode(char *name);
72 // static void text_mode(int alignment);
73 static void ld_indexx(int byte, int n, int xreg,int reg,int sign);
74 static void local_table(void);
75 static void shift(char *op, int creg,int reg);
76 static int push_struct(int e4,int t,int arg);
77 static void register_usage(char *s);
78 static void code_add(int reg,int offset,int r);
79 static void const_list_table();
80 //static int search_const(int tag,int value,int *label);
81 static char * cstore(int sz);
82 static void code_int_lib(char *lib,int reg,int oreg);
83 static int caller_arg_offset_v(int arg);
84 static void pcond(int op, int r2,int r1,int r0,int cond,int l1,int mode);
85 #if FLOAT_CODE
86 static int code_d1(double d);
87 static int code_d2(double d);
88 static void code_float_lib(char *opc,int oreg,int in_reg,int e1);
89 static void code_float_lib_c(char *lib,int from,int to,double value);
90 static void code_double_lib(char *lib,int to,int reg,int oreg);
91 static void code_double_lib_c(char *lib,int from,int to,double value);
92 static void dconst(int l,int h,double value);
93 static void code_assign_input_double_long(int e1,int e2) ;
94 static void code_assign_input_float_int(int e1,int e2) ;
95 #endif
96 static void use_input_reg(int reg,int mode);
97 static void ascii(char *s);
98
99 static int creg;
100 static int output_mode = TEXT_EMIT_MODE;
101 static int register_save_return_label;
102
103 static int r1_offset_label;
104 static int lvar_offset_label;
105 static int max_func_args = 0;
106 static int arg_on_register = 0;
107 static int max_func_arg_label = 0;
108
109
110 static int freg,ireg,lreg;
111
112 int code_lassop_p = 4;
113
114 #define SIZE_OF_INT 4
115 #define SIZE_OF_SHORT 2
116 #define SIZE_OF_FLOAT 4
117 #define SIZE_OF_DOUBLE 8
118 #define SIZE_OF_LONGLONG 8
119 #define ENDIAN 0
120 #define ENDIAN_L 0
121 #define ENDIAN_D 1
122
123 int eval_order = NORMAL;
124
125 static int reg_sp; /* REGister Stack-Pointer */
126 static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
127
128
129 #define REG_ip 13
130 #define REG_fp 0
131 #define REG_sp 1
132 #define REG_VAR_BASE 3
133 #define REG_VAR_MIN 3
134 #define REG_VAR_USER_MAX 127 /* at leat 6 tmp var */
135 #define REG_VAR_MAX 127
136 #define MIN_TMP_REG 4
137 #define MAX_TMP_REG 127
138
139 #define FREG_VAR_BASE 3
140 #define FREG_VAR_MIN 3
141 #define FREG_VAR_MAX 127
142 #define MIN_TMP_FREG 3
143 #define MAX_TMP_FREG 127
144
145 int MAX_REGISTER=127; /* ARMのレジスタを10個まで使う*/
146 #define REAL_MAX_REGISTER 127 /* ARMのレジスタが32ということ*/
147
148 #define FREG_OFFSET 3
149 #define LREG_OFFSET 3
150
151 int MAX_INPUT_REGISTER_VAR = 80;
152 int MAX_INPUT_DREGISTER_VAR = 80;
153 int MAX_INPUT_FREGISTER_VAR = 80;
154 int MAX_CODE_INPUT_REGISTER_VAR = 80;
155 int MAX_CODE_INPUT_DREGISTER_VAR = 80;
156 int MAX_CODE_INPUT_FREGISTER_VAR = 80;
157
158 #define LREG_V 3 /* mark for virtual long long/double register */
159 #define REGS_MAX (REAL_MAX_REGISTER)
160 static int spu_regs[REGS_MAX];
161 /// #define (i) (i)
162 // #define (i) (i)
163
164 #define RET_REGISTER 3
165 #define REGISTER_OPERAND 3 //this is first register for input
166 #define REGISTER_OPERAND_1 4
167 #define RET_FREGISTER FREG_OFFSET
168 #define FREGISTER_OPERAND (FREG_OFFSET)
169 #define FREGISTER_OPERAND_1 (FREG_OFFSET+1)
170
171 #define RET_LREGISTER 3
172 #define LREGISTER_OPERAND 3
173 #define LREGISTER_OPERAND_1 4
174 #define RET_LREGISTER_L 1 /* low word */
175 #define RET_LREGISTER_H 2 /* high word */
176 #define LREGISTER_OPERAND_L 1 /* low word */
177 #define LREGISTER_OPERAND_H 2 /* high word */
178 #define LREGISTER_OPERAND_1_L 3 /* low word */
179 #define LREGISTER_OPERAND_1_H 4 /* high word */
180
181 #define RET_DREGISTER RET_LREGISTER
182 #define DREGISTER_OPERAND LREGISTER_OPERAND
183 #define DREGISTER_OPERAND_1 LREGISTER_OPERAND_1
184 #define RET_DREGISTER_L RET_LREGISTER_L
185 #define RET_DREGISTER_H RET_LREGISTER_H
186 #define DREGISTER_OPERAND_H LREGISTER_OPERAND_H
187 #define DREGISTER_OPERAND_L LREGISTER_OPERAND_L
188 #define DREGISTER_OPERAND_1_L LREGISTER_OPERAND_1_L
189 #define DREGISTER_OPERAND_1_H LREGISTER_OPERAND_1_H
190
191 static int *regs = spu_regs;
192
193 // #define CREG_REGISTER (MAX_TMP_REG)
194 #define CREG_REGISTER REGISTER_OPERAND
195 // #define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET)
196 #define FREG_FREGISTER FREGISTER_OPERAND
197 // #define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET)
198 #define LREG_LREGISTER LREGISTER_OPERAND
199 #define DREG_DREGISTER LREG_LREGISTER
200 #define CMP_C1T (-1)
201
202
203 static int max_reg_var;
204
205
206 static char *reg_name[] = {
207 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
208 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
209 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
210 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
211 "$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39",
212 "$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47",
213 "$48", "$49", "$50", "$51", "$52", "$53", "$54", "$55",
214 "$56", "$57", "$58", "$59", "$60", "$61", "$62", "$63",
215 "$64", "$65", "$66", "$67", "$68", "$69", "$70", "$71",
216 "$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79",
217 "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87",
218 "$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95",
219 "$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103",
220 "$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111",
221 "$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119",
222 "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127"
223 };
224
225 #define register_name(i) reg_name[i]
226 #define lregister_name_low(i) reg_name[i]
227 #define lregister_name_high(i) reg_name[i]
228
229 char *rn(int i) { return register_name(i); }
230 char *lln(int i) { return lregister_name_low(i); }
231 char *lhn(int i) { return lregister_name_high(i); }
232 int ll(int i) { return i; }
233 int lh(int i) { return i; }
234
235 #define is_int_reg(i) (0<=i&&i<REAL_MAX_REGISTER)
236 #define is_float_reg(i) (is_int_reg(i))
237 #define is_longlong_reg(i) (is_int_reg(i))
238 #define is_double_reg(i) (is_int_reg(i))
239
240 #define use_int(reg) if (reg==USE_CREG) reg=use_int0()
241 static
242 int use_int0() {
243 int i = creg;
244 if (!i||!ireg||!is_int_reg(i)) {
245 if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; }
246 if (!ireg) ireg = get_register();
247 // else if (ireg!=i) free_register(i);
248 i = ireg;
249 }
250 if (!regs[i]) regs[i]=USING_REG;
251 creg = i;
252 return i;
253 }
254
255 #if LONGLONG_CODE||FLOAT_CODE
256 #define use_longlong(reg) if (reg==USE_CREG) reg=use_int0()
257 /*
258 static
259 int use_longlong0() {
260 int i = creg;
261 if (!is_longlong_reg(i)) {
262 if (ireg) { free_register(ireg); ireg=0; }
263 if (!lreg||!regs[lreg]) lreg = get_lregister();
264 else if (lreg!=i) free_register(i);
265 i = lreg;
266 }
267 if (!(i)) (i) = get_register();
268 if (!(i)) (i) = get_register();
269 if (!regs[i]) regs[i]=USING_REG;
270 if (!regs[(i)]) regs[(i)]=USING_REG;
271 if (!regs[(i)]) regs[(i)]=USING_REG;
272 creg = i;
273 return i;
274 }
275 */
276 static void lmove(int to,int from);
277 #endif
278
279 #define USING_DREG 5
280 #define INPUT_DREG 6
281
282
283 #if FLOAT_CODE
284
285 #define dsuffix(d) (d?'d':'s')
286
287 #define use_float(d,reg) if (reg==USE_CREG) { reg=use_int0();}
288
289 /*
290 static
291 int use_double0() {
292 int i;
293 use_longlong0();
294 use_int0();
295 i = lreg;
296 if (!regs[i]) regs[i]=USING_DREG;
297 if (!regs[(i)]) regs[(i)]=USING_REG;
298 if (!regs[(i)]) regs[(i)]=USING_REG;
299 creg = i;
300 return i;
301 }
302 */
303 void code_lassign_lvar(int e2,int creg);
304 int code_lrindirect(int e1, int reg, int offset, int us);
305 void code_lregister(int e2,int reg);
306 void code_lassign_gvar(int e2,int creg);
307 void code_lassign(int e2,int creg);
308 void code_lassign_lregister(int e2,int reg);
309 void code_lrgvar(int e1,int creg);
310 void code_lrlvar(int e1,int creg);
311 void emit_lpop_free(int xreg);
312 void emit_lpush();
313 int emit_lpop();
314
315 #endif
316
317
318
319 #if LONGLONG_CODE
320 static int code_l1(long long ll);
321 static int code_l2(long long ll);
322 #endif
323
324 static void code_save_input_registers(int dots);
325 static void set_ireg(int,int);
326 #if FLOAT_CODE
327 static void set_dreg(int,int);
328 static void set_freg(int,int);
329 #endif
330 #if LONGLONG_CODE
331 static void set_lreg(int,int);
332 #endif
333
334 static int max_func_args;
335 static int my_func_args;
336
337
338
339
340
341 static void jcond(int l, int cond);
342
343 #define ARG_LVAR_OFFSET 0x10000000
344
345 #define round16(i) ((i+0xf)&~0xf)
346 #define round4(i) ((i+3)&~3)
347
348 /*
349
350 r0 return value etc.
351 r0,r1 return value. (dpcmp return value on $2)
352 00 special register
353 r0-r3 input register
354 r7-r9 saved register variable (input register for code segment)
355 jump register
356 sp stack pointer
357 fp frame pointer
358
359 f0 return value etc.
360 r0-r3 input register
361 f20-f31 saved register variable
362
363 code segment stack frame
364
365 register_save is done by callee
366
367 (prev $sp)
368 <---lvar_offset-->
369 # $fp <--------------------r1_offset---------> $sp
370 r+ +----------+-------------+--------+-------+-----------+---------------+
371 cousin arg! callee arg !reg_save!reg_arg!local caller arg
372 (arg4..)lvar>0 (arg0.3) lvar<0 lvar>0x1000 000
373 <--------------my_func_args--><--disp-----><-max_func_arg->
374 *SIZE_OF_INT *SIZE_OF_INT
375 prev $sp=$fp $fp $sp
376
377 (prev $sp)
378 <------r1_offset----------------> $sp
379 (prev $fp) $fp
380 r+ +-----------+--------------------+----------+-----------------------+
381 callee arg register save local caller arg
382 disp max_func_args*SIZE_OF_INT
383 lvar<0 lvar>0x1000 0000
384 prev $sp=$fp $sp=$fp
385 */
386
387 #define arg_offset (16)
388 #define arg_offset1 (-64)
389 int disp_offset=0; // fore mc-codegen.c
390 #define disp_offset 0
391
392 #define code_disp_offset 0
393
394 #define CODE_LVAR(l) ((l)+code_disp_offset)
395 #define CODE_CALLER_ARG(l) ((l)+arg_offset1)
396 #define FUNC_LVAR(l) (l+disp_offset)
397 #define CALLER_ARG(l) ((l)+arg_offset1)
398 #define CALLEE_ARG(l) ((l)+arg_offset)
399
400 static int
401 code_offset_set(NMTBL *fnptr)
402 {
403 int lvar_offsetv;
404 int r1_offsetv;
405 int code_f = is_code(fnptr);
406
407 disp &= -SIZE_OF_INT;
408
409 if (code_f) {
410 r1_offsetv = disp-max_func_args*SIZE_OF_INT+code_disp_offset;
411 printf("\t.set .LC%d, %d\n",r1_offset_label,r1_offsetv);
412 } else {
413 lvar_offsetv =
414 -12 - max_reg_var*SIZE_OF_INT-max_reg_var*SIZE_OF_DOUBLE;
415 printf("\t.set .LC%d, %d\n",lvar_offset_label,lvar_offsetv);
416 }
417 if (max_func_arg_label) {
418 printf("\t.set .LC%d, %d\n",max_func_arg_label,max_func_args*SIZE_OF_INT);
419 max_func_arg_label = 0;
420 }
421
422
423 // printf(" @ args = %d, pretend = %d, frame = %d\n",
424 // max_func_args,0,round16(-disp));
425 // printf(" @ frame_needed = 1, current_function_anonymous_args = 0\n");
426
427
428 #if 0
429 printf("## vars= %d, regs= %d/%d, args= %d, extra= %d\n",
430 round16(-disp),
431 max_reg_var+2,
432 max_reg_var,
433 round16(max_func_args*SIZE_OF_INT),
434 0
435 );
436 printf("## callee arg top=\t%d\n",CALLEE_ARG(0));
437 printf("## reg_save_top=\t\t%d\n",r1_offsetv);
438 printf("## reg_save_end=\t\t%d\n",
439 -max_reg_var*SIZE_OF_INT-max_reg_var*SIZE_OF_FLOAT-2*SIZE_OF_INT+
440 r1_offsetv);
441 printf("## lvar_offset=\t\t%d %d\n",lvar_offsetv,lvar_offsetv%16);
442 printf("## min local var=\t%d\n",FUNC_LVAR(0)+lvar_offsetv);
443 printf("## max local var=\t%d\n",FUNC_LVAR(disp)+lvar_offsetv);
444 printf("## min caller arg var=\t%d\n",
445 CALLER_ARG(round16(max_func_args*SIZE_OF_INT)));
446 printf("## max caller arg var=\t%d\n",CALLER_ARG(0));
447 printf("##\n");
448 #endif
449
450 return 0;
451 }
452
453 #define LARGE_OFFSET(l) (l<-511||l>511)
454
455 static void lvar_address(int l,int creg);
456
457 static int large_lvar;
458 static void
459 lvar_intro(int l)
460 {
461 int large;
462 if (is_code(fnptr)) {
463 if (l>=ARG_LVAR_OFFSET) {
464 large = LARGE_OFFSET(CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
465 } else
466 large = LARGE_OFFSET(CODE_LVAR(l));
467 } else if (l<0) { /* local variable */
468 large = LARGE_OFFSET(FUNC_LVAR(l));
469 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
470 large = LARGE_OFFSET(CALLER_ARG(l-ARG_LVAR_OFFSET));
471 } else { /* callee's arguments */
472 large = LARGE_OFFSET(CALLEE_ARG(l));
473 }
474 if (large) {
475 large_lvar = get_register();
476 lvar_address(l,large_lvar);
477 } else {
478 large_lvar = 0;
479 }
480 }
481
482 static void
483 lvar(int l,char *cext)
484 {
485 if (large_lvar) {
486 printf("[%s, 0]%s\n",register_name(large_lvar),cext);
487 free_register(large_lvar);
488 return;
489 }
490 if (is_code(fnptr)) {
491 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
492 printf("[sp, %d]%s\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET),cext);
493 } else
494 printf("[fp, %d]%s\n",CODE_LVAR(l),cext);
495 } else if (l<0) { /* local variable */
496 //printf("[fp, #%d+.L%d]%s\n",FUNC_LVAR(l),lvar_offset_label,cext);
497 printf("%d($sp)\n",FUNC_LVAR(l));
498 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
499 printf("[sp, %d]%s\n",CALLER_ARG(l-ARG_LVAR_OFFSET),cext);
500 } else { /* callee's arguments */
501 printf("[fp, %d]%s\n",CALLEE_ARG(l),cext);
502 }
503 }
504
505 static void
506 lvar_address(int l,int creg)
507 {
508 //int label,disp;
509 int disp;
510 int tmp = -1;
511 char *trn;
512 if (is_code(fnptr)) {
513 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
514 code_add(creg,CODE_CALLER_ARG(l-ARG_LVAR_OFFSET),REG_sp);
515 } else
516 code_add(creg,CODE_LVAR(l),REG_fp);
517 } else if (l<0) { /* local variable */
518 // printf("\tsf\t%s, fp, %d\n",register_name(creg), FUNC_LVAR(l));
519 trn = register_name(tmp = get_register());
520 //disp = search_const(LVAR,glist2(lvar_offset_label,FUNC_LVAR(l)),&label);
521 printf("\tlqd\t%s, %d($sp)\n",trn,(disp*4));
522 printf("\tadd\t%s, fp, %s\n",register_name(creg),trn);
523 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
524 code_add(creg,CALLER_ARG(l-ARG_LVAR_OFFSET),REG_sp);
525 } else { /* callee's arguments */
526 code_add(creg,CALLEE_ARG(l),REG_fp);
527 }
528 if (tmp!=-1) free_register(tmp);
529 }
530
531
532 void
533 code_lvar(int e2,int reg) {
534 use_int(reg);
535 lvar_address(e2,reg);
536 }
537
538
539 void
540 code_init(void)
541 {
542 /* called only once */
543
544 size_of_int = SIZE_OF_INT;
545 size_of_short = SIZE_OF_SHORT;
546 size_of_float = SIZE_OF_FLOAT;
547 size_of_double = SIZE_OF_DOUBLE;
548 size_of_longlong = SIZE_OF_LONGLONG;
549 endian = ENDIAN;
550 init_src = init_src0;
551
552 }
553
554 extern void
555 emit_reinit()
556 {
557 /* called for each file */
558 init_ptr_cache();
559 output_mode = -1;
560 }
561
562
563
564 void
565 gexpr_code_init(void){
566 }
567
568 void
569 code_gexpr(int e){
570 if (is_int_reg(creg) && creg!=ireg) error(-1);
571 // register_usage("code_gexpr");
572 }
573
574
575 void
576 code_arg_register(NMTBL *fnptr)
577 {
578 int args = fnptr->dsp;
579 NMTBL *n;
580 int reg_var = 0;
581 int freg_var = 0;
582 int type;
583 int reg;
584 int i;
585 int is_code0 = is_code(fnptr);
586 int dots;
587
588 function_type(fnptr->ty,&dots);
589 while (args) {
590 /* process in reverse order */
591 n = (NMTBL*)caddr(args);
592 type = n->ty;
593 if (scalar(type)) {
594 if ((reg = get_input_register_var(reg_var,n,is_code0))) {
595 n->sc = REGISTER;
596 n->dsp = cadr(reg);
597 regs[n->dsp]= INPUT_REG;
598 reg_var++;
599 cadddr(args)=SIZE_OF_INT;
600 }
601 } else if (type==FLOAT) {
602 if (is_function(fnptr)) {
603 if ((reg = get_input_dregister_var(reg_var,n,is_code0,0))) {
604 n->sc = REGISTER;
605 n->dsp = cadr(reg);
606 regs[n->dsp]= INPUT_REG;
607 reg_var++;
608 cadddr(args)=size(type);
609 }
610 } else {
611 if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) {
612 n->sc = FREGISTER;
613 n->dsp = cadr(reg);
614 regs[n->dsp]= INPUT_REG;
615 freg_var++;
616 cadddr(args)=size(type);
617 }
618 }
619 } else if (type==DOUBLE) {
620 if ((reg = get_input_dregister_var(reg_var,n,is_code0,1))) {
621 n->sc = LREGISTER;
622 n->dsp = cadr(reg);
623 regs[i=n->dsp]= INPUT_DREG;
624 regs[i]= INPUT_REG;
625 //regs[i]= INPUT_REG;
626 reg_var+=2;
627 cadddr(args)=size(type);
628 }
629 } else if (type==LONGLONG||type==ULONGLONG) {
630 if ((reg = get_input_lregister_var(reg_var,n,is_code0))) {
631 n->sc = LREGISTER;
632 n->dsp = cadr(reg);
633 regs[i=n->dsp]= INPUT_REG;
634 regs[i]= INPUT_REG;
635 //regs[(i)]= INPUT_REG;
636 reg_var+=2;
637 cadddr(args)=size(type);
638 }
639 }
640 args = cadr(args);
641 }
642 if (is_function(fnptr))
643 code_save_input_registers(dots);
644 }
645
646
647 int
648 get_register(void)
649 { /* 使われていないレジスタを調べる */
650 int i,j,reg;
651 for(i=MAX_TMP_REG;i>=MIN_TMP_REG;i--) {
652 if (regs[i]) continue; /* 使われている */
653 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */
654 return i; /* その場所を表す番号を返す */
655 }
656 for(i=0;i<REG_VAR_MAX-REG_VAR_MIN;i++) {
657 reg =REG_VAR_BASE+i;
658 if (! regs[reg]) { /* 使われていないなら */
659 regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */
660 if (i+1>max_reg_var) max_reg_var=i+1;
661 return reg; /* その場所を表す番号を返す */
662 }
663 }
664 /* search register stack */
665 for(i=0;i<reg_sp;i++) {
666 if ((reg=reg_stack[i])>0) {
667 code_assign_lvar(
668 (j=new_lvar(SIZE_OF_INT)*4),reg,0);
669 reg_stack[i]= j-REG_LVAR_OFFSET;
670 return reg;
671 }
672 }
673 #if LONGLONG_CODE||FLOAT_CODE
674 /* search register stack */
675 for(i=0;i<reg_sp;i++) {
676 if ((reg=reg_stack[i])>0) {
677 code_lassign_lvar(
678 (j=new_lvar(SIZE_OF_LONGLONG)),reg);
679 reg_stack[i]= j-REG_LVAR_OFFSET;
680 free_register(reg);
681 return get_register();
682 }
683 }
684 #endif
685 /* PTR_CACHE をつぶす */
686 for(i=MAX_TMP_REG;i>=MIN_TMP_REG;i--) {
687 if (regs[i]==PTRC_REG) {
688 clear_ptr_cache_reg(i);
689 } else
690 continue;
691 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */
692 return i; /* その場所を表す番号を返す */
693 }
694 for(i=0;i<REG_VAR_MAX-REG_VAR_MIN;i++) {
695 reg =REG_VAR_BASE+i;
696 /* PTR_CACHE をつぶす */
697 if (regs[reg]==PTRC_REG) {
698 clear_ptr_cache_reg(reg);
699 regs[reg]=0;
700 return reg; /* その場所を表す番号を返す */
701 }
702 }
703 /* あいている場所がないなら、エラー(いったい誰が使ってるの?) */
704 error(RGERR); return creg;
705 }
706
707 #if 0
708 int
709 get_register(void)
710 {
711 int i = get_register0();
712 printf("## get_register %d\n",i);
713 //printf("hoge:%d\n",i);
714 return i;
715 }
716 #endif
717
718 int
719 pop_register(void)
720 { /* レジスタから値を取り出す */
721 return reg_stack[--reg_sp];
722 }
723
724 #if FLOAT_CODE
725 int
726 get_dregister(int d)
727 { /* 使われていないレジスタを調べる */
728 return get_register();
729 }
730
731 #if 0
732 int
733 get_dregister(int d)
734 {
735 int i = get_dregister0(d);
736 printf("## get_dregister %d\n",i);
737 return i;
738 }
739 #endif
740
741 int
742 pop_fregister(void)
743 { /* レジスタから値を取り出す */
744 return reg_stack[--reg_sp];
745 }
746 #endif
747
748 // static int lreg_count;
749 int
750 get_lregister0()
751 {
752 return get_register();
753 }
754
755 int
756 get_lregister()
757 {
758 return get_register();
759 }
760
761 int
762 get_lregister_var(NMTBL *n)
763 {
764 return get_register_var(n);
765 }
766
767 void
768 emit_pop_free(int xreg)
769 {
770 if (xreg>=0 && xreg!=creg)
771 free_register(xreg);
772 }
773
774 void
775
776 free_register(int i) { /* いらなくなったレジスタを解放 */
777 // printf("## free_register %d\n",i);
778 regs[i]=0;
779 // if (is_longlong_reg(i)) {
780 // printf("## free lregister %d (%d)\n",i,lreg_count++);
781 // regs[(i)]=0;
782 // regs[(i)]=0;
783 //(i)=0;
784 //(i)=0;
785 // }
786 }
787
788 extern void
789 use_ptr_cache(int r)
790 {
791 regs[r]=PTRC_REG;
792 }
793
794 int
795 get_input_dregister_var(int i,NMTBL *n,int is_code,int d)
796 {
797 int j;
798 if (is_code) {
799 if(i>MAX_CODE_INPUT_DREGISTER_VAR) return 0;
800 i = FREG_VAR_BASE+i+FREG_OFFSET;
801 use_input_reg(i,1);
802 return list3(FREGISTER,i,(int)n);
803 }
804 if (d) {
805 j = get_input_lregister_var(i,n,is_code);
806 return j;
807 } else {
808 if (i==0) return list3(REGISTER,1,(int)n);
809 else if (i==1) return list3(REGISTER,2,(int)n);
810 else if (i==2) return list3(REGISTER,3,(int)n);
811 else if (i==3) return list3(REGISTER,4,(int)n);
812 else return 0;
813 }
814 }
815
816 int
817 get_input_lregister_var(int i,NMTBL *n,int is_code)
818 {
819 return get_input_register_var(i,n,is_code);
820 }
821
822 int
823 get_input_register_var(int i,NMTBL *n,int is_code)
824 {
825 if (is_code) {
826 if(!(i<REG_VAR_MAX-REG_VAR_MIN)) return 0;
827 i = REG_VAR_BASE+i;
828 use_input_reg(i,1);
829 } else {
830 if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0;
831 i = i+1;
832 }
833 return list3(REGISTER,i,(int)n);
834 }
835
836
837 int
838 free_register_count(int d)
839 {
840 int i,count,fcount;
841 fcount = count = 0;
842 for(i=0;i<MAX_REGISTER;i++) {
843 if (! regs[i]) count++;
844 }
845 for(i=0;i<MAX_REGISTER;i++) {
846 if (! regs[i+FREG_OFFSET]) fcount++;
847 }
848 printf("## free reg %d freg %d\n",count,fcount);
849 return d?fcount:count;
850 }
851
852 #if 0
853 static int
854 register_full(void)
855 {
856 int i;
857 for(i=0;i<MAX_REGISTER;i++) {
858 if (! regs[i]) {
859 return 0;
860 }
861 }
862 return 1;
863 }
864 #endif
865
866 void
867 free_all_register(void)
868 {
869 int i;
870 // printf("## free_all register\n");
871 #if LONGLONG_CODE||FLOAT_CODE
872 for(i=0;i<REAL_MAX_REGISTER;i++) {
873 regs[i+LREG_OFFSET]=0;
874 }
875 lreg = 0;
876 // set_lreg(LREG_LREGISTER,0);
877 #endif
878 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; }
879 #if FLOAT_CODE
880 for(i=0;i<MAX_REGISTER;i++) { regs[i+FREG_OFFSET]=0; }
881 freg = get_dregister(1);
882 set_freg(FREG_FREGISTER,0);
883 #endif
884 ireg = creg = get_register();
885 set_ireg(CREG_REGISTER,0);
886 return;
887 }
888
889
890 extern int
891 code_register_overlap(int s,int t)
892 {
893 switch(car(s)) {
894 case REGISTER:
895 switch(car(t)) {
896 case FREGISTER: break;
897 case REGISTER:
898 return cadr(s)==cadr(t);
899 break;
900 case LREGISTER: case DREGISTER:
901 if(cadr(s)==(cadr(t))) return 1;
902 if(cadr(s)==(cadr(t))) return 1;
903 break;
904 }
905 break;
906 case FREGISTER:
907 switch(car(t)) {
908 case REGISTER: case LREGISTER: case DREGISTER: break;
909 case FREGISTER:
910 return cadr(s)==cadr(t);
911 break;
912 }
913 break;
914 case DREGISTER:
915 case LREGISTER:
916 switch(car(t)) {
917 case FREGISTER: break;
918 case REGISTER:
919 if(cadr(t)==(cadr(s))) return 1;
920 if(cadr(t)==(cadr(s))) return 1;
921 break;
922 case LREGISTER: case DREGISTER:
923 if((cadr(t))==(cadr(s))) return 1;
924 if((cadr(t))==(cadr(s))) return 1;
925 if((cadr(t))==(cadr(s))) return 1;
926 if((cadr(t))==(cadr(s))) return 1;
927 break;
928 }
929 break;
930 }
931 return 0;
932 }
933
934
935 void
936 register_usage(char *s)
937 {
938 #if 1
939 int i,j;
940 #endif
941 #define USAGE_MAX 4
942 if (!lsrc) return;
943 printf("## %d: %s:",lineno,s);
944 if (ireg) printf(" creg=%s",register_name(ireg));
945 if (freg) printf(" freg=%s",register_name(freg));
946 if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg),
947 lregister_name_low(lreg));
948 #if 1
949 for(j=0,i=1;i<MAX_REGISTER;i++) if (regs[i]) j++;
950 if (j>USAGE_MAX) {
951 // printf("\n# regs:01234567890123456789012");
952 printf("\n# regs:");
953 for(i=1;i<MAX_REGISTER;i++) { printf("%d",regs[i]); }
954 }
955 if (reg_sp>0) {
956 printf(" stack ");
957 for(i=reg_sp;i>0;i--) {
958 if(reg_stack[i-1]>=0) {
959 printf(" %s",register_name(reg_stack[i-1]));
960 } else
961 printf(",%d",reg_stack[i-1]);
962 }
963 }
964 for(j=0,i=0;i<MAX_REGISTER;i++) if (regs[i+FREG_OFFSET]) j++;
965 if (j>USAGE_MAX) {
966 printf("\n# freg:");
967 for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); }
968 }
969 if (reg_sp>0) {
970 printf(" fstack ");
971 for(i=reg_sp;i>0;i--) {
972 if(reg_stack[i-1]>=0) {
973 printf(" %s",register_name(reg_stack[i-1]));
974 } else
975 printf(",%d",reg_stack[i-1]);
976 }
977 }
978
979 for(j=0,i=0;i<REAL_MAX_REGISTER;i++) if (regs[i+LREG_OFFSET]) j++;
980 if (j>USAGE_MAX) {
981 printf("\n# lreg:");
982 for(i=0;i<REAL_MAX_REGISTER;i++) { printf("%d",regs[i+LREG_OFFSET]); }
983 }
984 if (reg_sp>0) {
985 printf(" lstack ");
986 for(i=reg_sp;i>0;i--) {
987 if(reg_stack[i-1]>=0) {
988 printf(" %s",lregister_name_high(reg_stack[i-1]));
989 printf(",%s",lregister_name_low(reg_stack[i-1]));
990 } else
991 printf(",%d",reg_stack[i-1]);
992 }
993 }
994 #endif
995 printf("\n");
996 }
997
998
999 void
1000 gexpr_init(void)
1001 {
1002 while(reg_sp > 0) {
1003 error(-1);
1004 free_register(reg_stack[--reg_sp]);
1005 }
1006 while(reg_sp > 0) {
1007 error(-1);
1008 free_register(reg_stack[--reg_sp]);
1009 }
1010 while(reg_sp > 0) {
1011 error(-1);
1012 free_register(reg_stack[--reg_sp]);
1013 }
1014 use_int0();
1015 text_mode(2);
1016 gexpr_code_init();
1017 register_usage("");
1018 }
1019
1020
1021 void
1022
1023 emit_init(void)
1024 {
1025 /* called before each declaration */
1026
1027 free_all_register();
1028 max_reg_var=0; max_reg_var=0;
1029 reg_sp = 0;
1030 reg_sp = 0;
1031 }
1032
1033 #define reg_var_num(i) (REG_VAR_BASE+i)
1034
1035 int
1036 get_register_var(NMTBL *n)
1037 {
1038 int i,j;
1039 int max = n?REG_VAR_USER_MAX-REG_VAR_BASE:REG_VAR_MAX-REG_VAR_BASE;
1040 for(i=0;i<max;i++) {
1041 j = reg_var_num(i);
1042 if (! regs[j]) { /* ??͡??????ˡ????ϡ????ϡ?? */
1043 /* ????ۡ???????????͡??????͡?????????? */
1044 regs[j]=USING_REG;
1045 if (i+1>=max_reg_var) max_reg_var=i+1;
1046 /* ????ۥ???????Υ?????襱?????衢? */
1047 return list3(REGISTER,j,(int)n);
1048 }
1049 }
1050 return list3(LVAR,new_lvar(SIZE_OF_INT),0);
1051 }
1052
1053 #define freg_var_num(i) (FREG_VAR_BASE+i+FREG_OFFSET)
1054
1055 int
1056 get_dregister_var(NMTBL *n,int d)
1057 {
1058 int i,j;
1059 for(i=0;i<FREG_VAR_MAX-FREG_VAR_BASE;i++) {
1060 j = freg_var_num(i);
1061 if (! regs[j]) { /* 使われていないなら */
1062 regs[j]=USING_REG; /* そのレジスタを使うことを宣言し */
1063 if (i+1>max_reg_var) max_reg_var=i+1;
1064 /* その場所を表す番号を返す */
1065 return list3(FREGISTER,j,(int)n);
1066 }
1067 }
1068 }
1069
1070 int
1071 emit_push()
1072 {
1073 int new_reg,old=creg;
1074 if (!is_int_reg(creg)) error(-1);
1075 if (reg_sp>MAX_MAX) error(-1);
1076 new_reg = get_register(); /* 絶対にとれる */
1077 if (new_reg==creg) error(-1); /* who freed creg? */
1078 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */
1079 ireg = creg = new_reg;
1080 if (!regs[creg]) regs[creg]=USING_REG;
1081 return old;
1082 }
1083
1084 int
1085 emit_pop(int type)
1086 {
1087 int xreg,reg;
1088 xreg=pop_register();
1089 if (xreg<= -REG_LVAR_OFFSET) {
1090 reg = get_register();
1091 code_rlvar(REG_LVAR_OFFSET+xreg,reg);
1092 free_lvar(REG_LVAR_OFFSET+xreg);
1093 xreg = reg;
1094 }
1095 return xreg;
1096 }
1097
1098 static int const_list;
1099 static int const_list_label;
1100 static int prev_const_list;
1101 static int prev_const_list_label;
1102
1103 /*
1104 constant table
1105 glist3( tag, next, value )
1106 LVAR glist2(label,offset)
1107 GVAR nptr
1108 CONST value
1109 LABEL value
1110 nth element has offset n * SIZE_OF_INT
1111 */
1112
1113 #define CONST_TBL_COUNT 100
1114 /*
1115 static int
1116 search_const(int tag,int value,int *label)
1117 {
1118 int p,i,j,list,prev;
1119
1120 for(j=0;j<2;j++) {
1121 i = 0;
1122 if(j==1) {
1123 if (!const_list_label) const_list_label = fwdlabel();
1124 *label = const_list_label;
1125 if (const_list==0) {
1126 const_list = glist3(tag,0,value);
1127 return 0;
1128 } else {
1129 prev = list = const_list;
1130 }
1131 } else {
1132 prev = list = prev_const_list; *label = prev_const_list_label;
1133 }
1134 for(p = list; p ;prev=p,p=cadr(p),i+=SIZE_OF_INT) {
1135 if (car(p)!=tag) continue;
1136 switch(tag) {
1137 case GVAR: case CONST: case LABEL:
1138 if (caddr(p)!=value) continue;
1139 return i;
1140 case LVAR:
1141 if (car(caddr(p))!=car(value)) continue;
1142 if (cadr(caddr(p))!=cadr(value)) continue;
1143 return i;
1144 }
1145 }
1146 }
1147 cadr(prev) = glist3(tag,0,value);
1148 if (i>CONST_TBL_COUNT) {
1149 const_list_table();
1150 }
1151 return i;
1152 }
1153 */
1154 #if FLOAT_CODE
1155 static int
1156 search_double_const(int tag,int value1,int value2,int *label)
1157 {
1158 int p,i,j,list,prev;
1159
1160 for(j=0;j<2;j++) {
1161 i = 0;
1162 if(j==1) {
1163 if (!const_list_label) const_list_label = fwdlabel();
1164 *label = const_list_label;
1165 if (const_list==0) {
1166 const_list = glist3(tag,glist3(tag,0,value2),value1);
1167 return 0;
1168 } else {
1169 prev = list = const_list;
1170 }
1171 } else {
1172 prev =list = prev_const_list; *label = prev_const_list_label;
1173 }
1174 for(p = list; p ;prev=p,p=cadr(p),i+=SIZE_OF_INT) {
1175 if (car(p)!=tag) continue;
1176 switch(tag) {
1177 case DCONST: case LCONST:
1178 if (caddr(p)!=value1) continue;
1179 p = cadr(p);
1180 if (!p||car(p)!=tag) error(-1);
1181 if (caddr(p)!=value2) continue;
1182 return i;
1183 }
1184 prev = p;
1185 }
1186 }
1187 cadr(prev) = glist3(tag,glist3(tag,0,value2),value1);
1188 if (i>CONST_TBL_COUNT) {
1189 const_list_table();
1190 }
1191 return i;
1192 }
1193 #endif
1194
1195 static int inst_count;
1196
1197 static void
1198 const_list_table()
1199 {
1200 int p,lb=0;
1201 inst_count = 0;
1202
1203 if (const_list) {
1204 if (control) {
1205 lb = fwdlabel();
1206 gen_jmp(lb);
1207 // printf("\t.align\t2\n");
1208 }
1209 fwddef(const_list_label);
1210 control=0;
1211 for(p = const_list; p ; p = cadr(p)) {
1212 switch(car(p)) {
1213 case GVAR: printf("\t.word\t%s\n",((NMTBL *)caddr(p))->nm); break;
1214 case DCONST: case LCONST:
1215 case CONST: printf("\t.word\t%d\n",caddr(p)); break;
1216 case LABEL: printf("\t.word\t.LC%d\n",caddr(p)); break;
1217 case LVAR: printf("\t.word\t.LC%d+%d\n",
1218 car(caddr(p)),cadr(caddr(p))); break;
1219 default: error(-1);
1220 }
1221 }
1222 if (lb) {
1223 fwddef(lb); // control==1 now
1224 }
1225 prev_const_list_label=const_list_label;
1226 const_list_label = 0;
1227 }
1228 for(p = prev_const_list; p ; p = cadr(p)) {
1229 if (car(p)==LVAR) {
1230 free_glist2(caddr(p));
1231 }
1232 }
1233 free_glist3_a(prev_const_list);
1234 prev_const_list=const_list;
1235 const_list = 0;
1236 }
1237
1238
1239 extern void
1240 code_ptr_cache_def(int r, NMTBL *nptr)
1241 {
1242 //int label,disp;
1243 int disp;
1244 char *rrn = register_name(r);
1245 //disp = search_const(GVAR,(int)nptr,&label);
1246 printf("\tlqd\t%s, %d($sp)\n",rrn,(disp*4));
1247 }
1248
1249 #define mask8(d,bit) (d & (255 << bit))
1250
1251 /*
1252 mode CONST or other (CMP is Ok only in stage 1 result)
1253 *p1 stage 1 const
1254 *p2 stage 2 const
1255 *p3 stage 3 const
1256 return 0 ... require 4 stage
1257 1 ... positive result
1258 -1 ... negative result
1259
1260 */
1261 static int
1262 make_const(int c,int *p1,int *p2,int *p3,int mode)
1263 {
1264 int sign,im,jm,km;
1265 int min_stage = 4;
1266 int msign=0,mim=0,mjm,mkm;
1267 int id,jd,kd;
1268 int i,j,k;
1269 int d;
1270 if (c == (d = mask8(c,0))) {
1271 min_stage=1; min_stage=1; msign = 1;
1272 mim = d;mjm = 0;mkm = 0;
1273 } else if (mode!=CONST) {
1274 if (-c == (d = mask8(-c,0))) {
1275 min_stage=1; min_stage=1; msign = -1;
1276 mim = d;mjm = 0;mkm = 0;
1277 }
1278 } else {
1279 if (~c== (d = mask8(~c,0))) {
1280 min_stage=1; min_stage=1; msign = -1;
1281 mim = d;mjm = 0;mkm = 0;
1282 }
1283 }
1284 for(sign=1;sign>=-1;sign-=2) {
1285 if (min_stage==1) break;
1286 for(i=24;i>=0;i-=2) {
1287 jm = km = 0;
1288 if (sign>0) {
1289 if (c == (d = mask8(c,i))) {
1290 min_stage=1; min_stage=1; msign = 1;
1291 mim = d;mjm = 0;mkm = 0;
1292 break;
1293 }
1294 id = c - d;
1295 } else if (mode!=CONST) {
1296 if (-c == (d = mask8(-c,i))) {
1297 min_stage=1; min_stage=1; msign = -1;
1298 mim = d;mjm = 0;mkm = 0;
1299 break;
1300 }
1301 id = -c - d;
1302 } else {
1303 if (~c== (d = mask8(~c,i))) {
1304 min_stage=1; min_stage=1; msign = -1;
1305 mim = d;mjm = 0;mkm = 0;
1306 break;
1307 }
1308 id = ~c - d;
1309 }
1310 if (d==0) continue;
1311 im = d;
1312 if (min_stage<=2) continue;
1313 for(j=i-8;j>=0;j-=2) {
1314 km = 0;
1315 if (!(jm=mask8(id,j))) continue;
1316 jd = id - jm;
1317 if (jd==0) {
1318 min_stage=2; msign = sign;
1319 mim = im;mjm = jm;mkm = km;
1320 break;
1321 }
1322 if (min_stage<=3) continue;
1323 for(k=j-8;k>=0;k-=2) {
1324 if (!(km=mask8(jd,k))) continue;
1325 kd = jd - km;
1326 if (kd==0) {
1327 min_stage=3; msign = sign;
1328 mim = im;mjm = jm;mkm = km;
1329 break;
1330 }
1331 }
1332 }
1333 }
1334 }
1335 if (min_stage<=3) {
1336 *p1 = mim; *p2= mjm; *p3 = mkm;
1337 return msign;
1338 } else return 0;
1339 }
1340
1341 static int
1342 is_stage1_const(int c,int mode)
1343 {
1344 int sign,p1=0,p2=0,p3=0;
1345 sign = make_const(c,&p1,&p2,&p3,mode);
1346 return (c==0||(p1&&!p2&&!p3))?sign:0;
1347 }
1348
1349
1350 static void
1351 code_const0(int e2,int reg,char *opt)
1352 {
1353 char *crn,*add,*mov;
1354 int s,p1,p2,p3;
1355 //int label,disp;
1356 int disp;
1357
1358 use_int(reg);
1359 crn = register_name(reg);
1360 if ((s=make_const(e2,&p1,&p2,&p3,CONST))) {
1361 add = s>0?"a":"sfi";
1362 /************************************************************
1363 * ここでp1の値によって、命令が異なる...... *
1364 * il命令は-32768~32767 *
1365 * ila命令は262143まで *
1366 * それ以上はilhuとiohlを混合して使う。 *
1367 * example:15728639 *
1368 * 15728639/16^4 = 239 ilhu $4,239 *
1369 * 15728639%16^4 = 65535 iohl $4,65535 *
1370 ***********************************************************/
1371 mov = s>0?"il":"mvn";
1372 printf("\t%s\t%s, %d\n",mov,crn,p1);
1373 if (p2) printf("\t%s\t%s, %s, %d\n",add,crn,crn,p2);
1374 if (p3) printf("\t%s\t%s, %s, %d\n",add,crn,crn,p3);
1375 } else {
1376 //disp = search_const(CONST,e2,&label);
1377 printf("\tlqd\t%s, %d($sp)\n",crn,(disp*4));
1378 }
1379 }
1380
1381 extern void
1382 code_const(int e2,int reg) {
1383 code_const0(e2,reg,"");
1384 }
1385
1386 static void
1387 code_add(int reg,int offset,int r)
1388 {
1389 char *crn = register_name(reg);
1390 char *rrn = register_name(r);
1391 char *drn;
1392 int dreg;
1393 int s,p1,p2,p3;
1394 char *add;
1395 //int label,disp;
1396 int disp;
1397 if (offset==0) {
1398 if(r!=reg)
1399 printf("\tori\t%s, %s, 0\n",crn,rrn);
1400 } else if ((s=make_const(offset,&p1,&p2,&p3,0))) {
1401 add = s>0?"a":"sfi";
1402 printf("\t%s\t%s, %s, %d\n",add,crn,rrn,p1);
1403 if (p2) printf("\t%s\t%s, %s, %d\n",add,crn,crn,p2);
1404 if (p3) printf("\t%s\t%s, %s, %d\n",add,crn,crn,p3);
1405 } else {
1406 //disp = search_const(CONST,offset,&label);
1407 drn = register_name(dreg = get_register());
1408 printf("\tlqd\t%s, %d($sp)\n",drn,(disp*4));
1409 printf("\ta\t%s, %s, %s\n",crn,drn,rrn);
1410 free_register(dreg);
1411 }
1412 }
1413
1414
1415 static void
1416 code_ld(char *ld,int reg,int offset,int r,char *cext)
1417 {
1418 char *crn = register_name(reg);
1419 char *rrn = register_name(r);
1420 if (-1024<offset&&offset<1024) {
1421 printf("\t%s\t%s, [%s, %d]%s\n",ld,crn,rrn,offset,cext);
1422 } else {
1423 code_add(reg,offset,r);
1424 printf("\t%s\t%s, [%s, 0]%s\n",ld,crn,crn,cext);
1425 }
1426 }
1427
1428 static void
1429 code_ldf(char *ld,char *crn,int offset,int r,char *cext)
1430 {
1431 //char *rrn = register_name(r);
1432 char *orn;
1433 int reg;
1434 if (-1024<offset&&offset<1024) {
1435 printf("\t%s\t%s, %d(%s)\n",ld,crn,(offset*4),cext);
1436 } else {
1437 orn = register_name(reg=get_register());
1438 code_add(reg,offset,r);
1439 //printf("\t%s\t%s, [%s, 0]%s\n",ld,crn,orn,cext);
1440 printf("hoge\n");
1441 free_register(reg);
1442 }
1443 }
1444
1445
1446 #define cload(sz,sign) \
1447 (sz==1?(sign?"lqx":"lqa"):sz==SIZE_OF_SHORT?(sign?"lqx":"lqa"):"lqd")
1448
1449
1450 #define cext(sign,sz,reg)
1451
1452 static char *
1453 cext_at(int sz,int sign)
1454 {
1455 return ((sz==1&&!sign)?" @ zero_extendqisi2":"");
1456 }
1457
1458 void
1459 code_label(int labelno)
1460 {
1461 clear_ptr_cache();
1462 printf(".LC%d:\n",labelno);
1463 }
1464
1465 void
1466 code_gvar(int e1,int reg) {
1467 use_int(reg);
1468 code_add(reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1)));
1469 return;
1470 }
1471
1472 void
1473 code_rgvar(int e1,int reg) {
1474 use_int(reg);
1475 code_ld("lqd",reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1)),"");
1476 }
1477
1478 void
1479 code_crgvar(int e1,int reg,int sign,int sz){
1480 use_int(reg);
1481 code_ld(cload(sz,sign),reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1)),
1482 cext_at(sz,sign));
1483 cext(sign,sz,reg);
1484 }
1485
1486
1487 void
1488 code_register(int e2,int reg) {
1489 use_int(reg);
1490 // reg = e2
1491 if (reg!=e2) {
1492 printf("\tori\t%s, %s, 0\n",register_name(reg),register_name(e2));
1493 }
1494 }
1495
1496
1497 void
1498 code_rlvar(int e2,int reg) {
1499 use_int(reg);
1500 lvar_intro(e2);
1501 printf("\tlqd\t%s, ",register_name(reg));
1502 e2 *= 4;
1503 lvar(e2,"");
1504 }
1505
1506 extern void
1507 code_i2c(int reg)
1508 {
1509 }
1510
1511 extern void
1512 code_i2s(int reg)
1513 {
1514 }
1515
1516 extern void
1517 code_u2uc(int reg)
1518 {
1519 use_int(reg);
1520 printf("and\t%s, %s, #255\n",register_name(reg),register_name(reg));
1521 }
1522
1523 extern void
1524 code_u2us(int reg)
1525 {
1526 use_int(reg);
1527 printf("bic\t%s, %s, #16711680\n",register_name(reg),register_name(reg));
1528 printf("bic\t%s, %s, #-16777216\n",register_name(reg),register_name(reg));
1529 }
1530
1531 void
1532 code_crlvar(int e2,int reg,int sign,int sz) {
1533 use_int(reg);
1534 lvar_intro(e2);
1535 printf("\t%s\t%s, ",cload(sz,sign),register_name(reg));
1536 lvar(e2,cext_at(sz,sign));
1537 cext(sign,sz,reg);
1538 }
1539
1540 void
1541 code_fname(NMTBL *n,int reg) {
1542 int r;
1543 use_int(reg);
1544 r = get_ptr_cache(n);
1545 if(r!=reg) {
1546 printf("\tori\t%s, %s, 0\n",register_name(reg),register_name(r));
1547 }
1548 return;
1549 }
1550
1551 void
1552 code_label_value(int label,int reg) {
1553 //int lb,disp;
1554 use_int(reg);
1555 //disp = search_const(LABEL,label,&lb);
1556 printf("\tila\t%s,.LC%d\n",register_name(reg),label);
1557 return;
1558 }
1559
1560 void
1561 code_neg(int creg) {
1562 use_int(creg);
1563 printf("\trsb\t%s, %s, #0\n", register_name(creg), register_name(creg));
1564 }
1565
1566
1567 void
1568 code_not(int creg) {
1569 use_int(creg);
1570 printf("\tmvn\t%s, %s\n",
1571 register_name(creg), register_name(creg));
1572 }
1573
1574
1575 void
1576 code_lnot(int creg) {
1577 use_int(creg);
1578
1579 printf("\tcmp\t%s, #0\n", register_name(creg));
1580 printf("\tmovne\t%s, #0\n", register_name(creg));
1581 printf("\tmoveq\t%s, #1\n", register_name(creg));
1582 }
1583
1584 void
1585 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) {
1586 char *xrn,*drn;
1587 int xreg;
1588 if (car(e2)==REGISTER) {
1589 use_int(reg);
1590 code_add(cadr(e2),dir,cadr(e2));
1591 if (reg!=cadr(e2))
1592 code_register(cadr(e2),reg);
1593 return;
1594 }
1595 g_expr(e2);
1596 if (!is_int_reg(creg)) error(-1);
1597 xrn = register_name(xreg = creg);
1598 if (reg==USE_CREG) {
1599 reg=get_register(); if (!reg) error(-1);
1600 drn = register_name(reg);
1601 set_ireg(reg,0);
1602 } else {
1603 drn = register_name(reg);
1604 }
1605 // ldrb r2, [ip, #-1]! @ zero_extendqisi2
1606 // ??????offset???????????12bit!
1607 code_ld(cload(sz,sign),reg,0,xreg,cext_at(sz,sign));
1608 code_add(reg,dir,reg);
1609 code_ldf(cstore(sz),drn,0,xreg,sz==SIZE_OF_SHORT?" @ movhi":"");
1610 }
1611
1612
1613 void
1614 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) {
1615 char *xrn,*crn,*nrn;
1616 int nreg,xreg;
1617 if (car(e2)==REGISTER) {
1618 use_int(reg);
1619 code_register(cadr(e2),reg);
1620 code_add(cadr(e2),dir,cadr(e2));
1621 return;
1622 }
1623 g_expr(e2);
1624 if (!is_int_reg(creg)) error(-1);
1625 crn = register_name(xreg=creg);
1626 nreg=get_register(); if (!nreg) error(-1);
1627 nrn = register_name(nreg);
1628 if (reg==USE_CREG) {
1629 reg=get_register(); if (!reg) error(-1);
1630 xrn = register_name(reg);
1631 set_ireg(reg,0);
1632 } else {
1633 xrn = register_name(reg);
1634 }
1635 //_1: ldrb r4, [r0], #1 @ zero_extendqisi2 *buffer++
1636 code_ld(cload(sz,sign),reg,0,xreg,cext_at(sz,sign));
1637 code_add(nreg,dir,reg);
1638 code_ldf(cstore(sz),nrn,0,xreg,sz==SIZE_OF_SHORT?" @ movhi":"");
1639
1640 free_register(nreg);
1641 }
1642
1643
1644 void
1645 code_return(int creg) {
1646 //int label,disp;
1647 int disp;
1648 char *crn;
1649 use_int(creg);
1650 crn = register_name(creg);
1651
1652 //disp = search_const(LABEL,retcont,&label);
1653 printf("\tlqd\t%s, %d($sp)\n",crn,(disp*4));
1654 }
1655
1656 void
1657 code_environment(int creg) {
1658 /* save frame pointer */
1659 if (is_code(fnptr)) {
1660 use_int(creg);
1661 printf("\tmov\t%s, fp\n",register_name(creg));
1662 } else {
1663 //int disp,label;
1664 int disp;
1665 char *trn = register_name(REG_ip);
1666 use_int(creg);
1667 //disp = search_const(LVAR,glist2(lvar_offset_label,FUNC_LVAR(0)),&label);
1668 printf("\tlqa\t%s, %d\n",trn,disp);
1669 printf("\ta\t%s, fp, %s\n",register_name(creg),trn);
1670 }
1671 }
1672
1673 static int rexpr_bool(int e1, int reg);
1674 #if LONGLONG_CODE
1675 static int lrexpr_bool(int e1, int reg);
1676 #endif
1677
1678 void
1679 code_bool(int e1,int reg) {
1680 int e2,e3;
1681 char *xrn;
1682 if (rexpr_bool(e1, reg)) return;
1683 #if LONGLONG_CODE
1684 if (lrexpr_bool(e1, reg)) return;
1685 #endif
1686 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */
1687 if (use) {
1688 use_int(reg);
1689 xrn = register_name(reg);
1690 printf("\tmov\t%s, #0\n",xrn);
1691 gen_jmp(e3=fwdlabel());
1692 fwddef(e2);
1693 printf("\tmov\t%s, #1\n",xrn);
1694 fwddef(e3);
1695 } else {
1696 fwddef(e2);
1697 }
1698 }
1699
1700
1701 void
1702 code_cmp_crgvar(int e1,int reg,int sz,int label,int cond) {
1703 use_int(reg);
1704 code_ld(cload(sz,0),reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1)),
1705 cext_at(sz,0));
1706 cext(0,sz,r);
1707 printf("\tcmp\t%s, #0\n",register_name(reg));
1708 jcond(label,cond);
1709 }
1710
1711
1712 void
1713 code_cmp_crlvar(int e2,int reg, int sz,int label,int cond) {
1714 char *crn;
1715 use_int(reg);
1716 crn = register_name(reg);
1717 lvar_intro(e2);
1718 printf("\t%s\t%s, ",cload(sz,0),crn);
1719 lvar(e2,cext_at(sz,0));
1720 cext(0,sz,reg);
1721 code_cmp_register(reg,label,cond);
1722 }
1723
1724
1725 void
1726 code_cmp_rgvar(int e1,int reg,int label,int cond) {
1727 use_int(reg);
1728 code_ld("lqd",reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1)),"");
1729 code_cmp_register(reg,label,cond);
1730 }
1731
1732
1733 void
1734 code_cmp_rlvar(int e2,int reg,int label,int cond) {
1735 char *crn;
1736 use_int(reg);
1737 crn = register_name(reg);
1738 lvar_intro(e2);
1739 printf("\tlqd\t%s, ",crn);
1740 e2 *= 4;
1741 lvar(e2,"");
1742 code_cmp_register(reg,label,cond);
1743 }
1744
1745
1746 void
1747 code_cmp_register(int e2,int label,int cond) {
1748 use_int(e2);
1749 printf("\tcmp\t%s, #0\n",register_name(e2));
1750 jcond(label,cond);
1751 }
1752
1753
1754 void
1755 code_string(int e1,int creg)
1756 {
1757 char *s,*crn;
1758 //int lb,label;
1759 int lb;
1760 printf("creg:%d\n",creg);
1761 NMTBL *n = (NMTBL *)cadr(e1);
1762 if ((lb=attr_value(n,LABEL))) {
1763 // already defined
1764 return code_label_value(lb,creg) ;
1765 //return code_label_value(lb,35) ;
1766 }
1767
1768 use_int(creg);
1769 crn = register_name(creg);
1770
1771 s=n->nm;
1772 lb = emit_string_label();
1773 ascii(s);
1774 text_mode(2);
1775
1776 //disp = search_const(LABEL,lb,&label);
1777 printf("\tila\t%s, .LC%d\n",crn,lb);
1778 set_attr(n,LABEL,lb);
1779 }
1780
1781 #define MAX_COPY_LEN 20
1782
1783 void
1784 emit_copy(int from,int to,int length,int offset,int value,int det)
1785 {
1786 char *frn;
1787 char *trn;
1788 char *drn;
1789 char *memmove = "memmove";
1790 int dreg = REG_ip;
1791
1792 drn = register_name(dreg);
1793 use_int(from);
1794 use_int(to);
1795 frn = register_name(from);
1796 trn = register_name(to);
1797
1798 /* length <0 means upward direction copy */
1799 switch (length) {
1800 case 0: break;
1801 case 1: case -1:
1802 printf("\tlqd\t%s, %d(%s)\n",drn,(offset*4),trn);
1803 printf("\tstqd\t%s,%d(%s)\n",drn,(offset*4),trn);
1804 break;
1805 case 2: case -2:
1806 printf("\tlqx\t%s, [%s,#%d]\n",drn,frn,offset);
1807 printf("\tstqx\t%s, [%s,#%d]\n",drn,trn,offset);
1808 break;
1809 case 4: case -4:
1810 printf("\tlqa\t%s, [%s,#%d]\n",drn,frn,offset);
1811 printf("\tstqa\t%s, [%s,#%d]\n",drn,trn,offset);
1812 break;
1813 default:
1814 if (length <0) {
1815 if (length > -MAX_COPY_LEN) {
1816 for(;length<=-4;length+=4,offset-=4)
1817 emit_copy(from,to,-4,offset-4,0,det);
1818 for(;length<=-2;length+=2,offset-=2)
1819 emit_copy(from,to,-2,offset-2,0,det);
1820 if(length<0)
1821 emit_copy(from,to,length,offset-1,0,det);
1822 break;
1823 }
1824 } else if (length <=MAX_COPY_LEN) {
1825 for(;length>=4;length-=4,offset+=4)
1826 emit_copy(from,to,4,offset,0,det);
1827 for(;length>=2;length-=2,offset+=2)
1828 emit_copy(from,to,2,offset,0,det);
1829 if(length>0)
1830 emit_copy(from,to,length,offset,0,det);
1831 break;
1832 }
1833 clear_ptr_cache();
1834 code_save_stacks();
1835 parallel_rassign(list3(1,list3(2,0,from),to));
1836 code_const(length>0?length:-length,3);
1837 /* overlap must be allowed */
1838 // offset have to be ignored */
1839 printf("\thbra\t%s\n",memmove);
1840 extern_define(memmove,0,FUNCTION,1);
1841 set_ireg(RET_REGISTER,0);
1842 if (creg!=to) {
1843 free_register(to); to = creg;
1844 }
1845 break;
1846 }
1847 if (value) {
1848 /* creg must point top of the destination data */
1849 /* this code is necessary for the value of assignment or function call */
1850 /* otherwise we don't need this */
1851 if(creg!=to) {
1852 free_register(creg); creg=to; ireg=to;
1853 }
1854 }
1855 // free_register(dreg);
1856 }
1857
1858 int
1859 push_struct(int e4,int t,int arg)
1860 {
1861 int length,len0,count;
1862 int dreg = -1,sreg; char *drn,*crn,*srn;
1863 int arg_disp = cadr(arg);
1864 int on_register,arg_reg;
1865 g_expr(e4);
1866 if (!is_int_reg(creg)) error(-1);
1867 len0=length=size(t);
1868 if(length%SIZE_OF_INT) {
1869 length += SIZE_OF_INT - (length%SIZE_OF_INT);
1870 }
1871 crn = register_name(creg);
1872 on_register = 0;
1873 // arg_reg = 1-CALLER_ARG(arg_disp-ARG_LVAR_OFFSET)/SIZE_OF_INT;
1874 arg_reg = (arg_disp-ARG_LVAR_OFFSET)/SIZE_OF_INT + 1;
1875 while (length>0 &&
1876 arg_disp>=ARG_LVAR_OFFSET &&
1877 CALLER_ARG(arg_disp-ARG_LVAR_OFFSET)<0) {
1878 /* some part will be on registers */
1879 on_register ++;
1880 length-=SIZE_OF_INT; arg_disp+= SIZE_OF_INT;
1881 }
1882 if (length>0) {
1883 dreg = get_register(); if (!dreg) error(-1);
1884 drn = register_name(dreg);
1885 if (length<MAX_COPY_LEN) {
1886 sreg = get_register(); if (!sreg) error(-1);
1887 srn = register_name(sreg);
1888 code_lvar(arg_disp,dreg);
1889 for(count=0;count<length;count+=SIZE_OF_INT) {
1890 printf("\tlqd\t%s, [%s, #%d]\n",srn,crn,count+on_register*SIZE_OF_INT);
1891 printf("\tstr\t%s, [%s, #%d]\n",srn,drn,count);
1892 }
1893 free_register(sreg);
1894 if (on_register) {
1895 if (creg<=MAX_INPUT_REGISTER_VAR) {
1896 code_register(creg,REG_ip);
1897 crn = register_name(REG_ip);
1898 }
1899 }
1900 } else {
1901 code_lvar(arg_disp,dreg);
1902 /* downward direction copy */
1903 if (on_register) {
1904 sreg = new_lvar(SIZE_OF_INT);
1905 code_assign_lvar(sreg*4,creg,0);
1906 code_add(creg,on_register*SIZE_OF_INT,creg);
1907 emit_copy(creg,dreg,length,0,0,1);
1908 code_rlvar(sreg,REG_ip);
1909 crn = register_name(REG_ip);
1910 free_lvar(sreg);
1911 } else {
1912 emit_copy(creg,dreg,length,0,0,1);
1913 }
1914 }
1915 if (dreg!=-1) free_register(dreg);
1916 }
1917 for (count=0,arg_reg; on_register-->0; arg_reg++,count+=SIZE_OF_INT) {
1918 // len0 = (len0>2)?0:len0;
1919 printf("\t%s\t%s, [%s, #%d]\n", cload(0,0),
1920 register_name(arg_reg), crn,count);
1921 use_input_reg(arg_reg,1);
1922 }
1923 return length/SIZE_OF_INT;
1924 }
1925
1926 static void
1927 set_ireg(int reg,int mode)
1928 {
1929 if (!is_int_reg(reg)) error(-1);
1930 if (reg!=creg) {
1931 clear_ptr_cache_reg(reg);
1932 if (ireg && reg!=ireg ) {
1933 free_register(ireg);
1934 if (mode) {
1935 printf("\tori\t%s, %s, 0\n",register_name(reg),register_name(ireg));
1936 }
1937 }
1938 free_register(creg);
1939 if (creg==lreg) lreg=0;
1940 regs[reg]=USING_REG;
1941 }
1942 creg = ireg = reg;
1943 }
1944
1945 static void
1946 set_freg(int reg,int mode)
1947 {
1948 if (!is_float_reg(reg)) error(-1);
1949 if (reg!=creg) {
1950 if (freg && reg!=freg) {
1951 free_register(freg);
1952 if (mode) {
1953 printf("\t%s\t%s, %s\n",
1954 "mvfs"
1955 register_name(reg),register_name(freg));
1956 }
1957 }
1958 // if (creg!=ireg) free_register(creg);
1959 regs[reg]=USING_REG;
1960 }
1961 creg = freg = reg;
1962 }
1963
1964 #if LONGLONG_CODE||FLOAT_CODE
1965 static void
1966 set_lreg0(int reg,int mode)
1967 {
1968 if (reg!=creg) {
1969 if (lreg && reg!=lreg) {
1970 if (mode) {
1971 lmove(reg,lreg);
1972 }
1973 free_register(lreg);
1974 }
1975 if (creg!=lreg) {
1976 free_register(creg);
1977 if (creg==ireg) ireg = 0;
1978 }
1979 regs[reg]=USING_REG;
1980 clear_ptr_cache_reg(reg);
1981 regs[reg]=USING_REG;
1982 clear_ptr_cache_reg(reg);
1983 regs[reg]=USING_REG;
1984 }
1985 creg = lreg = reg;
1986 }
1987 #endif
1988
1989 #if LONGLONG_CODE
1990 static void
1991 set_lreg(int reg,int mode)
1992 {
1993 if (!is_longlong_reg(reg)) error(-1);
1994 set_lreg0(reg,mode);
1995 }
1996 #endif
1997
1998 #if FLOAT_CODE
1999 static void
2000 set_dreg(int reg,int mode)
2001 {
2002 return set_ireg(reg,mode);
2003 }
2004
2005 static void
2006 set_lreg_operand(int reg,int mode)
2007 {
2008 // save_stack,clear_ptr_cache is assumed
2009 if (!is_longlong_reg(reg)) { error(-1); return; }
2010 if (mode) {
2011 lmove(LREGISTER_OPERAND,reg);
2012 }
2013 }
2014
2015 static void
2016 set_dreg_operand(int reg,int mode)
2017 {
2018 set_lreg_operand(reg,mode);
2019 }
2020
2021
2022 #endif
2023
2024 void
2025 use_reg(int arg)
2026 {
2027 // printf("## use reg %d\n",arg);
2028 if (arg<0||arg> REGS_MAX)
2029 error(-1);
2030 clear_ptr_cache_reg(arg);
2031 regs[arg]=USING_REG;
2032 if (is_longlong_reg(arg)) {
2033 clear_ptr_cache_reg(arg);
2034 regs[arg]=USING_REG;
2035 clear_ptr_cache_reg(arg);
2036 regs[arg]=USING_REG;
2037 } else if (is_double_reg(arg)) {
2038 clear_ptr_cache_reg(arg);
2039 regs[arg]=USING_REG;
2040 clear_ptr_cache_reg(arg);
2041 regs[arg]=USING_REG;
2042 }
2043 }
2044
2045 void
2046 code_save_input_registers(int dots)
2047 {
2048 int args;
2049 NMTBL *n;
2050 int reg;
2051 int tag;
2052 /* fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); */
2053 int offset = 0;
2054 int reg_var = 0;
2055 int len;
2056 arg_on_register = 0;
2057
2058 for(args = fnptr->dsp;args;args = cadr(args)) {
2059 n = (NMTBL *)caddr(args);
2060 tag = n->sc;
2061 reg = n->dsp;
2062 if (!n||n==&null_nptr) error(REG_ERR);
2063 if (reg_var<MAX_INPUT_REGISTER_VAR) {
2064 n->dsp = offset;
2065 n->sc = LVAR;
2066 len = size(n->ty); len = round4(len);
2067 for(;len>0 && reg_var<MAX_INPUT_REGISTER_VAR;len-=SIZE_OF_INT) {
2068 reg_var++;
2069 g_expr_u(assign_expr0(list3(LVAR,offset,0),
2070 list3(REGISTER,reg_var,0),INT,INT));
2071 arg_on_register += SIZE_OF_INT;
2072 free_register(reg);
2073 offset += SIZE_OF_INT;
2074 }
2075 }
2076 }
2077 if (dots) {
2078 while ((reg = get_input_register_var(reg_var,0,0))) {
2079 g_expr_u(assign_expr0(
2080 list3(LVAR,offset,0),reg,INT,INT));
2081 offset+=SIZE_OF_INT;
2082 reg_var++;
2083 arg_on_register += SIZE_OF_INT;
2084 }
2085 }
2086 my_func_args = offset;
2087 }
2088
2089 int
2090 not_simple_p(int e3)
2091 {
2092 switch(e3) {
2093 case FUNCTION: case CONV: case STASS: case ALLOCA:
2094 case DIV : case UDIV : case MOD : case UMOD :
2095 case LDIV: case LUDIV: case LMOD: case LUMOD:
2096 case LMUL: case LUMUL:
2097 case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT:
2098 case DDIV: case DADD: case DSUB: case DMUL: case DMINUS:
2099 case DPOSTINC : case DPREINC : case DASSOP :
2100 case DOP+LT : case DOP+LE : case DOP+GT : case DOP+GE :
2101 case DOP+EQ : case DOP+NEQ:
2102 case RBIT_FIELD: case BASS: case BASSOP: case LCALL:
2103 case INLINE:
2104 return 1;
2105 }
2106 return 0;
2107 }
2108
2109 int
2110 simple_arg(int e3)
2111 {
2112 return !contains_p(e3,not_simple_p);
2113 }
2114
2115 static int
2116 caller_arg_offset_v(int arg)
2117 {
2118 return ARG_LVAR_OFFSET+arg*SIZE_OF_INT;
2119 }
2120
2121 /*
2122 Mark argument register is used. This is too complex.
2123 There must be an easy way.
2124 */
2125
2126 static void
2127 use_input_reg(int reg,int mode)
2128 {
2129 if (is_int_reg(reg)) {
2130 if (ireg&&reg == ireg) {
2131 if (creg==ireg) creg = 0;
2132 ireg = 0;
2133 }
2134 if (lreg) {
2135 if (lreg==reg) {
2136 regs[lreg]=0;
2137 if (lreg>reg&&
2138 (regs[lreg]==USING_REG||
2139 regs[lreg]==USING_DREG))
2140 {
2141 free_register(lreg);
2142 }
2143 if (creg==lreg) creg = ireg;
2144 free_register(lreg);
2145 lreg = 0;
2146 } else if (lreg==reg) {
2147 regs[lreg]=0;
2148 if (lreg>reg && (
2149 (regs[lreg]==USING_REG) ||
2150 (regs[lreg]==USING_DREG) ))
2151 {
2152 free_register(lreg);
2153 }
2154 if (creg==lreg) creg = ireg;
2155 free_register(lreg);
2156 lreg = 0;
2157 }
2158 }
2159 } else if (is_longlong_reg(reg)) {
2160 use_input_reg(reg,0);
2161 use_input_reg(reg,0);
2162 } else if (is_double_reg(reg)) {
2163 use_input_reg(reg,0);
2164 use_input_reg(reg,0);
2165 } else if (is_float_reg(reg)) {
2166 if (freg&&reg == freg) {
2167 if (creg==freg) creg = ireg;
2168 freg = 0;
2169 }
2170 }
2171 if (mode) use_reg(reg);
2172 }
2173
2174 static void
2175 code_assign_input_float_int(int e1,int e2) {
2176 #if FLOAT_CODE
2177 int r,tmp=-1;
2178 float f;
2179 char *frn;
2180 // e1 = e2;
2181 if (car(e1)!=REGISTER) { error(-1); return; }
2182 frn = register_name(r=cadr(e1));
2183 switch(car(e2)) {
2184 case FCONST:
2185 f = dcadr(e2);
2186 code_const(*((int*)&f),r);
2187 break;
2188 case FRGVAR:
2189 code_rgvar(e2,r);
2190 break;
2191 case FRLVAR:
2192 code_rlvar(cadr(e2),r);
2193 break;
2194 default:
2195 g_expr(rvalue_t(e2,FLOAT));
2196 case FREGISTER:
2197 tmp = new_lvar(SIZE_OF_INT);
2198 code_dassign_lvar(tmp, (car(e2)==FREGISTER)?cadr(e2):freg,0);
2199 code_rlvar(tmp,r);
2200 if (tmp!=-1) free_lvar(tmp);
2201 }
2202 #endif
2203 }
2204
2205 static void
2206 code_assign_input_double_long(int e1,int e2) {
2207 #if FLOAT_CODE
2208 int r,tmp=-1,reg=0;
2209 double value;
2210 // e1 = e2;
2211 if (car(e1)!=LREGISTER) { error(-1); return; }
2212 r=cadr(e1);
2213 switch(car(e2)) {
2214 case DCONST:
2215 value = dcadr(e2);
2216 dconst(r,r,value);
2217 break;
2218 case DRGVAR:
2219 code_lrgvar(e2,r);
2220 break;
2221 case DRLVAR:
2222 code_lrlvar(cadr(e2),r);
2223 break;
2224 default:
2225 g_expr(rvalue_t(e2,DOUBLE));
2226 reg = freg;
2227 case DREGISTER:
2228 if (car(e2)==DREGISTER) reg = cadr(e2);
2229 printf("\tstfd\t%s, [sp, #-8]!\n",register_name(reg));
2230 printf("\tldmfd\tsp!, {%s, %s}\n",lregister_name_low(r),lregister_name_high(r));
2231 }
2232 if (tmp!=-1) free_lvar(tmp);
2233 #endif
2234 }
2235
2236 static int
2237 compute_complex_arg(int e3,int reg_arg_list,int arg) {
2238 int t=caddr(e3);
2239 int e4 = car(e3);
2240 reg_arg_list = list2(arg,reg_arg_list);
2241 if (car(arg)==REGISTER||car(arg)==DREGISTER||
2242 car(arg)==FREGISTER||car(arg)==LREGISTER)
2243 use_input_reg(cadr(arg),1);
2244 if (t==FLOAT&&car(arg)==REGISTER)
2245 code_assign_input_float_int(arg, e4);
2246 else if (t==DOUBLE&&car(arg)==LREGISTER)
2247 code_assign_input_double_long(arg, e4);
2248 else
2249 g_expr_u(assign_expr0(arg,e4,t,t));
2250 car(e3) = arg;
2251 return reg_arg_list;
2252 }
2253
2254 static void
2255 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
2256 int nargs=0,reg_arg=0,freg_arg=0;
2257 int t=caddr(e3);
2258 if(scalar(t)) {
2259 nargs ++ ; reg_arg++; freg_arg++;
2260 } else if (t==LONGLONG||t==ULONGLONG||t==DOUBLE) {
2261 nargs ++ ; reg_arg++;
2262 nargs ++ ; reg_arg++;
2263 } else if (t==FLOAT) {
2264 reg_arg ++ ; freg_arg++;
2265 nargs += size(t)/SIZE_OF_INT;
2266 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
2267 nargs += round4(size(t))/SIZE_OF_INT;
2268 } else {
2269 error(TYERR);
2270 nargs ++ ;
2271 }
2272 *pnargs += nargs;
2273 *preg_arg += reg_arg;
2274 *pfreg_arg += freg_arg;
2275 }
2276
2277 #define AS_SAVE 1
2278 #define AS_ARG 0
2279
2280 static int
2281 get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg)
2282 {
2283 if(scalar(t)) {
2284 if (mode==AS_SAVE) {
2285 return get_register_var(0);
2286 } else if (reg_arg+1>MAX_INPUT_REGISTER_VAR) {
2287 return list3(LVAR,caller_arg_offset_v(nargs),0);
2288 } else
2289 return get_input_register_var(reg_arg,0,0);
2290 } else if (t==LONGLONG||t==ULONGLONG) {
2291 if (mode==AS_SAVE) {
2292 return get_lregister_var(0);
2293 } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) {
2294 return list3(LVAR,caller_arg_offset_v(nargs),0);
2295 } else
2296 return get_input_lregister_var(reg_arg,0,0);
2297 } else if (t==FLOAT) {
2298 if (mode==AS_SAVE) {
2299 return get_dregister_var(0,0);
2300 } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
2301 return list3(LVAR,caller_arg_offset_v(nargs),0);
2302 } else
2303 return get_input_dregister_var(freg_arg,0,0,0);
2304 } else if (t==DOUBLE) {
2305 if (mode==AS_SAVE) {
2306 return get_dregister_var(0,1);
2307 } else if (reg_arg+1>=MAX_INPUT_DREGISTER_VAR) {
2308 return list3(LVAR,caller_arg_offset_v(nargs),0);
2309 } else
2310 return get_input_dregister_var(reg_arg,0,0,1);
2311 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
2312 if (mode==AS_SAVE) {
2313 return get_register_var(0);
2314 } else
2315 return list3(LVAR,caller_arg_offset_v(nargs),0);
2316 } else {
2317 error(-1);
2318 return get_register_var(0);
2319 }
2320 }
2321
2322 static void
2323 code_call(int e2,NMTBL *fn,int jmp)
2324 {
2325 if (car(e2) == FNAME) {
2326 printf("\tbrsl\t$lr,%s\n",fn->nm);
2327 } else {
2328 printf("\tmov\tlr, pc\n");
2329 printf("\tmov\tpc, %s\n",register_name(cadr(jmp)));
2330 }
2331 }
2332
2333 int
2334 function(int e1)
2335 {
2336 int e2,e3,e4,e5,nargs,t;
2337 int arg,reg_arg,freg_arg,arg_assign;
2338 int dots;
2339 int reg_arg_list=0,ret_type,special_lvar;
2340 NMTBL *fn = 0;
2341 int jmp = 0;
2342 int complex_;
2343 int pnargs,preg_arg,pfreg_arg;
2344 int stargs,i;
2345 int half_register = 0;
2346
2347 special_lvar = -1;
2348 ret_type = function_type(cadddr(e1),&dots);
2349 if (caddr(cadddr(e1))==0) dots=1;
2350
2351 arg_assign = 0;
2352 e2 = cadr(e1);
2353 if (car(e2) == FNAME) {
2354 fn=(NMTBL *)cadr(e2);
2355 } else {
2356 if (car(e2)==INDIRECT) e2=cadr(e2); // (*func)(i) case
2357 // jmp = get_register_var(0);
2358 jmp = list2(REGISTER,REG_ip);
2359 if (!simple_arg(e2)) {
2360 e3=get_register_var(0);
2361 reg_arg_list = list2(e3,reg_arg_list);
2362 g_expr_u(assign_expr0(e3,e2,INT,INT));
2363 e2=e3;
2364 }
2365 reg_arg_list = list2(jmp,reg_arg_list);
2366 arg_assign = list2(assign_expr0(jmp,e2,INT,INT),arg_assign);
2367 }
2368 /* First we execute complex argument to avoid interaction with
2369 input variables. Remain the last complex argument in complex_. */
2370 stargs = 0;
2371 complex_ = 0;
2372 nargs = reg_arg = freg_arg = 0;
2373 pnargs = preg_arg = pfreg_arg = 0;
2374 for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {
2375 t=caddr(e3);
2376 if (reg_arg==3 && (t==DOUBLE||t==LONGLONG||t==ULONGLONG)) {
2377 half_register=1;
2378 }
2379 if ((e5= !simple_arg(car(e3)))) {
2380 if (complex_) {
2381 arg = get_input_arg(caddr(complex_),AS_SAVE,
2382 pnargs,preg_arg,pfreg_arg);
2383 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
2384 }
2385 // memorise last complex arg parameter
2386 pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg;
2387 complex_ = e3;
2388 }
2389 if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
2390 // The struct should be pushed after complex arguments.
2391 if (e5) { // compute address only, complex_ is me now. Clear it.
2392 complex_ = 0;
2393 e4 = car(e3);
2394 if (car(e4)!=RSTRUCT) error(-1);
2395 if (!simple_arg(cadr(e4))) {
2396 // Calculate complex struct address here.
2397 // If simple, leave it.
2398 arg = get_register_var(0);
2399 g_expr_u(assign_expr0(arg,list2(ADDRESS,car(e3)),INT,INT));
2400 car(e3)=arg;
2401 reg_arg_list = list2(arg,reg_arg_list);
2402 if (car(arg)==REGISTER) use_input_reg(cadr(arg),1);
2403 else car(e3) = rvalue_t(arg,INT);
2404 }
2405 }
2406 stargs = list4(e3,stargs,nargs,reg_arg);
2407 }
2408 increment_function_arg(e3,&nargs,&reg_arg,&freg_arg);
2409 }
2410
2411 /* now all input register vars are free */
2412 code_save_stacks();
2413 // set_lreg(LREG_LREGISTER,0);
2414 set_freg(FREG_FREGISTER,0);
2415 set_ireg(CREG_REGISTER,0);
2416
2417 // Struct arguments need emit_copy. it destructs 3 input registers.
2418 // But it returns no value on a register. So calculate it here.
2419 // We cannot do this in the previous loop, because the copied struct may be
2420 // override by other complex arguments. But before this we have to check
2421 // complex_.
2422
2423 if (stargs) {
2424 if (complex_) {
2425 arg = get_input_arg(caddr(complex_),AS_SAVE,
2426 pnargs,preg_arg,pfreg_arg);
2427 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
2428 }
2429 for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) {
2430 e3 = car(stargs);
2431 e4 = car(e3);
2432 t = caddr(e3);
2433 arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0);
2434 push_struct(e4,t,arg);
2435 car(e3)=0; // done
2436 if (car(arg)==REGISTER) // wrong?
2437 use_input_reg(cadr(arg),1);
2438 }
2439 } else {
2440 // last complex argument can use input register
2441 if (complex_) {
2442 arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg);
2443 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
2444 if (car(arg)!=LVAR) use_input_reg(cadr(arg),1);
2445 car(complex_) = 0; // done.
2446 if (car(arg)==REGISTER)
2447 use_input_reg(cadr(arg),1);
2448 }
2449 }
2450
2451 nargs = reg_arg = freg_arg = 0;
2452 // calc stack arguments first, it may requires extra registers,
2453 // and we can still use input registers now.
2454 for (e3 = e1; e3;
2455 increment_function_arg(e3,&nargs,&reg_arg,&freg_arg),
2456 e3 = cadr(e3)) {
2457 if (!(e4=car(e3))) continue;
2458 t=caddr(e3);
2459 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
2460 if (car(arg)!=LVAR) continue;
2461 g_expr_u(assign_expr0(arg,e4,t,t));
2462 car(e3)=0; // done
2463 }
2464 if (half_register) {
2465 // half register case writes *(sp-1) but it will be Ok.
2466 if (max_func_args<4) max_func_args=4;
2467 g_expr_u(assign_expr0(list3(REGISTER,4,0),
2468 list3(LVAR,caller_arg_offset_v(3),0),INT,INT));
2469 use_input_reg(4,1);
2470 }
2471 nargs = reg_arg = freg_arg = 0;
2472 for (e3 = e1; e3;
2473 increment_function_arg(e3,&nargs,&reg_arg,&freg_arg),
2474 e3 = cadr(e3)) {
2475 if (!(e4=car(e3))) continue;
2476 t=caddr(e3);
2477 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
2478 if(scalar(t)) {
2479 reg_arg_list = list2(arg,reg_arg_list);
2480 /* protect from input register free */
2481 if (car(arg)==REGISTER)
2482 use_input_reg(cadr(arg),1);
2483 g_expr_u(assign_expr0(arg,e4,t,t));
2484 } else if (t==LONGLONG||t==ULONGLONG) {
2485 if (car(arg)==LREGISTER) {
2486 use_input_reg(cadr(arg),1);
2487 }
2488 reg_arg_list = list2(arg,reg_arg_list);
2489 g_expr_u(assign_expr0(arg,e4,t,t));
2490 } else if (t==DOUBLE) {
2491 reg_arg_list = list2(arg,reg_arg_list);
2492 if (car(arg)==LREGISTER) {
2493 use_input_reg(cadr(arg),1);
2494 code_assign_input_double_long(arg, e4);
2495 } else {
2496 g_expr_u(assign_expr0(arg,e4,t,t));
2497 }
2498 } else if (t==FLOAT) {
2499 reg_arg_list = list2(arg,reg_arg_list);
2500 if (car(arg)==REGISTER) {
2501 use_input_reg(cadr(arg),1);/* protect from input register free */
2502 code_assign_input_float_int(arg, e4);
2503 } else {
2504 g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */
2505 }
2506 }
2507 // structs are finished
2508 }
2509 if (max_func_args<nargs) max_func_args=nargs;
2510 for(;arg_assign;arg_assign=cadr(arg_assign)) {
2511 g_expr_u(car(arg_assign));
2512 }
2513 clear_ptr_cache();
2514 code_call(e2,fn,jmp);
2515 for(;reg_arg_list;reg_arg_list=cadr(reg_arg_list)) {
2516 arg = car(reg_arg_list);
2517 if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER
2518 ||car(arg)==LREGISTER)
2519 free_register(cadr(arg));
2520 else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg));
2521 }
2522 for(i=1;i<MAX_INPUT_REGISTER_VAR;i++) {
2523 free_register(i);
2524 }
2525 if (ret_type==DOUBLE) {
2526 #if FLOAT_CODE
2527 set_dreg(RET_DREGISTER,0);
2528 use_reg(RET_DREGISTER);
2529 #endif
2530 } else if (ret_type==FLOAT) {
2531 #if FLOAT_CODE
2532 set_freg(RET_FREGISTER,0);
2533 #endif
2534 } else if (ret_type==ULONGLONG||ret_type==LONGLONG) {
2535 #if LONGLONG_CODE
2536 set_lreg(RET_LREGISTER,0);
2537 use_reg(RET_LREGISTER);
2538 #endif
2539 } else if (ret_type==VOID) {
2540 } else {
2541 set_ireg(RET_REGISTER,0);
2542 }
2543 return ret_type;
2544 }
2545
2546 void
2547 code_alloca(int e1,int reg)
2548 {
2549 char *crn;
2550
2551 g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15)));
2552 use_int(reg);
2553 crn = register_name(reg);
2554 printf("\trsb\tsp, %s, sp\n",crn);
2555 if (!max_func_arg_label) max_func_arg_label = fwdlabel();
2556 code_label_value(max_func_arg_label ,REG_ip);
2557 printf("\ta\t%s, sp, ip\n",crn);
2558 }
2559
2560 void
2561 code_frame_pointer(int e3) {
2562 use_int(e3);
2563 printf("\tmov\tfp, %s\n",register_name(e3));
2564 }
2565
2566 int
2567 code_frame_pointer_register()
2568 {
2569 return list2(REGISTER,REG_fp);
2570 }
2571
2572 void
2573 code_fix_frame_pointer(int env) {
2574 char *trn;
2575 //int disp,label;
2576 //int label;
2577 int disp;
2578 if (is_function(fnptr) && ! env) {
2579 trn = register_name(REG_ip);
2580 //disp = search_const(LVAR,glist2(lvar_offset_label,FUNC_LVAR(0)),&label);
2581 printf("\tlqd\t%s, %d($sp)\n",trn,disp);
2582 printf("\ta\tfp, fp, %s\n",trn);
2583 }
2584 }
2585
2586 static void
2587 code_unfix_frame_pointer()
2588 {
2589 char *trn;
2590 //int disp,label;
2591 int disp;
2592
2593 trn = register_name(REG_ip);
2594 //disp = search_const(LVAR,glist2(lvar_offset_label,FUNC_LVAR(0)),&label);
2595 printf("\tlqd\t%s, %d($sp)\n",trn,disp);
2596 printf("\tsf\tfp, fp, %s\n",trn);
2597 }
2598
2599
2600 void
2601 code_jmp(char *s) {
2602 // jump to continuation means use all register variable
2603 max_reg_var = REG_VAR_MAX-REG_VAR_MIN;
2604 max_reg_var = FREG_VAR_MAX-FREG_VAR_MIN;
2605 printf("\tbr\t%s\n",s);
2606 control=0;
2607 }
2608
2609 void
2610 code_indirect_jmp(int e2) {
2611 // jump to continuation means use all register variable
2612 max_reg_var = REG_VAR_MAX-REG_VAR_MIN;
2613 max_reg_var = FREG_VAR_MAX-FREG_VAR_MIN;
2614 use_int(e2);
2615 printf("\tmov\tpc, %s @ indirect jump\n",register_name(e2)); // ?!
2616 control=0;
2617 }
2618
2619 void
2620 code_rindirect(int e1, int reg,int offset, int sign,int sz)
2621 {
2622 int lreg;
2623 g_expr(e1);
2624 if (!is_int_reg(creg)) error(-1);
2625 lreg = creg;
2626 use_int(reg);
2627 code_ld(cload(sz,sign),reg,offset,lreg,cext_at(sz,sign));
2628 cext(sign,sz,reg);
2629 }
2630
2631 #if FLOAT_CODE
2632 int
2633 code_drindirect(int e1, int reg,int offset, int d)
2634 {
2635 int xreg;
2636 g_expr(e1);
2637 if (!is_int_reg(creg)) error(-1);
2638 xreg = creg;
2639 use_float(d,reg);
2640 code_ldf(d?"ldfd":"ldfs",register_name(reg),offset,xreg,"");
2641 return d?DOUBLE:FLOAT;
2642 }
2643 #endif
2644
2645 #if LONGLONG_CODE||FLOAT_CODE
2646
2647 static void
2648 lload(int creg,int reg,int offset)
2649 {
2650 char *crn=register_name(creg);
2651 #if ENDIAN_L==0
2652 if (creg!=reg) {
2653 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_low(reg),crn,offset);
2654 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_high(reg),crn,offset+SIZE_OF_INT);
2655 } else {
2656 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_high(reg),crn,offset+SIZE_OF_INT);
2657 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_low(reg),crn,offset);
2658 }
2659 #else
2660 if (creg!=reg) {
2661 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_low(reg),crn,offset+SIZE_OF_INT);
2662 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_high(reg),crn,offset);
2663 } else {
2664 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_high(reg),crn,offset);
2665 printf("\tldr\t%s, [%s, #%d]\n",lregister_name_low(reg),crn,offset+SIZE_OF_INT);
2666 }
2667 #endif
2668 }
2669
2670
2671 static void
2672 lmove(int to,int from)
2673 {
2674 int l;
2675 l = list3(to,0,from);
2676 l = list3(to,l,from);
2677 parallel_rassign(l);
2678 }
2679
2680 static void
2681 set_operands(int r0,int r1,int r2,int r3)
2682 {
2683 int l;
2684 l = list3(DREGISTER_OPERAND_L,0,r0);
2685 l = list3(DREGISTER_OPERAND_H,l,r1);
2686 l = list3(DREGISTER_OPERAND_1_L,l,r2);
2687 l = list3(DREGISTER_OPERAND_1_H,l,r3);
2688 parallel_rassign(l);
2689 }
2690
2691
2692 static void
2693 lstore(int e2,int creg)
2694 {
2695 char *drn = register_name(e2);
2696 char *crn_h;
2697 char *crn_l;
2698 crn_h = lregister_name_high(creg);
2699 crn_l = lregister_name_low(creg);
2700 #if ENDIAN_L==0
2701 printf("\tstr\t%s, [%s, #0]\n",crn_l,drn);
2702 printf("\tstr\t%s, [%s, #%d]\n",crn_h,drn,SIZE_OF_INT);
2703 #else
2704 printf("\tstr\t%s, [%s, #0]\n",crn_h,drn);
2705 printf("\tstr\t%s, [%s, #%d]\n",crn_l,drn,SIZE_OF_INT);
2706 #endif
2707 }
2708
2709 int
2710 code_lrindirect(int e1, int reg, int offset, int us)
2711 {
2712 int creg0;
2713
2714 g_expr(e1);
2715 if (!is_int_reg(creg)) error(-1);
2716 creg0=creg;
2717 use_longlong(reg);
2718 lload(creg0,reg,offset);
2719 return us?ULONGLONG:LONGLONG;
2720 }
2721 #endif
2722
2723 static char *
2724 cstore(int sz)
2725 {
2726 switch(sz) {
2727 case 1: return "stqx";
2728 case SIZE_OF_SHORT: return "stqa";
2729 default: return "stqd";
2730 }
2731 }
2732
2733 void
2734 code_assign_gvar(int e2,int creg,int byte) {
2735 use_int(creg);
2736 code_ldf(cstore(byte),register_name(creg),cadr(e2),
2737 get_ptr_cache((NMTBL*)caddr(e2)),byte==SIZE_OF_SHORT?" @ movhi":"");
2738 }
2739
2740 void
2741 code_assign_lvar(int e2,int creg,int byte) {
2742 char *crn;
2743 use_int(creg);
2744 crn=register_name(creg);
2745 lvar_intro(e2);
2746 printf("\t%s\t%s,",cstore(byte),crn);
2747 e2 *= 4;
2748 lvar(e2,"");
2749 }
2750
2751 void
2752 code_assign_register(int e2,int byte,int creg) {
2753 use_int(creg);
2754 if (e2!=creg) {
2755 printf("\tori\t%s, %s, 0\n",register_name(e2),register_name(creg));
2756 }
2757 }
2758
2759 void
2760 code_assign(int e2,int byte,int creg) {
2761 char *drn;
2762 char *crn;
2763 use_int(e2);
2764 drn=register_name(e2);
2765 use_int(creg);
2766 crn=register_name(creg);
2767
2768 printf("\t%s\t%s, 0(%s)\n",cstore(byte),crn,drn);
2769 }
2770
2771
2772 void
2773 code_register_assop(int e2,int reg, int op,int byte) {
2774 // reg <= reg(e2) op=reg
2775 use_int(reg);
2776 tosop(op,e2,reg);
2777 }
2778
2779 void
2780 code_assop(int op,int creg, int byte,int sign) {
2781 char *xrn,*crn,*drn;
2782 int xreg;
2783 int edx = get_register_var(0);
2784 if (car(edx)!=REGISTER) error(-1);
2785 // (*creg) op = pop()
2786
2787 drn = register_name(edx=cadr(edx));
2788 use_int(creg);
2789 xrn = register_name(xreg = emit_pop(0)); /* pop e3 value */
2790 code_register(creg,edx);
2791 ld_indexx(byte,0,edx,creg,sign);
2792 tosop(op,creg,xreg);
2793 crn = register_name(creg);
2794 printf("\t%s\t%s, 0(%s)\n",cstore(byte),crn,drn);
2795 free_register(edx);
2796 free_register(creg);
2797 emit_pop_free(xreg);
2798 }
2799
2800 int
2801 tosop_operand_safe_p(int op)
2802 {
2803 return 1;
2804 }
2805
2806 void
2807 tosop(int op,int creg,int oreg)
2808 {
2809 int ox = -1;
2810 char *orn,*crn;
2811 // creg = creg op oreg
2812
2813 use_int(creg);
2814 if(oreg==-1) {
2815 error(-1);
2816 } else if (oreg<= -REG_LVAR_OFFSET) {
2817 ox = get_register(); if (ox<0) error(-1);
2818 code_rlvar(oreg+REG_LVAR_OFFSET,ox);
2819 free_lvar(oreg+REG_LVAR_OFFSET);
2820 oreg = ox;
2821 }
2822
2823 switch(op) {
2824 case LSHIFT:
2825 case ULSHIFT:
2826 shift("asl",creg,oreg);
2827 if(ox!=-1) free_register(ox);
2828 return;
2829 case RSHIFT:
2830 shift("asr",creg,oreg);
2831 if(ox!=-1) free_register(ox);
2832 return;
2833 case URSHIFT:
2834 shift("lsr",creg,oreg);
2835 if(ox!=-1) free_register(ox);
2836 return;
2837 }
2838 orn = register_name(oreg);
2839 crn = register_name(creg);
2840 switch(op) {
2841 case ADD:
2842 printf("\ta\t%s, %s, %s\n",crn,crn,orn);
2843 break;
2844 case SUB:
2845 printf("\tsf\t%s, %s, %s\n",crn,crn,orn);
2846 break;
2847 case CMP:
2848 printf("\tcmp\t%s, %s\n",crn,orn);
2849 break;
2850 case BAND:
2851 printf("\tand\t%s, %s, %s\n",crn,crn,orn);
2852 break;
2853 case EOR:
2854 printf("\teor\t%s, %s, %s\n",crn,crn,orn);
2855 break;
2856 case BOR:
2857 printf("\torr\t%s, %s, %s\n",crn,crn,orn);
2858 break;
2859 case MUL:
2860 case UMUL:
2861 /* target!=source */
2862 printf("\tmul\t%s, %s, %s\n",crn,orn,crn);
2863 break;
2864 case DIV:
2865 code_int_lib("__divsi3",creg,oreg); break;
2866 case UDIV:
2867 code_int_lib("__udivsi3",creg,oreg); break;
2868 case MOD:
2869 code_int_lib("__modsi3",creg,oreg); break;
2870 case UMOD:
2871 code_int_lib("__umodsi3",creg,oreg); break;
2872 default:
2873 error(-1);
2874 }
2875 if(ox!=-1) free_register(ox);
2876 }
2877
2878 int
2879 code_const_op_p(int op,int v)
2880 {
2881 if (car(v)!=CONST) return 0;
2882 v = cadr(v);
2883 switch(op) {
2884 case MUL: case UMUL: case DIV: case UDIV:
2885 return ilog(v);
2886 case ADD: case SUB:
2887 return 1;
2888 case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT:
2889 return 0<v&&v<=32;
2890 case CMP:
2891 return is_stage1_const(v,CMP);
2892 case EOR: case BOR: case BAND:
2893 return (is_stage1_const(v,0)>0);
2894 default:
2895 return 0;
2896 }
2897 }
2898
2899 void
2900 oprtc(int op,int creg, int v)
2901 {
2902 char *crn;
2903 use_int(creg);
2904 crn = register_name(creg);
2905 v = cadr(v);
2906
2907 switch(op) {
2908 case MUL: case UMUL:
2909 v=ilog(v);
2910 case LSHIFT:
2911 case ULSHIFT:
2912 printf("\tmov\t%s, %s, asl #%d\n",crn,crn,v);
2913 break;
2914 case DIV:
2915 v=ilog(v);
2916 case RSHIFT:
2917 printf("\tmov\t%s, %s, asr #%d\n",crn,crn,v);
2918 break;
2919 case UDIV:
2920 v=ilog(v);
2921 case URSHIFT:
2922 printf("\tmov\t%s, %s, lsr #%d\n",crn,crn,v);
2923 break;
2924 case ADD:
2925 code_add(creg,v,creg);
2926 break;
2927 case SUB:
2928 code_add(creg,-v,creg);
2929 break;
2930 case CMP: printf("\tcmp\t%s,%d\n",crn,v); break;
2931 case BOR: printf("\torr\t%s, %s, #%d\n",crn,crn,v); break;
2932 case EOR: printf("\teor\t%s, %s, #%d\n",crn,crn,v); break;
2933 case BAND: printf("\tand\t%s, %s, #%d\n",crn,crn,v); break;
2934 default:
2935 error(-1);
2936 }
2937 }
2938
2939 void
2940 shift(char *op, int creg, int reg)
2941 {
2942 char *crn;
2943 char *rrn = register_name(reg);
2944 use_int(creg);
2945 crn = register_name(creg);
2946 printf("\tmov\t%s, %s, %s %s\n",crn,crn,op,rrn);
2947 }
2948
2949 void
2950 ld_indexx(int byte, int n, int xreg,int creg, int sign)
2951 {
2952 use_int(creg);
2953 code_ld(cload(byte,sign),creg,n,xreg,cext_at(byte,sign));
2954 }
2955
2956 int
2957 code_csvalue()
2958 {
2959 return glist2(REGISTER,creg);
2960 }
2961
2962 void
2963 code_cmpdimm(int e, int csreg,int label,int cond)
2964 {
2965 /* used in dosiwtch() */
2966 int sign,reg=-1;
2967 int regsv;
2968 char *rn,*crn;
2969 crn = register_name(csreg);
2970
2971 if (!(sign=is_stage1_const(e,CMP))) {
2972 regsv = regs[csreg]; regs[csreg]=1;
2973 rn = register_name(reg= get_register());
2974 regs[csreg] = regsv;
2975 code_const(e,reg);
2976 printf("\tcmp\t%s, %s\n",crn,rn);
2977 } else {
2978 if (sign>0)
2979 printf("\tcmp\t%s, #%d\n",crn,e);
2980 else
2981 printf("\tcmn\t%s, #%d\n",crn,-e);
2982 }
2983 switch(cond) {
2984 case -1: break;
2985 case 1:
2986 printf("\tbne\t.LC%d\n",label); break;
2987 case 0:
2988 printf("\tbeq\t.LC%d\n",label); break;
2989 case LT:
2990 printf("\tblt\t.LC%d\n",label); break;
2991 case GT:
2992 printf("\tbgt\t.LC%d\n",label); break;
2993 default: error(-1);
2994 }
2995 if (reg!=-1) free_register(reg);
2996 }
2997
2998 void
2999 code_opening(char *filename)
3000 {
3001 /* this is called once per file */
3002 //printf("@ Generated by mc for ARM/elf\n");
3003 printf("\t.file \"%s\"\n",filename);
3004 // printf(".text\n");
3005 }
3006
3007 // should have pcond_const
3008
3009 #define COND_BRANCH 1
3010 #define COND_VALUE 2
3011 #define COND_BRANCH_CONST 3
3012 #define COND_VALUE_CONST 4
3013
3014 /*
3015 if (r1 cmp r2) goto l1 COND_BRANCH
3016 r0 = (r1 cmp r2) COND_VALUE
3017 */
3018 static void
3019 pcond(int op, int r2,int r1,int r0,int cond,int l1,int mode)
3020 {
3021 char *rn2;
3022 char *rn1;
3023 char *rn0;
3024 char *cc=0,*ncc=0;
3025
3026 if (mode==COND_BRANCH_CONST||mode==COND_VALUE_CONST) {
3027 rn1 = register_name(r1);
3028 if (r2>=0)
3029 printf("\tcmp\t%s, #%d\n",rn1,r2);
3030 else
3031 printf("\tcmn\t%s, #%d\n",rn1,-r2);
3032 } else {
3033 rn1 = register_name(r1);
3034 rn2 = register_name(r2);
3035 printf("\tcmp\t%s, %s\n",rn1,rn2);
3036 }
3037
3038 switch(op+(!cond)*BNOT) {
3039 case GT: case LE+BNOT: cc="gt"; ncc="le"; break;
3040 case LE: case GT+BNOT: cc="le"; ncc="gt"; break;
3041 case GE: case LT+BNOT: cc="ge"; ncc="lt"; break;
3042 case LT: case GE+BNOT: cc="lt"; ncc="ge"; break;
3043 case UGT: case ULE+BNOT: cc="hi"; ncc="ls"; break;
3044 case ULE: case UGT+BNOT: cc="ls"; ncc="hi"; break;
3045 case UGE: case ULT+BNOT: cc="hs"; ncc="lo"; break;
3046 case ULT: case UGE+BNOT: cc="lo"; ncc="hs"; break;
3047 case EQ: case NEQ+BNOT: cc="eq"; ncc="ne"; break;
3048 case NEQ: case EQ+BNOT: cc="ne"; ncc="eq"; break;
3049 default: error(-1);
3050 }
3051
3052 if (mode==COND_BRANCH||mode==COND_BRANCH_CONST) {
3053 printf("\tb%s\t.LC%d\n",cc,l1);
3054 } else if (mode==COND_VALUE||mode==COND_VALUE_CONST) {
3055 rn0 = register_name(r0);
3056 printf("\tmov%s\t%s, #0\n",ncc,rn0);
3057 printf("\tmov%s\t%s, #1\n",cc,rn0);
3058 } else error(-1);
3059 }
3060
3061 int
3062 rexpr_bool(int e1, int reg)
3063 {
3064 int e2,reg0;
3065 int op = car(e1);
3066 if (!(
3067 op== GT || op== LT || op== UGT || op== ULT ||
3068 op== ULE || op== UGE || op== LE || op== GE ||
3069 op== EQ || op== NEQ
3070 )) return 0;
3071 if (car(caddr(e1))==CONST && is_stage1_const(cadr(caddr(e1)),CMP)) {
3072 g_expr(cadr(e1));
3073 reg0 = ireg;
3074 use_int(reg);
3075 pcond(op, cadr(caddr(e1)),reg0,reg,1,0,COND_VALUE_CONST);
3076 } else {
3077 g_expr(cadr(e1));
3078 emit_push();
3079 g_expr(caddr(e1));
3080 e2 = emit_pop(1);
3081 reg0 = ireg;
3082 use_int(reg);
3083 pcond(op, reg0,e2,reg,1,0,COND_VALUE);
3084 emit_pop_free(e2);
3085 }
3086 return 1;
3087 }
3088
3089 int
3090 rexpr(int e1, int l1, int cond,int t)
3091 {
3092 int e2;
3093 int op = car(e1);
3094
3095 if (car(caddr(e1))==CONST && is_stage1_const(cadr(caddr(e1)),CMP)) {
3096 g_expr(cadr(e1));
3097 pcond(op, cadr(caddr(e1)),ireg,0,cond,l1,COND_BRANCH_CONST);
3098 } else {
3099 g_expr(cadr(e1));
3100 emit_push();
3101 g_expr(caddr(e1));
3102 e2 = emit_pop(1);
3103 pcond(op, ireg,e2,0,cond,l1,COND_BRANCH);
3104 emit_pop_free(e2);
3105 }
3106 return l1;
3107 }
3108
3109 #define CMP_C1T (-1)
3110
3111 static void
3112 jcond(int l, int cond)
3113 {
3114 printf("\tb%s\t.LC%d\n",cond?"ne":"eq",l);
3115 }
3116
3117 void
3118 jmp(int l)
3119 {
3120 printf("\tbr\t.LC%d\n",l);
3121 if (inst_count>CONST_TBL_COUNT/2) {
3122 const_list_table();
3123 }
3124 }
3125
3126 void
3127 code_comment(char *s)
3128 {
3129 printf("## %s",s);
3130 }
3131 /*
3132 static int
3133 code_register_save(int reg_save,int freg_save,int disp)
3134 {
3135 int i;
3136 printf("\tstmfd\tsp!, {");
3137 for (i=reg_var_num(0);i<reg_var_num(reg_save);i++) {
3138 printf("%s, ",register_name(i));
3139 }
3140 printf("fp, ip, lr, pc}\n");
3141 if (freg_save>0) {
3142 printf("\tsfmfd\tf4, %d, [sp]!\n",freg_save);
3143 }
3144 return disp;
3145 }
3146 */
3147
3148 static int
3149 code_register_restore(int reg_save,int freg_save,int disp)
3150 {
3151 int i;
3152 if (freg_save>0) {
3153 i=reg_save*SIZE_OF_INT+
3154 freg_save*SIZE_OF_DOUBLE + 20;
3155 printf("\tlfm\tf4, %d, [fp, #%d]\n",freg_save,-i);
3156 }
3157 //printf("\tldmea\tfp, {");
3158 for (i=reg_var_num(0);i<reg_var_num(reg_save);i++) {
3159 printf("%s, ",register_name(i));
3160 }
3161 //printf("fp, sp, pc}\n");
3162 return disp;
3163 }
3164
3165 static int entry_label;
3166
3167 void
3168 code_enter(char *name)
3169 {
3170 if (output_mode!=TEXT_EMIT_MODE)
3171 text_mode(3);
3172 else
3173 printf("\t.align 3\n");
3174 if (stmode!=STATIC)
3175 printf("\t.globl\t%s\n",name);
3176 printf("\t.type\t%s,function\n",name);
3177 r1_offset_label = fwdlabel();
3178 max_func_args = 0;
3179 printf("%s:\n",name);
3180 code_label_value(r1_offset_label,REG_ip);
3181 printf("\ta\tsp, ip, fp\n");
3182 clear_ptr_cache();
3183 }
3184
3185
3186 void
3187 code_enter1(int args)
3188 {
3189 // set_lreg(LREG_LREGISTER,0);
3190 set_ireg(CREG_REGISTER,0);
3191 set_freg(FREG_FREGISTER,0);
3192 }
3193
3194 void
3195 code_leave(char *name)
3196 {
3197 code_offset_set(fnptr);
3198 local_table();
3199 printf("\t.size\t%s,.LC%d-%s\n",name, backdef(),name);
3200 }
3201
3202 void
3203 enter(char *name)
3204 {
3205 if (output_mode!=TEXT_EMIT_MODE)
3206 text_mode(2);
3207 else
3208 printf("\t.align 2\n");
3209
3210 max_func_args = 0;
3211
3212 lvar_offset_label = fwdlabel();
3213 // r1_offset_label = fwdlabel();
3214 printf("\t.type\t%s,function\n",name);
3215 if (stmode!=STATIC)
3216 printf("\t.globl\t%s\n",name);
3217 printf("%s:\n",name);
3218 //printf("\tmov\tip, sp\n");
3219 printf("\tstqd\t$lr,16($sp)\n");
3220 printf("\tstqd\t$sp,-32($sp)\n");
3221 printf("\tai\t$sp,$sp,-32\n");
3222 gen_jmp(entry_label = fwdlabel());
3223 register_save_return_label = backdef();
3224 clear_ptr_cache();
3225 }
3226
3227 void
3228 enter1()
3229 {
3230 text_mode(0);
3231 // set_lreg(LREG_LREGISTER,0);
3232 set_ireg(CREG_REGISTER,0);
3233 set_freg(FREG_FREGISTER,0);
3234 }
3235
3236 void
3237 code_label_call(int l)
3238 {
3239 printf("\tbl\tL_%d\n",l);
3240 }
3241
3242 void
3243 code_ret()
3244 {
3245 printf("\tmov\tpc, lr\n");
3246 control=0;
3247 }
3248
3249 void
3250 leave(int control0, char *name)
3251 {
3252 int retcont1=0,sz;
3253
3254 if (control0) {
3255 code_set_return_register(1);
3256 } else
3257 text_mode(2);
3258 if (retcont) {
3259 /* return from CbC segement */
3260 if (control0) gen_jmp(retlabel);
3261 retcont1 = fwdlabel();
3262 fwddef(retcont);
3263 if (cadr(fnptr->ty)==FLOAT) {
3264 #if FLOAT_CODE
3265 creg = freg = cadr(get_input_dregister_var(0,0,1,0));
3266 set_freg(RET_FREGISTER,1);
3267 #endif
3268 } else if (cadr(fnptr->ty)==DOUBLE) {
3269 #if FLOAT_CODE
3270 creg = lreg = cadr(get_input_dregister_var(0,0,1,1));
3271 set_dreg(RET_DREGISTER,1);
3272 #endif
3273 } else if (cadr(fnptr->ty)>0&&(
3274 car(cadr(fnptr->ty))==STRUCT ||
3275 car(cadr(fnptr->ty))==UNION)) {
3276 sz = size(cadr(fnptr->ty));
3277 code_const(sz,REGISTER_OPERAND);
3278 printf("\tsf\tr1, r2, fp\n");
3279 printf("\tlqd\tr0, [fp, #%d]\n",(my_func_args-1)*SIZE_OF_INT);
3280 emit_copy(6,3,sz,0,1,1);
3281 } else if (cadr(fnptr->ty)!=VOID) {
3282 creg = ireg = cadr(get_input_register_var(0,0,1));
3283 if (creg!=RET_REGISTER)
3284 set_ireg(RET_REGISTER,1);
3285 }
3286 code_unfix_frame_pointer();
3287 }
3288 fwddef(retlabel);
3289
3290 code_offset_set(fnptr);
3291 code_register_restore(max_reg_var,max_reg_var,0);
3292
3293 // leave part end
3294
3295 // entry part (save register)
3296
3297 fwddef(entry_label);
3298 if (arg_on_register>0)
3299 printf("\tsfi\tsp, sp, %d\n",arg_on_register);
3300 //code_register_save(max_reg_var,max_reg_var,0);
3301
3302 //printf("\tsf\tfp, ip, #%d\n",4+arg_on_register);
3303 code_add(REG_sp,disp-max_func_args*SIZE_OF_INT,REG_sp);
3304 gen_jmp(register_save_return_label);
3305 local_table();
3306
3307 printf("\t.size\t%s,.LC%d-%s\n",name, backdef(),name);
3308
3309 free_all_register();
3310 }
3311
3312
3313 void
3314 code_set_return_register(int mode) {
3315 if (cadr(fnptr->ty)==FLOAT) {
3316 set_freg(RET_FREGISTER,mode);
3317 } else if (cadr(fnptr->ty)==DOUBLE) {
3318 #if FLOAT_CODE
3319 set_dreg(RET_DREGISTER,mode);
3320 #endif
3321 } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) {
3322 #if LONGLONG_CODE
3323 set_lreg(RET_LREGISTER,mode);
3324 #endif
3325 } else if (cadr(fnptr->ty)==VOID) {
3326 } else {
3327 set_ireg(RET_REGISTER,mode);
3328 }
3329 }
3330
3331 int
3332 code_get_fixed_creg(int reg,int type) {
3333 switch(type) {
3334 #if FLOAT_CODE
3335 case DOUBLE: use_float(1,reg); break;
3336 case FLOAT: use_float(0,reg); break;
3337 #endif
3338 #if LONGLONG_CODE
3339 case LONGLONG: case ULONGLONG: use_longlong(reg); break;
3340 #endif
3341 default:
3342 if (reg==USE_CREG) {
3343 if (regs[CREG_REGISTER]==0||regs[CREG_REGISTER]==PTRC_REG) {
3344 set_ireg(CREG_REGISTER,is_int_reg(creg)&&regs[creg]==USING_REG);
3345 return CREG_REGISTER;
3346 }
3347 }
3348 use_int(reg);
3349 break;
3350 }
3351 return reg;
3352 }
3353
3354 void
3355 code_set_fixed_creg(int reg,int mode,int type) {
3356 if (type==FLOAT) {
3357 #if FLOAT_CODE
3358 set_freg(reg,mode);
3359 #endif
3360 } else if (type==DOUBLE) {
3361 #if FLOAT_CODE
3362 set_dreg(reg,mode);
3363 #endif
3364 } else if (type==LONGLONG||type==ULONGLONG) {
3365 #if LONGLONG_CODE
3366 set_lreg(reg,mode);
3367 // use_reg(reg);
3368 #endif
3369 } else {
3370 set_ireg(reg,mode);
3371 }
3372 }
3373
3374 void
3375 gen_gdecl(char *n, int gpc)
3376 {
3377 /*
3378 if (stmode!=STATIC)
3379 printf(".globl %s\n",n);
3380 */
3381 }
3382
3383 void
3384 align(int t)
3385 {
3386 int d;
3387 switch(t) {
3388 case CHAR: case UCHAR: return;
3389 case SHORT: case USHORT: d = data_alignment & 1; break;
3390 default: d = data_alignment & 3;
3391 }
3392 if (d) {
3393 printf("\t.align 2\n");
3394 data_alignment = 0;
3395 }
3396 }
3397
3398 static void
3399 ascii(char *s)
3400 {
3401 printf("\t.string \"");
3402 while(*s) {
3403 if (*s=='\n')
3404 printf("%cn",92);
3405 else if (*s<' ')
3406 printf("%c%03o",92,*s);
3407 else if (*s=='\\')
3408 printf("\\\\");
3409 else if (*s==34)
3410 printf("%c%c",92,34);
3411 else
3412 printf("%c",*s);
3413 s++;
3414 }
3415 printf("\\0%c\n",34);
3416 }
3417
3418 int
3419 emit_string_label() {
3420 int lb;
3421
3422 lb=fwdlabel();
3423 // should put on different segement
3424 cstring_mode();
3425 printf(".LC%d:\n",lb);
3426 return lb;
3427 }
3428
3429 extern void
3430 emit_string(char *s,int t)
3431 {
3432 t = type_value(t);
3433 if (car(t)==ARRAY &&
3434 (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) {
3435 ascii(s);
3436 } else {
3437 int l = emit_string_label();
3438 ascii(s);
3439 emit_label(l);
3440 }
3441 return;
3442 }
3443
3444 void
3445 emit_global(NMTBL *n,int a,int e)
3446 {
3447 int t = type_value(n->ty);
3448 if (e>0 && car(e)==STRING && t>0 && car(t)==ARRAY &&
3449 (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) {
3450 cstring_mode();
3451 } else
3452 data_mode(n->nm);
3453 align(a);
3454 if (n && n->sc!=STATIC)
3455 printf("\t.globl\t%s\n",n->nm);
3456 printf("%s:\n",n->nm);
3457 }
3458
3459 void
3460 emit_space(int sp)
3461 {
3462 data_mode(0);
3463 printf("\t.space\t%d\n",sp);
3464 }
3465
3466 void
3467 emit_char(int d)
3468 {
3469 data_mode(0);
3470 printf("\t.byte %d\n",d);
3471 }
3472
3473 void
3474 emit_short(int d)
3475 {
3476 data_mode(0);
3477 printf("\t.short %d\n",d);
3478 }
3479
3480 void
3481 emit_int(int d)
3482 {
3483 data_mode(0);
3484 align(0);
3485 printf("\t.word %d\n",d);
3486 }
3487
3488 void
3489 emit_longlong(int e)
3490 {
3491 #if LONGLONG_CODE
3492 long long ll = lcadr(e);
3493 data_mode(0);
3494 #if (ENDIAN_L==0)
3495 printf("\t.long\t0x%x,0x%x\n",code_l1(ll),code_l2(ll));
3496 #else
3497 printf("\t.long\t0x%x,0x%x\n",code_l2(ll),code_l1(ll));
3498 #endif
3499 #endif
3500 }
3501
3502 void
3503 emit_double(int e)
3504 {
3505 #if FLOAT_CODE
3506 double d = dcadr(e);
3507 data_mode(0);
3508 #if (ENDIAN_D==0)
3509 printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d));
3510 #else
3511 printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d));
3512 #endif
3513 #endif
3514 }
3515
3516 void
3517 emit_float(int e)
3518 {
3519 #if FLOAT_CODE
3520 float f = dcadr(e);
3521 data_mode(0);
3522 printf("\t.long\t0x%x\n",*(int *)&f);
3523 #endif
3524 }
3525
3526 void
3527 emit_address(char *s,int offset)
3528 {
3529 data_mode(0);
3530 if (offset)
3531 printf("\t.word %s+%d\n",s,offset);
3532 else
3533 printf("\t.word %s\n",s);
3534 }
3535
3536 void
3537 emit_label(int labelno)
3538 {
3539 data_mode(0);
3540 printf("\t.word .L%d\n",labelno);
3541 }
3542
3543 void
3544 emit_data_closing(NMTBL *n)
3545 {
3546 #ifdef DOT_SIZE
3547 int lb;
3548 #endif
3549 if (mode==GDECL) {
3550 data_mode(0);
3551 #ifdef DOT_SIZE
3552 lb=fwdlabel();
3553 printf(".LC%d:\n",lb);
3554 printf("\t.size\t%s,.L%d-%s\n",n->nm,lb,n->nm);
3555 #endif
3556 }
3557 }
3558
3559
3560 static void
3561 comm(NMTBL *n)
3562 {
3563 printf(".comm %s,%d @ %d\n",n->nm,size(n->ty),
3564 (n->ty==DOUBLE||n->ty==LONGLONG||n->ty==ULONGLONG)?8:4
3565 );
3566 }
3567
3568 void
3569 global_table(void)
3570 {
3571 NMTBL *n;
3572 int init;
3573 init=0;
3574 for(n=global_list;n;n=n->next) {
3575 if ((n->sc == GVAR) && n->dsp != -1) {
3576 /* n->dsp = -1 means initialized global */
3577 if (init==0) {
3578 data_mode(0);
3579 init=1;
3580 }
3581 comm(n);
3582 } else if ((n->sc==STATIC) && n->dsp != -1) {
3583 /* n->dsp = -1 means initialized global */
3584 if (is_code(n)||is_function(n)) continue;
3585 if (init==0) {
3586 data_mode(0);
3587 init=1;
3588 }
3589 // printf(".local %s\n",n->nm);
3590 comm(n);
3591 }
3592 }
3593 }
3594
3595 void
3596 local_table(void)
3597 {
3598 NMTBL *n;
3599 int init;
3600 free_glist3_a(prev_const_list); prev_const_list = 0;
3601 const_list_table();
3602
3603 init=0;
3604 /* static local variables */
3605 for(n=local_static_list;n;n=n->next) {
3606 if (n->sc == STATIC) {
3607 if (n->dsp != -1) { /* initialized static */
3608 if (init==0) {
3609 data_mode(0);
3610 init=1;
3611 }
3612 comm(n);
3613 }
3614 }
3615 }
3616 text_mode(2);
3617 }
3618
3619 void
3620 cstring_mode(int align)
3621 {
3622 if (output_mode!=RODATA_EMIT_MODE) {
3623 printf(".section\t.rodata\n\t.align 2\n");
3624 output_mode = RODATA_EMIT_MODE;
3625 }
3626 }
3627
3628 void
3629 text_mode(int align)
3630 {
3631 if (output_mode!=TEXT_EMIT_MODE) {
3632 printf(".text\n");
3633 if (align) printf("\t.align %d\n",align);
3634 output_mode = TEXT_EMIT_MODE;
3635 }
3636 }
3637
3638 void
3639 data_mode(char *name)
3640 {
3641 if (output_mode!=DATA_EMIT_MODE) {
3642 printf(".data\n");
3643 output_mode = DATA_EMIT_MODE;
3644 }
3645 if (name)
3646 printf("\t.type\t%s,object\n",name);
3647 }
3648
3649 #define lib_args(max) if (max_func_args<max) max_func_args=max
3650
3651 #if LONGLONG_CODE||FLOAT_CODE
3652 static void
3653 extern_conv(char *conv)
3654 {
3655 code_save_stacks();
3656 clear_ptr_cache();
3657 extern_define(conv,0,FUNCTION,1);
3658 printf("\tbl\t%s\n",conv);
3659 lib_args(16);
3660 }
3661 #endif
3662
3663 static void
3664 code_int_lib(char *lib,int reg,int oreg)
3665 {
3666 int g;
3667 code_save_stacks();
3668 clear_ptr_cache();
3669 g = list3(REGISTER_OPERAND,0,reg);
3670 g = list3(REGISTER_OPERAND_1,g,oreg);
3671 parallel_rassign(g);
3672 extern_define(lib,0,FUNCTION,1);
3673 printf("\tbl\t%s\n",lib);
3674 lib_args(16);
3675 set_ireg(RET_REGISTER,0);
3676 if (reg!=RET_REGISTER) {
3677 code_register(RET_REGISTER,reg);
3678 }
3679 }
3680
3681 #if FLOAT_CODE
3682
3683 /* floating point */
3684
3685 #define set_double(freg) if (regs[freg]) {regs[freg]=USING_DREG;}
3686 #define set_float(freg) if (regs[freg]) {regs[freg]=USING_DREG;}
3687
3688 void
3689 code_cmp_dregister(int e2,int d,int label,int cond)
3690 {
3691 char *frn;
3692 use_float(d,e2);
3693
3694 frn = register_name(e2);
3695 printf("\tcmf\t%s, #0\n",frn);
3696 jcond(label,cond);
3697 return;
3698 }
3699
3700 static char *
3701 movef(int d)
3702 {
3703 return d?"mvfd":"mvfs";
3704 }
3705
3706 static char *
3707 fload(int d) { return d?"ldfd":"ldfs"; }
3708
3709 static char *
3710 fstore(int d) { return d?"stfd":"stfs"; }
3711
3712
3713 void
3714 code_dregister(int e2,int freg,int d)
3715 {
3716 use_float(d,freg);
3717 if (freg!=e2) {
3718 if (is_int_reg(e2)) error(-1);
3719 printf("\t%s\t%s, %s\n",movef(d),
3720 register_name(freg),register_name(e2));
3721 }
3722 }
3723
3724 void
3725 code_dassign_gvar(int e2,int freg,int d)
3726 {
3727 use_float(d,freg);
3728 code_ldf(fstore(d),register_name(freg),cadr(e2),
3729 get_ptr_cache((NMTBL*)caddr(e2))," @ float");
3730 }
3731
3732 void
3733 code_dassign_lvar(int e2,int freg,int d)
3734 {
3735 use_float(d,freg);
3736 lvar_intro(e2);
3737 printf("\t%s\t%s, ",fstore(d),register_name(freg));
3738 lvar(e2,"@ float");
3739 }
3740
3741 void
3742 code_dassign(int e2,int freg,int d)
3743 {
3744 use_float(d,freg);
3745 printf("\t%s\t%s, [%s, #0] @ float\n",fstore(d),
3746 register_name(freg),register_name(e2));
3747 }
3748
3749 void
3750 code_dassign_dregister(int e2,int d,int freg) {
3751 use_float(d,freg);
3752 if (e2!=freg) {
3753 printf("\t%s\t%s, %s\n",movef(d),
3754 register_name(e2),register_name(freg));
3755 }
3756 }
3757
3758 static double d0 = 1.0;
3759
3760 int
3761 code_d1(double d)
3762 {
3763 int *i = (int *)&d0; int *j = (int *)&d;
3764 return (i[1] == 0x3ff00000)?j[0]:j[1];
3765 }
3766
3767 int
3768 code_d2(double d)
3769 {
3770 int *i = (int *)&d0; int *j = (int *)&d;
3771 return (i[1] == 0x3ff00000)?j[1]:j[0];
3772 }
3773
3774 int
3775 code_f(double d)
3776 {
3777 float f = d;
3778 int *j = (int *)&f;
3779 return *j;
3780 }
3781
3782 static void
3783 dconst(int l,int h,double value)
3784 {
3785 #if ENDIAN_D==0
3786 code_const(code_d1(value),l);
3787 code_const(code_d2(value),h);
3788 #else
3789 code_const(code_d1(value),h);
3790 code_const(code_d2(value),l);
3791 #endif
3792 }
3793
3794 static void
3795 fconst(int reg,double value)
3796 {
3797 float f = value;
3798 code_const(*((int*)&f),reg);
3799 }
3800
3801 void
3802 code_dconst(int e2,int freg,int d)
3803 {
3804 double value = dcadr(e2);
3805 float f = value;
3806 char *frn;
3807 int label,disp;
3808
3809 use_float(d,freg);
3810 frn = register_name(freg);
3811 if (value==0 || value==1 || value==10) {
3812 printf("\t%s\t%s, #%d\n",movef(d),frn,(int)value);
3813 } else if (value==-1 || value==-10) {
3814 printf("\t%s\t%s, #%d\n",d?"mnfd":"mnfs",frn,(int)-value);
3815 } else if (d) {
3816 #if ENDIAN_D==0
3817 disp = search_double_const(DCONST,
3818 code_d1(value),code_d2(value),&label);
3819 #else
3820 disp = search_double_const(DCONST,
3821 code_d2(value),code_d1(value),&label);
3822 #endif
3823 printf("\tldfd\t%s, .LC%d+%d\n",frn,label,disp);
3824 } else {
3825 //disp = search_const(CONST,*((int*)&f),&label);
3826 printf("\tldfs\t%s, .LC%d+%d\n",frn,label,disp);
3827 }
3828 }
3829
3830
3831 void
3832 code_builtin_fabsf(int e)
3833 {
3834 }
3835 void
3836 code_builtin_fabs(int e)
3837 {
3838 }
3839 void
3840 code_builtin_inff()
3841 {
3842 }
3843 void
3844 code_builtin_inf(int op)
3845 {
3846 }
3847
3848 void
3849 code_dneg(int freg,int d)
3850 {
3851 char *frn;
3852 use_float(d,freg);
3853 frn = register_name(freg);
3854 printf("\t%s\t%s, %s\n",d?"mnfd":"mnfs",frn,frn);
3855 }
3856
3857 void
3858 code_d2i0(int reg,int d)
3859 {
3860 int lreg;
3861 use_float(d,reg);
3862 lreg = get_register();
3863 printf("\tfixz\t%s, %s\n",register_name(lreg),register_name(reg));
3864 set_ireg(lreg,0);
3865 return;
3866 }
3867
3868 void
3869 code_i2d0(int reg,int d)
3870 {
3871 int lreg;
3872 use_int(reg);
3873 lreg = get_dregister(1);
3874 printf("\tflt%c\t%s, %s\n",dsuffix(d),
3875 register_name(lreg),register_name(reg));
3876 set_dreg(lreg,0);
3877 return;
3878 }
3879
3880 void
3881 code_d2u0(int reg,int d)
3882 {
3883 int lreg,reg0;
3884 char *lrn,*frn,*crn;
3885 // u = (d>2.1e9)?((int)(d-2.1e9)^2147483648):(int)d
3886 use_float(1,reg);
3887 frn = register_name(reg);
3888 if (!d) printf("\tmvfd\t%s, %s\n",frn,frn);
3889 emit_dpush(1);
3890 code_dconst(dlist2(DCONST,2.147483648e9),USE_CREG,1);
3891 lrn = register_name(lreg = emit_dpop(d));
3892 frn = register_name(freg);
3893 set_ireg(reg0=get_register(),0);
3894 crn = register_name(reg0);
3895 printf("\tcmfe\t%s, %s\n",lrn,frn);
3896 printf("\tbge\t1f\n");
3897 printf("\tfixz\t%s, %s\n",crn,lrn);
3898 printf("\tb\t2f\n");
3899 printf("1:\n");
3900 printf("\tsufd\t%s, %s, %s\n",lrn,lrn,frn);
3901 printf("\tfixz\t%s, %s\n",crn,lrn);
3902 printf("\teor\t%s, %s, #-2147483648\n",crn,crn);
3903 printf("2:\n");
3904 emit_dpop_free(lreg,d);
3905 return;
3906 }
3907
3908 void
3909 code_u2d0(int reg,int d)
3910 {
3911 int tmp,freg1;
3912 char *crn,*frn,*lrn;
3913 use_int(reg);
3914 crn = register_name(reg);
3915 set_dreg(reg=get_dregister(1),0);
3916 frn = register_name(reg);
3917 printf("\tfltd\t%s, %s\n",frn,crn);
3918 printf("\tcmp\t%s, #0\n",crn);
3919 printf("\tbge\t1f\n");
3920 freg1 = get_dregister(1);
3921 code_dconst(dlist2(DCONST,4.29496729600000000000e9),freg1,1);
3922 frn = register_name(creg);
3923 lrn = register_name(freg1);
3924 printf("\tadfd\t%s, %s, %s\n",frn,frn,lrn);
3925 printf("1:\n");
3926 if (!d)
3927 printf("\tmvfs\t%s, %s\n",frn,frn);
3928 free_register(freg1);
3929 return;
3930 }
3931
3932 void
3933 code_d2f(int reg) {
3934 char *frn;
3935 frn = register_name(freg);
3936 printf("\tmvfs\t%s,%s\n",frn,frn);
3937 return;
3938 }
3939
3940 void
3941 code_f2d(int reg) {
3942 char *frn;
3943 frn = register_name(freg);
3944 printf("\tmvfd\t%s, %s\n",frn,frn);
3945 return;
3946 }
3947
3948 void
3949 code_d2i(int reg) {
3950 code_d2i0(reg,1);
3951 }
3952
3953 void
3954 code_d2u(int reg) {
3955 code_d2u0(reg,1);
3956 }
3957
3958 void
3959 code_f2i(int reg) {
3960 code_d2i0(reg,0);
3961 }
3962
3963 void
3964 code_f2u(int reg) {
3965 code_d2u0(reg,0);
3966 }
3967
3968 void
3969 code_i2d(int reg) {
3970 code_i2d0(reg,1);
3971 }
3972
3973 void
3974 code_i2f(int reg) {
3975 code_i2d0(reg,0);
3976 }
3977
3978 void
3979 code_u2d(int reg) {
3980 code_u2d0(reg,1);
3981 }
3982
3983 void
3984 code_u2f(int reg) {
3985 code_u2d0(reg,0);
3986 }
3987
3988 void
3989 code_drgvar(int e2,int d,int freg)
3990 {
3991 use_float(d,freg);
3992 code_ldf(fload(d),register_name(freg),cadr(e2),
3993 get_ptr_cache((NMTBL*)caddr(e2)),"");
3994 }
3995
3996
3997 void
3998 code_drlvar(int e2,int d,int freg)
3999 {
4000 use_float(d,freg);
4001 lvar_intro(e2);
4002 printf("\t%s\t%s, ",fload(d),register_name(freg));
4003 lvar(e2,d?"@ double":"@ float");
4004 }
4005
4006 void
4007 code_cmp_drgvar(int e2,int reg,int d,int label,int cond)
4008 {
4009 use_float(d,reg);
4010 code_drgvar(e2,d,reg);
4011 code_cmp_dregister(reg,d,label,cond);
4012 }
4013
4014 void
4015 code_cmp_drlvar(int e2,int reg,int d,int label,int cond)
4016 {
4017 use_float(d,reg);
4018 code_drlvar(e2,d,reg);
4019 code_cmp_dregister(reg,d,label,cond);
4020 }
4021
4022 static void
4023 code_double_lib(char *lib,int to,int reg,int oreg)
4024 {
4025 code_save_stacks();
4026 clear_ptr_cache();
4027 set_operands(reg,reg,oreg,oreg);
4028 extern_conv(lib);
4029 set_dreg(RET_DREGISTER,0);
4030 if (to!=RET_DREGISTER) {
4031 lmove(to,RET_DREGISTER);
4032 }
4033 }
4034
4035 static void
4036 code_double_lib_c(char *lib,int from,int to,double value)
4037 {
4038 code_save_stacks();
4039 clear_ptr_cache();
4040 set_dreg_operand(from,1);
4041 dconst(DREGISTER_OPERAND_1_L,DREGISTER_OPERAND_1_H,value);
4042 extern_conv(lib);
4043 set_dreg(RET_DREGISTER,0);
4044 if (to!=RET_DREGISTER) {
4045 lmove(to,RET_DREGISTER);
4046 }
4047 }
4048
4049 static void
4050 code_float_lib(char *lib,int to,int reg,int oreg)
4051 {
4052 code_save_stacks();
4053 clear_ptr_cache();
4054 if (reg!=FREGISTER_OPERAND) code_dregister(FREGISTER_OPERAND,reg,0);
4055 if (to!=FREGISTER_OPERAND_1) code_dregister(FREGISTER_OPERAND_1,to,0);
4056 extern_conv(lib);
4057 set_freg(RET_FREGISTER,0);
4058 if (to!=RET_FREGISTER) {
4059 code_dregister(to,RET_FREGISTER,0);
4060 }
4061 }
4062
4063 static void
4064 code_float_lib_c(char *lib,int from,int to,double value)
4065 {
4066 code_save_stacks();
4067 clear_ptr_cache();
4068 set_dreg_operand(from,1);
4069 fconst(FREGISTER_OPERAND_1,value);
4070 extern_conv(lib);
4071 set_freg(RET_FREGISTER,0);
4072 if (to!=RET_FREGISTER) {
4073 code_dregister(to,RET_FREGISTER,0);
4074 }
4075 }
4076
4077
4078 void
4079 dtosop(int op,int reg,int e1)
4080 {
4081 char *opn="";
4082
4083 char *grn,*frn;
4084 int d;
4085 int cmp=0;
4086
4087
4088 d=(op<FOP);
4089 use_float(d,reg);
4090 switch(op) {
4091 case DADD: opn="adfd"; break;
4092 case DSUB: opn="sufd"; break;
4093 case DDIV: opn="fdvd"; break;
4094 case DMUL: opn="fmld"; break;
4095 case DCMPGE:
4096 case DCMP: opn="cmfe"; cmp=1; break;
4097 case FADD: opn="adfs"; break;
4098 case FSUB: opn="sufs"; break;
4099 case FDIV: opn="fdvs"; break;
4100 case FMUL: opn="fmls"; break;
4101 case FCMPGE:
4102 case FCMP: opn="cmfe"; cmp=1; break;
4103 default:
4104 error(-1); return;
4105 }
4106 grn = register_name(e1);
4107 frn = register_name(reg);
4108 if (cmp) {
4109 printf("\t%s\t%s, %s\n",opn,grn,frn);
4110 } else {
4111 printf("\t%s\t%s, %s, %s\n",opn,frn,frn,grn);
4112 }
4113 }
4114
4115
4116 void
4117 code_dassop(int op,int reg,int d) {
4118 /* we have lvalue in creg, applied floating value is in freg */
4119 // (*creg) op = pop()
4120 int xreg;
4121 char *crn;
4122 char *frn;
4123
4124
4125
4126 xreg=emit_dpop(d);
4127 crn=register_name(ireg);
4128 use_float(d,reg);
4129 frn =register_name(reg);
4130
4131 code_ldf(fload(d),register_name(freg),0,ireg,"");
4132 dtosop(op,reg,xreg);
4133 code_ldf(fstore(d),register_name(freg),0,ireg,"");
4134 emit_dpop_free(xreg,d);
4135 }
4136
4137 void
4138 code_register_dassop(int reg,int op,int d) {
4139 // reg op= dpop()
4140 int xreg;
4141 xreg=emit_dpop(d);
4142 dtosop(op,reg,xreg);
4143 emit_dpop_free(xreg,d);
4144 }
4145
4146 static int
4147 code_dload_1(int d)
4148 {
4149 int g = get_dregister(d);
4150 printf("\tmvf%c\t%s,#1\n",dsuffix(d),register_name(g));
4151 return g;
4152 }
4153
4154
4155 void
4156 code_dpreinc(int e1,int e2,int d,int reg) {
4157 char *frn;
4158 char *crn;
4159 int g,reg0;
4160 char *grn;
4161 int dir=caddr(e1);
4162
4163 if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
4164 crn=register_name(cadr(e2));
4165 grn=register_name(g=code_dload_1(d));
4166 if (reg==USE_CREG) {
4167 reg=get_dregister(d); if (!reg) error(-1);
4168 if (d) set_dreg(reg,0); else set_freg(reg,0);
4169 }
4170 frn=register_name(reg);
4171 printf("\t%s%c\t%s, %s, %s\n",
4172 dir>0?"adf":"suf",dsuffix(d),
4173 crn,crn,grn);
4174 if (use && reg!=cadr(e2)) {
4175 printf("\tmvf%c\t%s, %s\n",dsuffix(d),frn,crn);
4176 }
4177 } else {
4178 g_expr(e2);
4179 if (!is_int_reg(creg)) error(-1);
4180 reg0 = ireg;
4181 if (reg==USE_CREG) {
4182 reg=get_dregister(d); if (!reg) error(-1);
4183 if (d) set_dreg(reg,0); else set_freg(reg,0);
4184 }
4185 grn = register_name(g = code_dload_1(d));
4186 frn=register_name(reg);
4187 code_ldf(fload(d),frn,0,reg0,"");
4188 printf("\t%s%c\t%s, %s, %s\n",
4189 dir>0?"adf":"suf",dsuffix(d),
4190 frn,frn,grn);
4191 code_ldf(fstore(d),frn,0,reg0,"");
4192 }
4193 free_register(g);
4194 }
4195
4196 void
4197 code_dpostinc(int e1,int e2,int d,int reg) {
4198 char *frn;
4199 char *crn;
4200 int g,reg0;
4201 char *grn;
4202 int dir=caddr(e1);
4203
4204 if (car(e2)==DREGISTER||car(e2)==FREGISTER) {
4205 crn=register_name(cadr(e2));
4206 grn=register_name(g=code_dload_1(d));
4207 if (reg==USE_CREG) {
4208 reg=get_dregister(d); if (!reg) error(-1);
4209 set_freg(reg,0);
4210 }
4211 frn=register_name(reg);
4212 if (use && reg!=cadr(e2)) {
4213 printf("\tmvf%c\t%s, %s\n",dsuffix(d),frn,crn);
4214 }
4215 printf("\t%s%c\t%s,%s,%s\n",dir>0?"adf":"suf",
4216 dsuffix(d),crn,crn,grn);
4217 } else {
4218 g_expr(e2);
4219 if (!is_int_reg(creg)) error(-1);
4220 crn=register_name(reg0=ireg);
4221 if (reg==USE_CREG) {
4222 reg=get_dregister(d); if (!reg) error(-1);
4223 set_freg(reg,0);
4224 }
4225 frn=register_name(reg);
4226 grn = register_name(g = code_dload_1(d));
4227 code_ldf(fload(d),frn,0,reg0,"");
4228 printf("\t%s%c\t%s, %s, %s\n",
4229 dir>0?"adf":"suf",dsuffix(d),
4230 grn,frn,grn);
4231 code_ldf(fstore(d),grn,0,reg0,"");
4232 }
4233 free_register(g);
4234 }
4235
4236
4237 int
4238 drexpr(int e1, int e2,int l1, int op,int cond)
4239 {
4240 int op1=0;
4241 char *opn=0;
4242 if (!cond) {
4243 switch(op) {
4244 case FOP+GT:
4245 return drexpr(e2,e1,l1,FOP+GE,1);
4246 case FOP+GE:
4247 return drexpr(e2,e1,l1,FOP+GT,1);
4248 case FOP+EQ:
4249 op=FOP+NEQ; break;
4250 case FOP+NEQ:
4251 op=FOP+EQ; break;
4252 case DOP+GT:
4253 return drexpr(e2,e1,l1,DOP+GE,1);
4254 case DOP+GE:
4255 return drexpr(e2,e1,l1,DOP+GT,1);
4256 case DOP+EQ:
4257 op=DOP+NEQ; break;
4258 case DOP+NEQ:
4259 op=DOP+EQ; break;
4260 }
4261 }
4262 switch(op) {
4263 case FOP+GT: op1=FOP+CMP; opn = "bgt"; break;
4264 case FOP+GE: op1=FOP+CMPGE; opn = "bge"; break;
4265 case FOP+EQ: op1=FOP+CMP; opn = "beq"; break;
4266 case FOP+NEQ: op1=FOP+CMP; opn = "bne"; break;
4267 case DOP+GT: op1=DOP+CMP; opn = "bgt"; break;
4268 case DOP+GE: op1=DOP+CMPGE; opn = "bge"; break;
4269 case DOP+EQ: op1=DOP+CMP; opn = "beq"; break;
4270 case DOP+NEQ: op1=DOP+CMP; opn = "bne"; break;
4271 default: error(-1);
4272 }
4273 g_expr(list3(op1,e2,e1));
4274 printf("\t%s\t.L%d\n",opn,l1);
4275 return l1;
4276 }
4277
4278 int emit_dpop(int d)
4279 {
4280 int xreg,reg;
4281 xreg=pop_fregister();
4282 if (xreg<= -REG_LVAR_OFFSET) {
4283 reg = get_dregister(d);
4284 code_drlvar(REG_LVAR_OFFSET+xreg,1,reg);
4285 free_lvar(REG_LVAR_OFFSET+xreg);
4286 xreg=reg;
4287 }
4288 return xreg;
4289 }
4290
4291
4292 void
4293 emit_dpop_free(int e1,int d)
4294 {
4295 free_register(e1);
4296 }
4297
4298 void
4299 emit_dpush(int d)
4300 {
4301 int new_reg;
4302 if (!is_float_reg(creg)) error(-1);
4303 if (reg_sp>MAX_MAX) error(-1);
4304 new_reg = get_dregister(d); /* ?????????? */
4305 reg_stack[reg_sp++] = freg; /* push ???????????????? */
4306 creg = freg = new_reg;
4307 }
4308
4309 #endif
4310
4311 #if LONGLONG_CODE
4312
4313
4314 /* 64bit int part */
4315
4316 int
4317 lrexpr_bool(int e1, int reg)
4318 {
4319 return 0;
4320 }
4321
4322 int
4323 lrexpr(int e1, int e2,int l1, int op,int cond)
4324 {
4325 int reg,regh,regl,e3h,e3l;
4326 int e3,l2;
4327 g_expr(e1);
4328 emit_lpush();
4329 g_expr(e2);
4330 e3 = emit_lpop();
4331 if (!is_longlong_reg(creg)) error(-1);
4332 reg = lreg;
4333 l2 = fwdlabel();
4334 regh = reg; regl = reg;
4335 e3h = e3; e3l = e3;
4336 switch(op) {
4337 case LOP+GT: case LOP+GE:
4338 pcond(GT, regh,e3h,0,1,cond?l1:l2,COND_BRANCH);
4339 pcond(NEQ, regh,e3h,0,1,cond?l2:l1,COND_BRANCH);
4340 break;
4341 case LOP+UGT: case LOP+UGE:
4342 pcond(UGT, regh,e3h,0,1,cond?l1:l2,COND_BRANCH);
4343 pcond(NEQ, regh,e3h,0,1,cond?l2:l1,COND_BRANCH);
4344 break;
4345 case LOP+EQ:
4346 pcond(EQ, regh,e3h,0,0,cond?l2:l1,COND_BRANCH);
4347 break;
4348 case LOP+NEQ:
4349 pcond(EQ, regh,e3h,0,0,cond?l1:l2,COND_BRANCH);
4350 break;
4351 default:
4352 error(-1);
4353 }
4354 pcond(op%LOP,regl,e3l,0,cond,l1,COND_BRANCH);
4355 fwddef(l2);
4356 emit_lpop_free(e3);
4357 return l1;
4358 }
4359
4360 void
4361 code_cmp_lregister(int reg,int label,int cond)
4362 {
4363 use_longlong(reg);
4364 printf("\torr\t%s, %s, %s\n",
4365 lregister_name_low(reg),
4366 lregister_name_low(reg),
4367 lregister_name_high(reg));
4368 code_cmp_register((reg),label,cond);
4369 }
4370
4371 void
4372 code_cmp_lrgvar(int e1,int creg,int label,int cond)
4373 {
4374 use_longlong(creg);
4375 code_lrgvar(e1,creg);
4376 code_cmp_lregister(creg,label,cond);
4377 }
4378
4379 void
4380 code_cmp_lrlvar(int e1,int creg,int label,int cond)
4381 {
4382 use_longlong(creg);
4383 code_lrlvar(e1,creg);
4384 code_cmp_lregister(creg,label,cond);
4385 }
4386
4387 #endif
4388 #if LONGLONG_CODE||FLOAT_CODE
4389
4390 int
4391 emit_lpop()
4392 {
4393 int xreg,reg;
4394 xreg=reg_stack[--reg_sp];
4395 if (xreg<= -REG_LVAR_OFFSET) {
4396 reg = get_lregister();
4397 code_lrlvar(REG_LVAR_OFFSET+xreg,reg);
4398 free_lvar(REG_LVAR_OFFSET+xreg);
4399 xreg = reg;
4400 }
4401 return xreg;
4402 }
4403
4404 void
4405 code_lregister(int e2,int reg)
4406 {
4407 use_longlong(reg);
4408 if (reg!=e2) {
4409 lmove(reg,e2);
4410 }
4411 }
4412
4413
4414 void
4415 code_lassign(int e2,int creg)
4416 {
4417 use_longlong(creg);
4418 lstore(e2,creg);
4419 }
4420
4421 void
4422 code_lassign_gvar(int e2,int creg)
4423 {
4424 int r;
4425 use_longlong(creg);
4426 r = get_ptr_cache((NMTBL*)caddr(e2));
4427 #if ENDIAN_L==0
4428 code_ldf(cstore(0),lregister_name_low(creg),cadr(e2),r,"");
4429 code_ldf(cstore(0),lregister_name_high(creg),cadr(e2)+SIZE_OF_INT,r,"");
4430 #else
4431 code_ldf(cstore(0),lregister_name_high(creg),cadr(e2),r,"");
4432 code_ldf(cstore(0),lregister_name_low(creg),cadr(e2)+SIZE_OF_INT,r,"");
4433 #endif
4434 }
4435
4436 void
4437 code_lassign_lvar(int e2,int creg)
4438 {
4439 char *crn_h;
4440 char *crn_l;
4441
4442 use_longlong(creg);
4443 crn_h = lregister_name_high(creg);
4444 crn_l = lregister_name_low(creg);
4445 lvar_intro(e2);
4446 #if ENDIAN_L==0
4447 printf("\tstr\t%s, ",crn_l);lvar(e2,"");
4448 printf("\tstr\t%s, ",crn_h);lvar(e2+SIZE_OF_INT,"");
4449 #else
4450 printf("\tstr\t%s, ",crn_h);lvar(e2,"");
4451 printf("\tstr\t%s, ",crn_l);lvar(e2+SIZE_OF_INT,"");
4452 #endif
4453 }
4454
4455 void
4456 code_lassign_lregister(int e2,int reg)
4457 {
4458 use_longlong(reg);
4459 if (e2!=reg) {
4460 lmove(e2,reg);
4461 }
4462 }
4463
4464 void
4465 emit_lpop_free(int xreg)
4466 {
4467 if (xreg>=0)
4468 free_register(xreg);
4469 }
4470
4471 void
4472 emit_lpush()
4473 {
4474 int new_reg;
4475 if (!is_longlong_reg(creg)) error(-1);
4476 if (reg_sp>MAX_MAX) error(-1);
4477 new_reg = get_lregister(); /* ??????????(?) */
4478 reg_stack[reg_sp++] = creg; /* push ???????????????? */
4479 lreg = creg = new_reg;
4480 }
4481
4482 void
4483 code_lrgvar(int e1,int creg)
4484 {
4485 int r;
4486 char *crn_h;
4487 char *crn_l;
4488 use_longlong(creg);
4489 crn_h = lregister_name_high(creg);
4490 crn_l = lregister_name_low(creg);
4491 r = get_ptr_cache((NMTBL*)caddr(e1));
4492 #if ENDIAN_L==0
4493 code_ldf("ldr",crn_l,cadr(e1),r,"");
4494 code_ldf("ldr",crn_h,cadr(e1)+SIZE_OF_INT,r,"");
4495 #else
4496 code_ldf("ldr",crn_h,cadr(e1),r,"");
4497 code_ldf("ldr",crn_l,cadr(e1)+SIZE_OF_INT,r,"");
4498 #endif
4499 }
4500
4501 void
4502 code_lrlvar(int e1,int creg)
4503 {
4504 char *crn_h;
4505 char *crn_l;
4506 use_longlong(creg);
4507 crn_h = lregister_name_high(creg);
4508 crn_l = lregister_name_low(creg);
4509 lvar_intro(e1);
4510 printf("\tlqd\t%s, ",crn_l); lvar(e1,"");
4511 printf("\tlqd\t%s, ",crn_h); lvar(e1+SIZE_OF_INT,"");
4512 }
4513
4514 #endif
4515 #if LONGLONG_CODE
4516
4517 static long long ll0 = 1LL;
4518
4519 static int
4520 code_l1(long long d)
4521 {
4522 int *i = (int *)&ll0; int *j = (int *)&d;
4523 return (i[1] == 1)?j[1]:j[0];
4524 }
4525
4526 static int
4527 code_l2(long long d)
4528 {
4529 int *i = (int *)&ll0; int *j = (int *)&d;
4530 return (i[1] == 1)?j[0]:j[1];
4531 }
4532
4533 void
4534 code_lconst(int e1,int creg)
4535 {
4536 use_longlong(creg);
4537 #if ENDIAN_L==0
4538 code_const(code_l1(lcadr(e1)),(creg));
4539 code_const(code_l2(lcadr(e1)),(creg));
4540 #else
4541 code_const(code_l1(lcadr(e1)),(creg));
4542 code_const(code_l2(lcadr(e1)),(creg));
4543 #endif
4544 }
4545
4546 void
4547 code_lneg(int creg)
4548 {
4549
4550 char *rh,*rl;
4551 use_longlong(creg);
4552 rl=lregister_name_low(creg);
4553 rh=lregister_name_high(creg);
4554 printf("\trsbs\t%s, %s, #0\n",rl,rl);
4555 printf("\trsc\t%s, %s, #0\n",rh,rh);
4556 }
4557
4558 static void
4559 code_longlong_lib(char *lib,int reg,int oreg)
4560 {
4561 code_save_stacks();
4562 clear_ptr_cache();
4563 set_operands((reg),(reg),(oreg),(oreg));
4564 extern_conv(lib);
4565 // set_lreg(RET_LREGISTER,0);
4566 }
4567
4568 #define check_lreg(reg) lmove(reg,RET_LREGISTER)
4569
4570 void
4571 ltosop(int op,int reg,int oreg)
4572 {
4573 int dx = -1;
4574 int ox = -1;
4575 char *orn_h,*crn_h;
4576 char *orn_l,*crn_l;
4577
4578 // reg = reg op oreg
4579
4580 use_longlong(reg);
4581 if(oreg==-1) {
4582 error(-1);
4583 } else if (oreg<= -REG_LVAR_OFFSET) {
4584 ox = get_lregister(); if (ox<0) error(-1);
4585 use_reg(ox);
4586 code_rlvar(oreg+REG_LVAR_OFFSET,ox);
4587 oreg = ox;
4588 }
4589
4590 switch(op) {
4591 case LLSHIFT:
4592 case LULSHIFT:
4593 code_longlong_lib("__ashldi3",reg,oreg);
4594 check_lreg(reg);
4595 if(ox!=-1) free_register(ox);
4596 return;
4597 case LRSHIFT:
4598 code_longlong_lib("__ashrdi3",reg,oreg);
4599 check_lreg(reg);
4600 if(ox!=-1) free_register(ox);
4601 return;
4602 case LURSHIFT:
4603 code_longlong_lib("__lshrdi3",reg,oreg);
4604 check_lreg(reg);
4605 if(ox!=-1) free_register(ox);
4606 return;
4607 }
4608 orn_h = lregister_name_high(oreg);
4609 orn_l = lregister_name_low(oreg);
4610 crn_h = lregister_name_high(reg);
4611 crn_l = lregister_name_low(reg);
4612 switch(op) {
4613 case LADD:
4614 printf("\tadds\t%s, %s, %s\n",crn_l,crn_l,orn_l);
4615 printf("\tadc\t%s, %s, %s\n",crn_h,crn_h,orn_h);
4616 break;
4617 case LSUB:
4618 printf("\tsubs\t%s, %s, %s\n",crn_l,crn_l,orn_l);
4619 printf("\tsbc\t%s, %s, %s\n",crn_h,crn_h,orn_h);
4620 break;
4621 case LCMP:
4622 error(-1);
4623 break;
4624 case LBAND:
4625 printf("\tand\t%s, %s, %s\n",crn_l,crn_l,orn_l);
4626 printf("\tand\t%s, %s, %s\n",crn_h,crn_h,orn_h);
4627 break;
4628 case LEOR:
4629 printf("\teor\t%s, %s, %s\n",crn_l,crn_l,orn_l);
4630 printf("\teor\t%s, %s, %s\n",crn_h,crn_h,orn_h);
4631 break;
4632 case LBOR:
4633 printf("\torr\t%s, %s, %s\n",crn_l,crn_l,orn_l);
4634 printf("\torr\t%s, %s, %s\n",crn_h,crn_h,orn_h);
4635 break;
4636 case LMUL:
4637 case LUMUL:
4638 code_longlong_lib("__muldi3",reg,oreg);
4639 check_lreg(reg);
4640 break;
4641 case LDIV:
4642 code_longlong_lib("__divdi3",reg,oreg);
4643 check_lreg(reg);
4644 break;
4645 case LUDIV:
4646 code_longlong_lib("__udivdi3",reg,oreg);
4647 check_lreg(reg);
4648 break;
4649 case LMOD:
4650 code_longlong_lib("__moddi3",reg,oreg);
4651 check_lreg(reg);
4652 break;
4653 case LUMOD:
4654 code_longlong_lib("__umoddi3",reg,oreg);
4655 check_lreg(reg);
4656 break;
4657 default:
4658 error(-1);
4659 }
4660 if(ox!=-1) free_register(ox);
4661 if(dx!=-1) free_register(dx);
4662 }
4663
4664 int
4665 code_lconst_op_p(int op,int e)
4666 {
4667 long long v;
4668 if (car(e)==LCONST) {
4669 v = lcadr(e);
4670 } else if (car(e)==CONST) {
4671 v = cadr(e);
4672 } else return 0;
4673
4674 switch(op) {
4675 case LMUL: case LUMUL: /* case LDIV: */ case LUDIV:
4676 return ilog(v);
4677 case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT:
4678 return 0<v&&v<=64;
4679 case LADD:
4680 case LSUB:
4681 case LBOR:
4682 case LEOR: case LBAND:
4683 return (is_stage1_const(v,0)>0)
4684 && (is_stage1_const(v>>32,0)>0);
4685 default:
4686 return 0;
4687 }
4688 }
4689
4690 void
4691 loprtc(int op,int creg,int e)
4692 {
4693 char *crn_h;
4694 char *crn_l;
4695 char *grn;
4696 int v=0;
4697 int vh=0;
4698 int greg,dx=-1;
4699
4700 use_longlong(creg);
4701 crn_h = lregister_name_high(creg);
4702 crn_l = lregister_name_low(creg);
4703
4704 if (car(e)==LCONST) { v = lcadr(e); vh = lcadr(e)>>32; }
4705 else if (car(e)==CONST) {
4706 v = cadr(e);
4707 vh = (v<0)?-1:0;
4708 }
4709
4710 switch(op) {
4711 case LMUL: case LUMUL:
4712 v=ilog(v);
4713 case LLSHIFT:
4714 case LULSHIFT:
4715 if (v==0) return;
4716 if (v==32) {
4717 code_register((creg),(creg));
4718 code_const(0,(creg));
4719 return;
4720 } else if (v>31) {
4721 printf("\tmov\t%s, %s, lsl #%d\n",crn_h,crn_l,v-32);
4722 code_const(0,(creg));
4723 return;
4724 }
4725 greg = get_register();
4726 grn = register_name(greg);
4727 printf("\tmov\t%s, %s, lsl #%d\n",crn_h,crn_h,v);
4728 printf("\tmov\t%s, %s, lsr #%d\n",grn,crn_l,32-v);
4729 printf("\torr\t%s, %s,%s\n",crn_h,crn_h,grn);
4730 printf("\tmov\t%s, %s, lsl #%d\n",crn_l,crn_l,v);
4731 free_register(greg);
4732 return;
4733 case LDIV:
4734 v=ilog(v);
4735 case LRSHIFT:
4736 if (v==0) return;
4737 if (v==32) {
4738 code_register((creg),(creg));
4739 printf("\tmov\t%s, %s, asr #31\n",crn_h,crn_l);
4740 return;
4741 } else if (v>31) {
4742 printf("\tmov\t%s, %s, asr #%d\n",crn_l,crn_h,v-32);
4743 printf("\tmov\t%s, %s, asr #31\n",crn_h,crn_l);
4744 return;
4745 }
4746 greg = get_register();
4747 grn = register_name(greg);
4748 printf("\tmov\t%s, %s, lsr #%d\n",crn_l,crn_l,v);
4749 printf("\tmov\t%s, %s, lsl #%d\n",grn,crn_h,32-v);
4750 printf("\torr\t%s, %s,%s\n",crn_l,crn_l,grn);
4751 printf("\tmov\t%s, %s, asr #%d\n",crn_h,crn_h,v);
4752 free_register(greg);
4753 return;
4754 case LUDIV:
4755 v=ilog(v);
4756 case LURSHIFT:
4757 if (v==0) return;
4758 if (v==32) {
4759 code_register((creg),(creg));
4760 code_const(0,(creg));
4761 return;
4762 } else if (v>31) {
4763 printf("\tmov\t%s, %s, lsr #%d\n",crn_l,crn_h,v-32);
4764 code_const(0,(creg));
4765 return;
4766 }
4767 greg = get_register();
4768 grn = register_name(greg);
4769 printf("\tmov\t%s, %s, lsl #%d\n",grn,crn_h,32-v);
4770 printf("\tmov\t%s, %s, lsr #%d\n",crn_l,crn_l,v);
4771 printf("\torr\t%s, %s,%s\n",crn_l,grn,crn_l);
4772 printf("\tmov\t%s, %s, lsr #%d\n",crn_h,crn_h,v);
4773 free_register(greg);
4774 return;
4775 case LADD:
4776 printf("\tadds\t%s, %s, #%d\n",crn_l,crn_l,v);
4777 printf("\tadc\t%s, %s, #%d\n",crn_h,crn_h,vh);
4778 break;
4779 case LSUB:
4780 printf("\tsubs\t%s, %s, #%d\n",crn_l,crn_l,v);
4781 printf("\tsbc\t%s, %s, #%d\n",crn_h,crn_h,vh);
4782 break;
4783 case LBAND:
4784 printf("\tand\t%s, %s, #%d\n",crn_l,crn_l,v);
4785 printf("\tand\t%s, %s, #%d\n",crn_h,crn_h,vh);
4786 break;
4787 case LEOR:
4788 printf("\teor\t%s, %s, #%d\n",crn_l,crn_l,v);
4789 printf("\teor\t%s, %s, #%d\n",crn_h,crn_h,vh);
4790 break;
4791 case LBOR:
4792 printf("\torr\t%s, %s, #%d\n",crn_l,crn_l,v);
4793 printf("\torr\t%s, %s, #%d\n",crn_h,crn_h,vh);
4794 break;
4795 default:
4796 error(-1);
4797 }
4798 if (dx!=-1) free_register(dx);
4799 }
4800
4801
4802 void
4803 code_i2ll(int reg)
4804 {
4805 char *crn,*crn_h,*crn_l;
4806 int reg0;
4807 crn = register_name(reg0 = ireg);
4808 use_longlong(reg);
4809 crn_h = lregister_name_high(lreg);
4810 crn_l = lregister_name_low(lreg);
4811 if (reg0!=(lreg))
4812 printf("\tori\t%s, %s, 0\n",crn_l,crn);
4813 printf("\tmov\t%s, %s, asr #31\n",crn_h,crn_l);
4814 }
4815
4816 void
4817 code_i2ull(int reg)
4818 {
4819 code_i2ll(reg);
4820 }
4821
4822 void
4823 code_u2ll(int reg)
4824 {
4825 char *crn,*crn_h,*crn_l;
4826 int reg0;
4827 crn = register_name(reg0 = ireg);
4828 use_longlong(reg);
4829 crn_h = lregister_name_high(lreg);
4830 crn_l = lregister_name_low(lreg);
4831 if (reg0!=(lreg))
4832 printf("\tori\t%s, %s, 0\n",crn_l,crn);
4833 printf("\tmov\t%s, #0\n",crn_h);
4834 }
4835
4836 void
4837 code_u2ull(int creg)
4838 {
4839 code_u2ll(creg);
4840 }
4841
4842 void
4843 code_ll2i(int reg)
4844 {
4845 char *crn_l;
4846 int reg0;
4847 crn_l = lregister_name_low(reg0=lreg);
4848 use_int(reg);
4849 if (ireg!=(reg0)) {
4850 printf("\tori\t%s, %s, 0\n",register_name(ireg),crn_l);
4851 }
4852 }
4853
4854 void
4855 code_ll2u(int creg)
4856 {
4857 code_ll2i(creg);
4858 }
4859
4860 void
4861 code_ull2i(int creg)
4862 {
4863 code_ll2i(creg);
4864 }
4865
4866 void
4867 code_ull2u(int creg)
4868 {
4869 code_ll2i(creg);
4870 }
4871
4872 #if FLOAT_CODE
4873
4874 void
4875 code_d2ll(int reg)
4876 {
4877 // fixdfdi$stub
4878 code_assign_input_double_long(
4879 list2(LREGISTER,LREGISTER_OPERAND),list2(FREGISTER,freg)) ;
4880 extern_conv("__fixdfdi");
4881 set_lreg(RET_LREGISTER,0);
4882 if (reg!=USE_CREG&&reg!=RET_LREGISTER) {
4883 use_longlong(reg);
4884 }
4885 }
4886
4887 void
4888 code_d2ull(int reg)
4889 {
4890 code_assign_input_double_long(
4891 list2(LREGISTER,LREGISTER_OPERAND),list2(FREGISTER,freg)) ;
4892 extern_conv("__fixunsdfdi");
4893 set_lreg(RET_LREGISTER,0);
4894 if (reg!=USE_CREG&&reg!=RET_LREGISTER) {
4895 use_longlong(reg);
4896 }
4897 }
4898
4899 void
4900 code_f2ll(int reg)
4901 {
4902 code_assign_input_float_int(list2(REGISTER,REGISTER_OPERAND),list2(FREGISTER,freg));
4903 extern_conv("__fixsfdi");
4904 set_lreg(RET_LREGISTER,0);
4905 if (reg!=USE_CREG&&reg!=RET_LREGISTER) {
4906 use_longlong(reg);
4907 }
4908 }
4909
4910 void
4911 code_f2ull(int reg)
4912 {
4913 code_assign_input_float_int(list2(REGISTER,REGISTER_OPERAND),list2(FREGISTER,freg));
4914 extern_conv("__fixunssfdi");
4915 set_lreg(RET_LREGISTER,0);
4916 if (reg!=USE_CREG&&reg!=RET_LREGISTER) {
4917 use_longlong(reg);
4918 }
4919 }
4920
4921 void
4922 code_ll2d(int reg)
4923 {
4924 set_lreg(LREGISTER_OPERAND,1);
4925 extern_conv("__floatdidf");
4926 set_dreg(RET_DREGISTER,0);
4927 if (reg!=USE_CREG&&reg!=RET_FREGISTER)
4928 use_float(1,reg);
4929 }
4930
4931
4932 void
4933 code_ll2f(int reg)
4934 {
4935 set_lreg(LREGISTER_OPERAND,1);
4936 extern_conv("__floatdisf");
4937 set_freg(RET_FREGISTER,0);
4938 if (reg!=USE_CREG&&reg!=RET_FREGISTER)
4939 use_float(0,reg);
4940 }
4941
4942 void
4943 code_ull2d(int creg)
4944 {
4945 code_ll2d(creg);
4946 }
4947
4948 void
4949 code_ull2f(int creg)
4950 {
4951 code_ll2f(creg);
4952 }
4953
4954 #endif
4955
4956 static void
4957 ladd(int dreg,int rreg,int v) // rreg = dreg + v
4958 {
4959 // v should be 8bit const with 2's shift
4960 if (v>0) {
4961 printf("\tadds\t%s, %s, #%d\n",
4962 lregister_name_low(rreg),lregister_name_low(dreg), v);
4963 printf("\tadc\t%s, %s, #0\n",
4964 lregister_name_high(rreg),lregister_name_high(dreg));
4965 } else {
4966 printf("\tsubs\t%s, %s, #%d\n",
4967 lregister_name_low(rreg),lregister_name_low(dreg), -v);
4968 printf("\tsbc\t%s, %s, #0\n",
4969 lregister_name_high(rreg),lregister_name_high(dreg));
4970 }
4971 }
4972
4973 void
4974 code_lpreinc(int e1,int e2,int reg)
4975 {
4976 int dreg=-1,xreg=-1;
4977 int dir=caddr(e1);
4978 if (car(e2)==LREGISTER) {
4979 use_longlong(reg);
4980 ladd(cadr(e2),cadr(e2),dir);
4981 if (reg!=cadr(e2)) {
4982 lmove(reg,cadr(e2));
4983 }
4984 return;
4985 }
4986 g_expr(e2);
4987 if(!is_int_reg(creg)) error(-1);
4988 emit_push();
4989 if (reg==USE_CREG) {
4990 dreg=get_lregister(); if (!dreg) error(-1);
4991 set_lreg(dreg,0); // free old lreg==creg
4992 } else {
4993 dreg = reg;
4994 }
4995 xreg = emit_pop(0);
4996 lload(xreg,dreg,0);
4997 ladd(dreg,dreg,dir);
4998 code_lassign(xreg,dreg);
4999 emit_pop_free(xreg);
5000 if (dreg!=-1) free_register(dreg);
5001 }
5002
5003 void
5004 code_lpostinc(int e1,int e2,int reg)
5005 {
5006 int dreg,nreg,xreg;
5007 int dir=caddr(e1);
5008 if (car(e2)==LREGISTER) {
5009 use_longlong(reg);
5010 lmove(reg,cadr(e2));
5011 ladd(cadr(e2),cadr(e2),dir);
5012 return;
5013 }
5014 g_expr(e2);
5015 if(!is_int_reg(creg)) error(-1);
5016 emit_push();
5017 nreg=get_lregister(); if (!nreg) error(-1);
5018 if (reg==USE_CREG) {
5019 dreg=get_lregister(); if (!dreg) error(-1);
5020 set_lreg(dreg,0); // free old lreg==creg
5021 } else {
5022 dreg = reg;
5023 }
5024 xreg = emit_pop(0);
5025 lload(xreg,dreg,0);
5026 ladd(dreg,nreg,dir);
5027 lstore(xreg,nreg);
5028 emit_pop_free(xreg);
5029 free_register(nreg);
5030 }
5031
5032 void
5033 code_lassop(int op,int reg)
5034 {
5035 int xreg;
5036 int edx,edx0=-1;
5037
5038 // (*creg) op = pop()
5039 xreg = emit_lpop(0); /* pop e3 value */
5040 if (!is_int_reg(creg)) error(-1);
5041 edx = ireg;
5042 emit_push();
5043 use_longlong(reg);
5044 if ((lreg)==edx || (lreg)==edx) {
5045 edx0 = get_register(); if(!edx0) error(-1);
5046 printf("## lassop\n\tori\t%s, %s, 0\n",register_name(edx0),
5047 register_name(edx));
5048 edx = edx0;
5049 }
5050 lload(edx,reg,0);
5051 // free_register(edx); don't do this, it will free pushed register
5052 ltosop(op,reg,xreg); // loprtc?
5053 emit_lpop_free(xreg);
5054 use_reg(reg);
5055 edx = emit_pop(0);
5056 code_lassign(edx,reg);
5057 emit_pop_free(edx);
5058 if (edx0!=-1)
5059 free_register(edx0);
5060 if (reg!=lreg)
5061 free_register(reg);
5062 }
5063
5064 void
5065 code_register_lassop(int reg,int op) {
5066 // reg op = pop()
5067 int xreg=emit_lpop();
5068 ltosop(op,reg,xreg);
5069 emit_lpop_free(xreg);
5070 }
5071
5072
5073 #endif
5074
5075 void
5076 code_save_stacks()
5077 {
5078 int i,reg;
5079 for(i=0;i<reg_sp;i++) {
5080 if ((reg=reg_stack[i])>=0) {
5081 code_assign_lvar(
5082 (reg_stack[i]=new_lvar(SIZE_OF_INT)*4),reg,0);
5083 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
5084 free_register(reg);
5085 }
5086 }
5087 #if FLOAT_CODE
5088 for(i=0;i<reg_sp;i++) {
5089 if ((reg=reg_stack[i])>=0) {
5090 code_dassign_lvar(
5091 (reg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1);
5092 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
5093 free_register(reg);
5094 }
5095 }
5096 #endif
5097 #if LONGLONG_CODE
5098 for(i=0;i<reg_sp;i++) {
5099 if ((reg=reg_stack[i])>=0) {
5100 code_lassign_lvar(
5101 (reg_stack[i]=new_lvar(SIZE_OF_LONGLONG)),reg);
5102 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
5103 free_register(reg);
5104 }
5105 }
5106 #endif
5107 }
5108
5109 void
5110 emit_lib(char *p[])
5111 {
5112 while(*p) {
5113 printf("%s\n",*p++);
5114 }
5115 }
5116
5117 void
5118 code_closing()
5119 {
5120 global_table();
5121 /* printf("\t.ident \"Micro-C compiled\"\n"); */
5122 }
5123
5124 #if CASE_CODE
5125
5126 int
5127 code_table_jump_p(int delta) { return delta==1||delta==2||delta==4; }
5128
5129 void
5130 code_table_jump(int l,int csvalue,int delta,int max,int min,int dlabel)
5131 {
5132 int t,regsv;
5133 char *trn;
5134
5135 regsv = regs[csvalue]; regs[csvalue] = 1;
5136 trn = register_name(t=get_register());
5137 regs[csvalue] = regsv;
5138
5139 code_add(t,-min,csvalue);
5140 switch(delta) {
5141 case 1:
5142 code_cmpdimm(max-min,t,dlabel,-1);
5143 printf("\tldrls\tpc, [pc, %s, asl #2]\n",trn);
5144 break;
5145 case 2:
5146 printf("\ttst\t%s, #1\n",trn);
5147 printf("\tbne\t.L%d\n",dlabel);
5148 code_cmpdimm(max-min,t,dlabel,-1);
5149 printf("\tldrls\tpc, [pc, %s, asl #1]\n",trn); break;
5150 break;
5151 case 4:
5152 printf("\ttst\t%s, #3\n",trn);
5153 printf("\tbne\t.L%d\n",dlabel);
5154 code_cmpdimm(max-min,t,dlabel,-1);
5155 printf("\tldrls\tpc, [pc, %s]\n",trn); break;
5156 break;
5157 default:
5158 error(-1);
5159 }
5160 printf("\tbr\t.L%d\n",dlabel);
5161
5162 free_register(t);
5163 }
5164
5165 void
5166 code_table_open(int l)
5167 {
5168 output_mode = DATA_EMIT_MODE;
5169 printf("\t.align 2\n");
5170 fwddef(l);
5171 }
5172
5173 void
5174 code_table_value(int label,int table_top)
5175 {
5176 printf("\t.word .L%d\n",label);
5177 }
5178
5179 void
5180 code_table_close()
5181 {
5182 }
5183
5184 #endif
5185
5186
5187 #if ASM_CODE
5188
5189 /*
5190 print an operand
5191 */
5192
5193 static void
5194 emit_asm_operand(int rstr)
5195 {
5196 if (car(rstr)==REGISTER) {
5197 printf("%s",register_name(cadr(rstr)));
5198 } else if (car(rstr)==CONST) {
5199 printf("%d",cadr(rstr));
5200 } else if (car(rstr)==FNAME) {
5201 printf("%s",(char*)cadr(rstr));
5202 } else if (car(rstr)==STRING) {
5203 printf(".L%d",cadr(rstr));
5204 } else {
5205 error(-1);
5206 }
5207 }
5208
5209 /*
5210 prepare asm operands
5211
5212 char *constraints string
5213 int operand expr
5214 int mode (ASM_INPUT,ASM_OUTPUT)
5215 int replacement list
5216 int output operands count
5217 int output operands replacement list
5218
5219 retrun replacement list
5220 list3( operands, next, clobber )
5221 0 can be shared in input/output
5222 1 can't be used in input
5223 */
5224
5225 int
5226 code_asm_operand(char *p,int e1,int mode,int repl,int n,int repl0)
5227 {
5228 int r;
5229 int c;
5230 int val;
5231 int clobber = 0;
5232
5233 printf("## constraint %s\n",p);
5234 if (*p=='=') {
5235 // output register
5236 p++;
5237 }
5238 if (*p=='&') {
5239 // earlyclobber
5240 p++;
5241 clobber = 1;
5242 }
5243 c = *p;
5244 if (c=='r') {
5245 if (mode==ASM_INPUT) {
5246 for(;repl0;repl0 = cadr(repl0)) {
5247 if (car(car(repl0))==REGISTER && caddr(repl0)==0) {
5248 r = cadr(car(repl0));
5249 caddr(repl0) = ASM_USED;
5250 break;
5251 }
5252 }
5253 r = get_register();
5254 } else {
5255 r = get_register();
5256 }
5257 repl = list3(list2(REGISTER,r),repl,clobber);
5258 } else if (c=='m') {
5259 repl = list3(list2(0,0),repl,clobber);
5260 } else if (c=='i') {
5261 if (car(e1)==GVAR) {
5262 e1=list3(FNAME,(int)(((NMTBL *)caddr(e1))->nm),0);
5263 } else if (car(e1)==FNAME) {
5264 e1=list3(FNAME,(int)(((NMTBL *)cadr(e1))->nm),0);
5265 } else if (car(e1)==STRING) {
5266 val = emit_string_label();
5267 ascii((char*)cadr(e1));
5268 e1=list3(STRING,val,0);
5269 } else if (car(e1)==CONST) {
5270 } else error(-1);
5271 repl = list3(e1,repl,clobber);
5272 } else if (digit(c)) {
5273 val = 0;
5274 do { val = val*10 + c-'0'; } while (digit(c=*p++));
5275 if (val>MAX_ASM_REG) error(-1); // too large register
5276 if (n-val<0) error(-1);
5277 repl = list3(car(nth(n-val-1,repl0)),repl,clobber);
5278 } else error(-1);
5279 return repl;
5280 }
5281
5282 void
5283 code_free_asm_operand(int repl)
5284 {
5285 for(;repl;repl=cadr(repl)) {
5286 if (car(car(repl))==REGISTER)
5287 free_register(cadr(car(repl)));
5288 }
5289 }
5290
5291
5292 extern void
5293 code_asm(char *asm_str,int repl)
5294 {
5295 int c,i,rstr,val;
5296 char *p;
5297 int reg[MAX_ASM_REG];
5298
5299 text_mode(2);
5300 c = *asm_str;
5301 if (c!='\t'&&c!=' ') printf("\t");
5302 for(i=0;repl && i<MAX_ASM_REG;i++) {
5303 reg[i] = car(repl);
5304 repl = cadr(repl);
5305 }
5306 p = asm_str;
5307 while((c = *p++)) {
5308 if (c=='%') {
5309 c = *p++;
5310 if (!c) { break;
5311 } else if (c=='%') {
5312 printf("%%"); continue;
5313 } else if (!digit(c)) {
5314 printf("%%%c",c); continue;
5315 }
5316 val = 0;
5317 do { val = val*10 + c-'0'; } while (digit(c=*p++)) ;
5318 p--;
5319 if (val>MAX_ASM_REG) error(-1); // too large register
5320 rstr = reg[val];
5321 emit_asm_operand(rstr);
5322 } else {
5323 printf("%c",c);
5324 }
5325 }
5326 printf("\n");
5327 }
5328
5329 #endif
5330
5331
5332 #if BIT_FIELD_CODE
5333
5334 /* bit field alignment calcuration */
5335
5336 static void
5337 set_bitsz(int type,int *pbitpos, int *pbitsize,
5338 int *psign,int *pbitsz,int *palign,int *pl)
5339 {
5340 int sign=0,bitsz=0;
5341 int align=0,l=0;
5342 switch(cadr(type)) { /* value type */
5343 case INT: sign=1; break;
5344 case UNSIGNED: break;
5345 case CHAR: sign=1; break;
5346 case UCHAR: break;
5347 case SHORT: sign=1; break;
5348 case USHORT: sign=1; break;
5349 case LONGLONG: sign=1; l=1; break;
5350 case ULONGLONG: l=1; break;
5351 default: error(-1);
5352 }
5353 if (car(caddr(type))>0) { /* store type */
5354 if (car(car(caddr(type)))==STRUCT) {
5355 bitsz=64+32; align=4; l=2;
5356 } else error(-1);
5357 } else {
5358 switch(car(caddr(type))) {
5359 case INT: bitsz=32; align=4; break;
5360 case UNSIGNED: bitsz=32; align=4; break;
5361 case CHAR: bitsz= 8; align=1; break;
5362 case UCHAR: bitsz= 8; align=1; break;
5363 case SHORT: bitsz=16; align=2; break;
5364 case USHORT: bitsz=16; align=2; break;
5365 case LONGLONG: bitsz=64; align=4; l=1; break;
5366 case ULONGLONG: bitsz=64; align=4; l=1; break;
5367 default: error(-1);
5368 }
5369 }
5370 *pbitpos = cadr(caddr(type));
5371 *pbitsize = caddr(caddr(type));
5372 *psign = sign;
5373 *pbitsz = bitsz;
5374 *palign = align;
5375 *pl = l;
5376 }
5377
5378 /*
5379 bit field alignment calcuration
5380 this is architecture depenedent
5381 */
5382
5383 #define NON_ALIGNED_BFD 1
5384
5385 extern int
5386 code_bit_field_disp(int type,int *poffset,int *bfd,int *sz)
5387 {
5388 int sign,bitsz,align;
5389 int i;
5390 int bitpos = *bfd;
5391 int offset = *poffset;
5392 int l;
5393 int bitsize,bitpos0;
5394 set_bitsz(type,&bitpos0,&bitsize,&sign,&bitsz,&align,&l);
5395
5396 if (bitsize>bitsz) { error(BTERR); bitsize = bitsz; }
5397
5398 /* bfd means previous bit field bit offset */
5399 if (bitpos) {
5400 /* previous field is bit field and spaces may remain */
5401 /* calc previsous offset */
5402 offset-=(bitpos+7)/8;
5403
5404 #ifdef NON_ALIGNED_BFD
5405 /* code for non-aligned non-hole bit-field */
5406
5407 /* remove extra previous offset from bitpos */
5408 while(bitpos>align*8) {
5409 i = ((offset+(align))&~(align-1))-offset;
5410 offset+=i; bitpos-=i*8;
5411 }
5412 if (bitpos+bitsize > bitsz) {
5413 int stype=UNSIGNED;
5414
5415 /* rewind extra previous offset */
5416 bitpos = *bfd; offset=*poffset;
5417 offset-=(bitpos+7)/8;
5418
5419 /* extend store type to allow |---===|===---| */
5420 switch(car(caddr(type))) {
5421 case INT: case UNSIGNED:
5422 stype=ULONGLONG; align=4; break;
5423 case CHAR: case UCHAR:
5424 stype=USHORT; align=2; break;
5425 case SHORT: case USHORT:
5426 stype=UNSIGNED; align=4; break;
5427 case ULONGLONG: case LONGLONG:
5428 /* dummy struct type. fields are never used */
5429 stype=list4(STRUCT,12,0,0);align=4;break;
5430 default: error(-1);
5431 }
5432 /* remove extra previous offset from bitpos again */
5433 while(bitpos>align*8) {
5434 i = ((offset+(align))&~(align-1))-offset;
5435 offset+=i; bitpos-=i*8;
5436 }
5437 bitsz = size(stype)*8;
5438 /* fix store type */
5439 car(caddr(type)) = stype;
5440 }
5441 #endif
5442
5443 /* previous remaining bit space can contain this type? */
5444 i= offset;
5445 for(l = bitpos;l>0;l -= 8,i++) {
5446 if ((i & (align-1))==0 && l+bitsize <= bitsz) {
5447 /* alignment is correct and space remains */
5448 *poffset=offset=i;
5449 i = l+bitsize;
5450 *bfd = (i==bitsz)?0:i;
5451 *sz = (i+7)/8;
5452 #ifdef BITPOS_DEBUG
5453 printf("## %d: bitpos=%d bitsize=%d bitsz=%d offset=%d\n",lineno,bitpos,bitsize,bitsz,*poffset);
5454 #endif
5455 return l;
5456 }
5457 }
5458 }
5459
5460 /* first bit-field or no remaining bits */
5461
5462 if ((i=(offset & (align-1)))) {
5463 *poffset = (offset += (align-i));
5464 }
5465 bitpos = 0;
5466 *bfd = (bitsize==bitsz)?0:bitsize;
5467 *sz = (bitsize+7)/8;
5468 #ifdef BITPOS_DEBUG
5469 printf("## %d: bitpos=%d bitsize=%d bitsz=%d offset=%d\n",lineno,bitpos,bitsize,bitsz,*poffset);
5470 #endif
5471 return bitpos;
5472 }
5473
5474 /* bit field value */
5475
5476 /* reg contains container value, result should be in reg */
5477 extern void
5478 code_bit_field(int type,int adr,int reg)
5479 {
5480 int sign,bitsz,l,align;
5481 int bitsize,bitpos;
5482 int i,size;
5483 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l);
5484 size = bitsz/8;
5485 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
5486 /* this implementation returns -1 for int i:1; */
5487 if (l==1) {
5488 #if LONGLONG_CODE
5489 // use_int(adr);
5490 use_longlong(reg);
5491 lload(adr,reg,0);
5492 /* shift left */
5493 if ((i=bitsz-bitsize-bitpos))
5494 loprtc(LLSHIFT,reg,list2(CONST,i));
5495 /* shift right */
5496 if ((i=bitsz-bitsize))
5497 loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i));
5498 } else if (l==2) { /* three int container */
5499 int lvalue;
5500 // use_int(adr);
5501 use_longlong(reg);
5502 lvalue = get_register();
5503 code_register(adr,lvalue); adr = lvalue;
5504 /*
5505
5506 <-----bitsize--------------->
5507 hhhhhh mmmmmmmmmmmm lllllll
5508 lllll 00000000000 mmmmmmmmmmmm 0000000 hhhhhhh
5509 |-----||-----------||------------||-------||-------|
5510 <-bitpos--->
5511 <----------------bitsz----------------------------->
5512 <-----32----------> <---32------> <----32---------->
5513 (r0:r1) <<= bitsz-bitsize-bitbos
5514 rest >> = b;
5515 rest << = a; (b>a) ==> rest >> (b-a)
5516 (64+32-bitsize -bitpos - (bitsz-bitsize))
5517 = 64+32 -bitsz -bitbpos
5518 */
5519 /* load hhhhh */
5520 code_ld(cload(0,0),(reg),SIZE_OF_INT*2,adr,cext_at(0,0));
5521 /* load mmmmmm */
5522 code_ld(cload(0,0),(reg),SIZE_OF_INT,adr,cext_at(0,0));
5523 i = 64-(bitsize-(32-bitpos));
5524 loprtc(LLSHIFT,reg,list2(CONST,i));
5525 if (i<0||64<=i) error(-1);
5526 /* load lllll */
5527 code_ld(cload(0,0),adr,0,adr,cext_at(0,0));
5528 i = (bitsize-(32-bitpos))-32;
5529 oprtc(URSHIFT,adr,list2(CONST,i));
5530 if (i<0||32<=i) error(-1);
5531 printf("\tadd\t%s,%s,%s\n",
5532 register_name((reg)),
5533 register_name((reg)),
5534 register_name(adr));
5535 i = 64-bitsize;
5536 loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i));
5537 if (i<0||64<=i) error(-1);
5538 free_register(adr);
5539 #endif
5540 } else {
5541 // use_int(adr);
5542 use_int(reg);
5543 code_ld(cload(size,sign),reg,0,adr,cext_at(0,0));
5544 /* shift left */
5545 if ((i=32-bitsize-bitpos))
5546 oprtc(LSHIFT,reg,list2(CONST,i));
5547 /* shift right */
5548 if ((i=32-bitsize))
5549 oprtc(sign?RSHIFT:URSHIFT,reg,list2(CONST,i));
5550 }
5551 }
5552
5553 /* bit field replacement */
5554
5555 static void
5556 make_mask_and_or(int mask,int tmp,char *trn,char *crn,char *lrn)
5557 {
5558 // printf("## mask 0x%08x ~0x%08x\n",mask,~mask);
5559 code_const(~mask,tmp);
5560 printf("\torr\t%s, %s, %s\n",trn,crn,trn);
5561 /* do conjunction */
5562 printf("\tand\t%s, %s, %s\n",lrn,trn,lrn);
5563 /* make or-mask */
5564 code_const(mask,tmp);
5565 printf("\tand\t%s, %s, %s\n",trn,crn,trn);
5566 /* do disjunction */
5567 printf("\torr\t%s, %s, %s\n",crn,trn,lrn);
5568 }
5569
5570 extern void
5571 code_bit_replace(int adr,int value,int type)
5572 {
5573 int sign,bitsz,l,align;
5574 int bitsize,bitpos;
5575 int mask = 0;
5576 int tmp = -1,lvalue,size;
5577 char *crn,*lrn,*trn;
5578 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l);
5579 size = bitsz/8;
5580 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
5581 if (l==1) {
5582 #if LONGLONG_CODE
5583 int tmp2;
5584 // use_int(adr);
5585 lvalue = get_lregister();
5586 tmp2 = get_register();
5587 code_register(adr,tmp2); adr = tmp2;
5588 lload(adr,lvalue,0);
5589 use_longlong(value);
5590 crn = lregister_name_high(value);
5591 lrn = lregister_name_high(lvalue);
5592 /* shift left */
5593 if (bitpos)
5594 loprtc(LLSHIFT,value,list2(CONST,bitpos));
5595 trn = register_name(tmp = get_register());
5596 if (bitpos+bitsize>=32) {
5597 /* make and-mask upper */
5598 mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31);
5599 make_mask_and_or(mask,tmp,trn,crn,lrn);
5600 }
5601 crn = lregister_name_low(value);
5602 lrn = lregister_name_low(lvalue);
5603 if (bitpos<32) {
5604 /* make and-mask lower */
5605 mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos);
5606 make_mask_and_or(mask,tmp,trn,crn,lrn);
5607 }
5608 code_lassign(adr,value);
5609 free_register(lvalue);
5610 free_register(adr);
5611 } else if (l==2) {
5612 int i;
5613 int tmpvar;
5614 // use_int(adr);
5615 use_longlong(value);
5616 lvalue = get_register();
5617 code_register(adr,lvalue); adr = lvalue;
5618 tmpvar=new_lvar(SIZE_OF_LONGLONG);
5619 code_lassign_lvar(tmpvar,value);
5620 trn = register_name(tmp = get_register());
5621
5622 /* make and-mask upper */
5623 i=bitpos;
5624 if (i)
5625 oprtc(LSHIFT,(value),list2(CONST,i));
5626 if (i<0||32<=i) error(-1);
5627 crn = lregister_name_low(value);
5628 code_ld(cload(0,0),(value),0,adr,cext_at(0,0));
5629 lrn = lregister_name_high(value);
5630 mask = make_mask(0,31-bitpos);
5631 make_mask_and_or(mask,tmp,trn,crn,lrn);
5632 printf("\t%s\t%s, 0(%s)\n",cstore(0),crn,register_name(adr));
5633 /*
5634 <-----bitsize--------------->
5635 hhhhhh mmmmmmmmmmmm lllllll
5636 lllll 00000000000 mmmmmmmmmmmm 0000000 hhhhhhh
5637 |-----||-----------||------------||-------||-------|
5638 <-bitpos--->
5639 <----------------bitsz----------------------------->
5640 <-----32----------> <---32------> <----32---------->
5641 */
5642 /* store middle */
5643 code_lrlvar(tmpvar,value);
5644 i=32-bitpos;
5645 if (i)
5646 loprtc(LRSHIFT,value,list2(CONST,i));
5647 if (i<0||64<=i) error(-1);
5648 printf("\t%s\t%s, 16(%s)\n",cstore(0),crn,register_name(adr));
5649
5650 /* make and-mask lower */
5651 code_ld(cload(0,0),(value),8,adr,cext_at(0,0));
5652 if (i<0||64<=i) error(-1);
5653 mask = make_mask(bitsz-bitpos-bitsize,31);
5654 make_mask_and_or(mask,tmp,trn,lrn,crn);
5655 printf("\t%s\t%s, 32(%s)\n",cstore(0),lrn,register_name(adr));
5656 free_lvar(tmpvar);
5657 free_register(adr);
5658 #endif
5659 } else {
5660 // use_int(adr);
5661 use_int(value);
5662 lvalue = get_register();
5663 code_ld(cload(size,sign),lvalue,0,adr,cext_at(0,0));
5664 crn = register_name(value);
5665 lrn = register_name(lvalue);
5666 /* shift left */
5667 if (bitpos)
5668 oprtc(LSHIFT,value,list2(CONST,bitpos));
5669 trn = register_name(tmp = get_register());
5670 /* make and-mask */
5671 mask = make_mask(32-bitpos-bitsize,31-bitpos);
5672 make_mask_and_or(mask,tmp,trn,crn,lrn);
5673 code_assign(adr,size,value);
5674 free_register(lvalue);
5675 }
5676 if (tmp!=-1) free_register(tmp);
5677 if (use) {
5678 code_bit_field(type,adr,USE_CREG);
5679 }
5680 }
5681
5682
5683 static void
5684 make_mask_and_or_const(int mask,char *crn,int c)
5685 {
5686 char *trn;
5687 int tmp = -1;
5688 int m;
5689 // printf("## mask 0x%08x ~0x%08x\n",mask,~mask);
5690 if ((m=(~mask|c))!=-1) {
5691 if (is_stage1_const(m,0)>0) {
5692 printf("\tand\t%s, %s, #%d\n",crn,crn,m);
5693 } else {
5694 trn = register_name(tmp=get_register());
5695 code_const((~mask|c),tmp);
5696 /* do conjunction */
5697 printf("\tand\t%s, %s, %s\n",crn,trn,crn);
5698 }
5699 }
5700 if (tmp!=-1) { free_register(tmp); tmp=-1; }
5701 /* make or-mask */
5702 c = mask&c;
5703 if (c!=0) {
5704 /* do disjunction */
5705 if (is_stage1_const(c,0)>0) {
5706 printf("\torr\t%s, %s, #%d\n",crn,crn,c);
5707 } else {
5708 trn = register_name(tmp=get_register());
5709 code_const(c,tmp);
5710 printf("\torr\t%s, %s, %s\n",crn,trn,crn);
5711 }
5712 }
5713 if (tmp!=-1) free_register(tmp);
5714 }
5715
5716 extern void
5717 code_bit_replace_const(int value,int adr,int type)
5718 {
5719 int sign,bitsz,l,align;
5720 int bitsize,bitpos,size;
5721 int mask = 0;
5722 int c;
5723 int lvalue;
5724 #if LONGLONG_CODE
5725 long long lc;
5726 int tmp;
5727 #endif
5728 char *crn;
5729 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l);
5730 size = bitsz/8;
5731 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
5732 if (l==1) {
5733 #if LONGLONG_CODE
5734 use_int(adr);
5735 lvalue = get_lregister();
5736 lload(adr,lvalue,0);
5737 crn = lregister_name_high(lvalue);
5738 /* shift left */
5739 lc = lcadr(value);
5740 lc <<= bitpos;
5741 if (bitpos+bitsize>=32) {
5742 /* make and-mask upper */
5743 mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31);
5744 make_mask_and_or_const(mask,crn,(int)(lc>>32));
5745 }
5746 crn = lregister_name_low(lvalue);
5747 if (bitpos<32) {
5748 /* make and-mask lower */
5749 mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos);
5750 make_mask_and_or_const(mask,crn,(int)lc);
5751 }
5752 code_lassign(adr,lvalue);
5753 free_register(adr);
5754 free_register(lvalue);
5755 } else if (l==2) { // three int container
5756 char *trn;
5757 /*
5758 hhhhhh mmmmmmmmmmmm lllllll
5759 lllll 00000000000 mmmmmmmmmmmm 0000000 hhhhhhh
5760 |-----||-----------||------------||-------||-------|
5761 */
5762 use_int(adr);
5763 crn = register_name(adr);
5764 trn = register_name(tmp = get_register());
5765 /* shift right */
5766 lc = lcadr(value);
5767 /* make and-mask upper */
5768 code_ld(cload(0,0),tmp,0,adr,cext_at(0,0));
5769 mask = make_mask(0,31-bitpos);
5770 make_mask_and_or_const(mask,trn,(int)(lc<<bitpos));
5771 printf("\t%s\t%s, 0(%s)\n",cstore(0),trn,crn);
5772 /* store middle */
5773 code_const((int)(lc>>(32-bitpos)),tmp);
5774 printf("\t%s\t%s, 16(%s)\n",cstore(0),trn,crn);
5775 /* make and-mask lower */
5776 code_ld(cload(0,0),tmp,8,adr,cext_at(0,0));
5777 mask = make_mask(bitsz-bitpos-bitsize,31);
5778 make_mask_and_or_const(mask,trn,(int)(lc>>(64-bitpos)));
5779 printf("\t%s\t%s, 32(%s)\n",cstore(0),trn,crn);
5780 free_register(tmp);
5781 #endif
5782 } else {
5783 use_int(adr);
5784 lvalue = get_register();
5785 code_ld(cload(size,sign),lvalue,0,adr,cext_at(0,0));
5786 crn = register_name(lvalue);
5787 /* shift left */
5788 c = cadr(value);
5789 c <<= bitpos;
5790 /* make and-mask */
5791 mask = make_mask(32-bitpos-bitsize,31-bitpos);
5792 make_mask_and_or_const(mask,crn,c);
5793 code_assign(adr,size,lvalue);
5794 free_register(lvalue);
5795 }
5796 if (use) {
5797 code_bit_field(type,adr,USE_CREG);
5798 }
5799 }
5800
5801
5802 #endif
5803
5804 /* end */