comparison mc-code-i64.c @ 731:1f6e34c4dbbf

INTEL64 (start)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 29 Oct 2010 16:14:00 +0900 (2010-10-29)
parents
children 7a4f389b5bc0
comparison
equal deleted inserted replaced
730:9bad72e27174 731:1f6e34c4dbbf
1 /* Micro-C Code Generation Part for intel386 */
2
3 /************************************************************************
4 ** Copyright (C) 2006 Shinji Kono
5 ** 連絡先: 琉球大学情報工学科 河野 真治
6 ** (E-Mail Address: kono@ie.u-ryukyu.ac.jp)
7 **
8 ** このソースのいかなる複写,改変,修正も許諾します。ただし、
9 ** その際には、誰が貢献したを示すこの部分を残すこと。
10 ** 再配布や雑誌の付録などの問い合わせも必要ありません。
11 ** 営利利用も上記に反しない範囲で許可します。
12 ** バイナリの配布の際にはversion messageを保存することを条件とします。
13 ** このプログラムについては特に何の保証もしない、悪しからず。
14 **
15 ** Everyone is permitted to do anything on this program
16 ** including copying, modifying, improving,
17 ** as long as you don't try to pretend that you wrote it.
18 ** i.e., the above copyright notice has to appear in all copies.
19 ** Binary distribution requires original version messages.
20 ** You don't have to ask before copying, redistribution or publishing.
21 ** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
22 ***********************************************************************/
23
24
25
26 #include <stdio.h>
27 #include "mc.h"
28 #include "mc-parse.h"
29 #include "mc-codegen.h"
30 #include "mc-code.h"
31
32 #ifdef __APPLE__
33 #define USE_SSE2
34 #define USE_PIC
35 #endif
36
37 #if defined(__GNUC__) && __GNUC__ >= 4
38
39 #include "mc-include.c"
40
41 static
42 char *init_src0 = "\
43 #define __DBL_MIN_EXP__ (-1021)
44 #define __FLT_MIN__ 1.17549435e-38F
45 #define __DEC64_DEN__ 0.000000000000001E-383DD
46 #define __CHAR_BIT__ 8
47 #define __WCHAR_MAX__ 2147483647
48 #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
49 #define __FLT_EVAL_METHOD__ 0
50 #define __DBL_MIN_10_EXP__ (-307)
51 #define __FINITE_MATH_ONLY__ 0
52 #define __DEC64_MAX_EXP__ 384
53 #define __SHRT_MAX__ 32767
54 #define __LDBL_MAX__ 1.18973149535723176502e+4932L
55 #define __APPLE_CC__ 5664
56 #define __UINTMAX_TYPE__ long unsigned int
57 #define __DEC32_EPSILON__ 1E-6DF
58 #define __SCHAR_MAX__ 127
59 #define __USER_LABEL_PREFIX__ _
60 #define __STDC_HOSTED__ 1
61 #define __DEC64_MIN_EXP__ (-383)
62 #define __DBL_DIG__ 15
63 #define __FLT_EPSILON__ 1.19209290e-7F
64 #define __LDBL_MIN__ 3.36210314311209350626e-4932L
65 #define __DEC32_MAX__ 9.999999E96DF
66 #define __strong
67 #define __APPLE__ 1
68 #define __DECIMAL_DIG__ 21
69 #define __LDBL_HAS_QUIET_NAN__ 1
70 #define __DYNAMIC__ 1
71 #define __GNUC__ 4
72 #define __MMX__ 1
73 #define __FLT_HAS_DENORM__ 1
74 #define __DBL_MAX__ 1.7976931348623157e+308
75 #define __DBL_HAS_INFINITY__ 1
76 #define __DEC32_MIN_EXP__ (-95)
77 #define OBJC_NEW_PROPERTIES 1
78 #define __STRICT_ANSI__ 1
79 #define __LDBL_HAS_DENORM__ 1
80 #define __DEC32_MIN__ 1E-95DF
81 #define __weak __attribute__((objc_gc(weak)))
82 #define __DBL_MAX_EXP__ 1024
83 #define __DEC128_EPSILON__ 1E-33DL
84 #define __SSE2_MATH__ 1
85 #define __amd64 1
86 #define __tune_core2__ 1
87 #define __LONG_LONG_MAX__ 9223372036854775807LL
88 #define __GXX_ABI_VERSION 1002
89 #define __FLT_MIN_EXP__ (-125)
90 #define __x86_64 1
91 #define __DBL_MIN__ 2.2250738585072014e-308
92 #define __LP64__ 1
93 #define __DBL_HAS_QUIET_NAN__ 1
94 #define __DEC128_MIN__ 1E-6143DL
95 #define __REGISTER_PREFIX__
96 #define __DBL_HAS_DENORM__ 1
97 #define __NO_INLINE__ 1
98 #define __DEC_EVAL_METHOD__ 2
99 #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
100 #define __FLT_MANT_DIG__ 24
101 #define __VERSION__ "4.2.1 (Apple Inc. build 5664)"
102 #define __DEC64_EPSILON__ 1E-15DD
103 #define __DEC128_MIN_EXP__ (-6143)
104 #define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 1064
105 #define __SIZE_TYPE__ long unsigned int
106 #define __DEC32_DEN__ 0.000001E-95DF
107 #define __FLT_RADIX__ 2
108 #define __LDBL_EPSILON__ 1.08420217248550443401e-19L
109 #define __SSE_MATH__ 1
110 #define __k8 1
111 #define __LDBL_DIG__ 18
112 #define __x86_64__ 1
113 #define __FLT_HAS_QUIET_NAN__ 1
114 #define __FLT_MAX_10_EXP__ 38
115 #define __LONG_MAX__ 9223372036854775807L
116 #define __FLT_HAS_INFINITY__ 1
117 #define __DEC64_MAX__ 9.999999999999999E384DD
118 #define __DEC64_MANT_DIG__ 16
119 #define __STDC_VERSION__ 199901L
120 #define __DEC32_MAX_EXP__ 96
121 #define __DEC128_DEN__ 0.000000000000000000000000000000001E-6143DL
122 #define __LITTLE_ENDIAN__ 1
123 #define __LDBL_MANT_DIG__ 64
124 #define __CONSTANT_CFSTRINGS__ 1
125 #define __DEC32_MANT_DIG__ 7
126 #define __k8__ 1
127 #define __WCHAR_TYPE__ int
128 #define __pic__ 2
129 #define __FLT_DIG__ 6
130 #define __INT_MAX__ 2147483647
131 #define __FLT_MAX_EXP__ 128
132 #define __DBL_MANT_DIG__ 53
133 #define __DEC64_MIN__ 1E-383DD
134 #define __WINT_TYPE__ int
135 #define __SSE__ 1
136 #define __LDBL_MIN_EXP__ (-16381)
137 #define __MACH__ 1
138 #define __amd64__ 1
139 #define __LDBL_MAX_EXP__ 16384
140 #define __SSP__ 1
141 #define __LDBL_MAX_10_EXP__ 4932
142 #define __DBL_EPSILON__ 2.2204460492503131e-16
143 #define _LP64 1
144 #define __GNUC_PATCHLEVEL__ 1
145 #define __LDBL_HAS_INFINITY__ 1
146 #define __GNUC_STDC_INLINE__ 1
147 #define __INTMAX_MAX__ 9223372036854775807L
148 #define __FLT_DENORM_MIN__ 1.40129846e-45F
149 #define __PIC__ 2
150 #define __FLT_MAX__ 3.40282347e+38F
151 #define __SSE2__ 1
152 #define __FLT_MIN_10_EXP__ (-37)
153 #define __INTMAX_TYPE__ long int
154 #define __DEC128_MAX_EXP__ 6144
155 #define __GNUC_MINOR__ 2
156 #define __DBL_MAX_10_EXP__ 308
157 #define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
158 #define __STDC__ 1
159 #define __PTRDIFF_TYPE__ long int
160 #define __DEC128_MANT_DIG__ 34
161 #define __LDBL_MIN_10_EXP__ (-4931)
162 #define __SSE3__ 1
163 "
164 #ifdef __APPLE__
165 "#define __APPLE__ 1\n"
166 "#define __GNUC__ 4\n"
167 "#define __BIG_ENDIAN__ 1\n"
168 #endif
169 ;
170
171 /*
172
173 #define size_t int\n\
174
175 */
176
177 #else
178
179 #include "mc-include.c"
180
181 #if defined(__GNUC__) && __GNUC__ >= 3
182 static
183 char *init_src0 = "\
184 #define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\
185 #define __builtin_va_arg(ap,type) (*((type *)ap)++)\n\
186 #define __builtin_va_end\n\
187 #define __i386__ 1\n\
188 #define __LITTLE_ENDIAN__ 1\n\
189 #define __STDC__ 1\n\
190 #define __extension__\n\
191 // #define __restrict\n\
192 #define __flexarr\n\
193 #define __const const\n\
194 #define __THORW\n\
195 // #define __attribute__(a)\n\
196 #define __inline__ inline\n\
197 #define __inline inline\n\
198 #define __GNUC__ 3\n\
199 #define __builtin_va_list int\n\
200 typedef long unsigned int __SIZE_TYPE__ ;\n\
201 "
202
203 #else
204 static
205 char *init_src0 = "\
206 #define va_list int\n\
207 #define va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\
208 #define va_arg(ap,type) (*((type *)ap)++)\n\
209 #define va_end\n\
210 #define __i386__ 1\n\
211 #define __LITTLE_ENDIAN__ 1\n\
212 #define __STDC__ 1\n\
213 #define __extension__\n\
214 // #define __restrict\n\
215 #define __flexarr\n\
216 #define __const const\n\
217 #define __THORW\n\
218 // #define __attribute__(a)\n\
219 #define __inline__ inline\n\
220 #define __SIZE_TYPE__ long unsigned int\n\
221 #define __GNUC__ 3\n\
222 "
223
224 #endif
225
226
227 ;
228
229 #endif
230
231 int data_alignment = 0;
232
233 #define SIZE_OF_INT 4
234 #define SIZE_OF_SHORT 2
235 #define SIZE_OF_FLOAT 4
236 #define SIZE_OF_DOUBLE 8
237 #define SIZE_OF_LONGLONG 8
238 #define ENDIAN 0
239 #define ENDIAN_L 0
240 #define ENDIAN_D 0
241
242 int eval_order = REVERSE;
243
244 #define TEXT_EMIT_MODE 0
245 #define DATA_EMIT_MODE 1
246 #define RODATA_EMIT_MODE 2
247
248 #ifdef __APPLE__
249 #else
250 #define DOT_SIZE 1
251 #endif
252
253 static int output_mode = TEXT_EMIT_MODE;
254
255 static int creg;
256 static int ireg;
257 static int lreg;
258
259 extern int lp64;
260
261 #define regv_l(r) (r==REG_L?REG_ESI:REG_EAX)
262 #define regv_h(r) (r==REG_L?REG_EDI:REG_EDX)
263
264 int code_lassop_p = 0;
265
266 #define MAX_REGISTER 14 /* intel386のレジスタを6つまで使う*/
267 #define REAL_MAX_REGISTER 16 /* intel386のレジスタが8つということ*/
268 static int MAX_DATA_REG=8;
269 static int MAX_POINTER=8;
270 int MAX_REGISTER_VAR=8;
271 // static int MAX_FREGISTER=1;
272
273 #define MAX_FPU_STACK 7
274
275 // static int MAX_INPUT_REGISTER_VAR = 0;
276 int MAX_CODE_INPUT_REGISTER_VAR = 6;
277 static int MAX_INPUT_DREGISTER_VAR = 6;
278 // static int MAX_INPUT_FREGISTER_VAR = 0;
279 static int MAX_CODE_INPUT_DREGISTER_VAR = 6;
280
281 static int reg_sp; /* REGister Stack-Pointer */
282 static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
283 static int stack_depth = 0;
284
285 /* floating point registers */
286
287 static int freg_sp; /* floating point REGister Stack-Pointer */
288 static int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */
289
290 static int reg_var;
291
292
293 /*
294 local2 -8
295 local1 <-- -6 0 local variable
296 %edi -12 <- disp_offset %ebp
297 %esi -8
298 %ebx -4
299 %ebp = %esp 0
300 %eip 4 <- arg_offset
301 arg7 8
302 %r9d arg6
303 %r8d arg5
304 %ecx arg4
305 %edx arg3
306 %esi arg2
307 %rdi arg1
308 see enter/enter1/leave see code_enter
309 */
310 // static int arg_offset;
311
312 static int code_disp_label;
313
314 #ifdef __APPLE__
315 static int goffset_label;
316 #endif
317
318
319 /*
320 creg current register
321 ireg current register for integer (int mode)
322 lreg current register for long long (long long mode)
323
324 regs[] register usage
325
326 freg current floating point register
327 kept in FPU stack (no register)
328 */
329
330 #define REAL_MAX_LREGISTER 2
331 static int ia32regs[1+REAL_MAX_REGISTER+REAL_MAX_LREGISTER];
332
333
334 static int *regs = ia32regs;
335
336 static int ia32fregs[1];
337 static int *fregs = ia32fregs;
338 static int freg;
339
340 // register number should start 1
341 // regs[] value
342 // 0 for not ready
343 // -1 use currrent register
344 // 1 used
345 // 2 (REG_VAR) register variable
346 // 3 pointer cache (not used in ia32)
347
348 #define REG_EBP 1
349 #define REG_ESP 2
350 #define REG_EDI 3 // first argument register
351 #define REG_ESI 4
352 #define REG_EDX 5
353 #define REG_ECX 6 // for strange reason (code_assop)
354 #define REG_EAX 7
355 #define REG_EBX 8
356 #define is_int_reg(reg) 1 // (1<=reg&&reg<REG_EBP)
357
358 // return value register
359 #define RET_FREGISTER
360 #define RET_DREGISTER
361 #define RET_LREGISTER REG_LCREG
362 #define RET_REGISTER REG_EAX
363
364 // defalut current register
365 #define CREG_REGISTER REG_ECX
366 #define FREG_FREGISTER 0
367
368 static char *reg_name[8+1];
369 static char *reg_name_l[4+1];
370 static char *reg_name_w[4+1];
371
372 static void ascii(char *s);
373
374 static int use_register(int virt, int real, int move);
375 static void shift(char *op, int reg,int creg);
376 static void ld_indexx(int byte, int n, int xreg,int reg,int sign);
377 //static void data_mode(char *name);
378 // static void text_mode(int align);
379 static int get_data_register(void);
380
381 static void local_table(void);
382 static int push_struct(int e4,int t, int arg) ;
383 static void code_clear_stack_reg(int reg1);
384 #if FLOAT_CODE
385 static char * fload(int d);
386 static int code_d1(double d);
387 static int code_d2(double d);
388 static void code_save_fstacks();
389 #endif
390 static void jcond(int l, char cond);
391 #if LONGLONG_CODE
392 static int code_l1(long long d);
393 static int code_l2(long long d);
394 #endif
395
396 #define round16(i) align(i,16)
397 #define round4(i) align(i,4)
398
399
400 #define func_disp_offset (16)
401 #define code_disp_offset (16)
402
403 #define arg_offset 8
404 #define arg_offset1 0
405 #define ARG_LVAR_OFFSET 0x10000000
406
407 #define code_disp_offset0 (-16)
408 // disp_offset
409 int disp_offset = code_disp_offset0;
410
411 #define CODE_LVAR(l) ((l)+code_disp_offset0)
412 #define CODE_CALLER_ARG(l) ((l)+arg_offset1)
413 #define FUNC_LVAR(l) ((l)-func_disp_offset)
414 #define CALLER_ARG(l) ((l)+arg_offset1)
415 #define CALLEE_ARG(l) ((l)+arg_offset)
416 static int r1_offset_label;
417 static const char lpfx[] = "_";
418 // static int lvar_offset_label;
419 static int max_func_args,max_func_arg_label;
420
421 /*
422 function call stack frame
423 prev esp
424 <-------r1_offset------------------------------>
425 <----- ebp--> <----- esp
426 r+ +------------+---+---------------+----------+-------------------+ -
427 callee arg xx register save local caller arg
428 reg_save disp max_func_args*SIZE_OF_INT
429 lvar>0 lvar<0 lvar>0x1000 0000
430
431 code segment stack frame
432
433 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
434 disp_offset
435 # * ebp <---r1_offset---------> esp
436 r+ +----------+--+----------+----------------+-----------+----------+----+
437 cousin arg xx reg save !callee arg !code local caller arg xx
438 r20-r29 lvar>0 lvar<0 lvar>0x1000 000
439 f20-f31 <-my_func_args--><--disp-----><-max_func_arg->
440 *SIZE_OF_INT *SIZE_OF_INT
441
442 %esp should be alignment 16
443
444 */
445
446 void
447 code_offset_set(NMTBL *fnptr)
448 {
449 #if 0
450 int l;
451 #endif
452 int code_f = is_code(fnptr);
453 int lvar_offsetv = round16(-disp);
454 int r1_offsetv = round16(lvar_offsetv+max_func_args*SIZE_OF_INT+func_disp_offset)+8;
455
456 if (code_f) {
457 printf("\t.set _%d,%d\n",code_disp_label,r1_offsetv);
458 } else {
459 // +8 makes esp alignment 16
460 // printf(".set %s%d,%d\n",lpfx,lvar_offset_label,lvar_offsetv);
461 if (r1_offsetv-lvar_offsetv > 65000) error(-1);
462 // too large function arguments?
463 printf(".set %s%d,%d\n",lpfx,r1_offset_label,r1_offsetv);
464 }
465 if (max_func_arg_label) {
466 printf(".set %s%d,%d\n",lpfx,max_func_arg_label,
467 round16(max_func_args*SIZE_OF_INT));
468 max_func_arg_label = 0;
469 }
470
471 #if 0
472 printf("## reg_save %d\n",reg_save);
473 printf("## function %s\n",fnptr->nm);
474 l = ARG_LVAR_OFFSET;
475 printf("## offset call0\t%d\n",CALLER_ARG);
476 l = ARG_LVAR_OFFSET+max_func_args*SIZE_OF_INT;
477 printf("## offset calln\t%d %d\n",CALLER_ARG,max_func_args*SIZE_OF_INT);
478 l = disp;
479 printf("## offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp);
480 l = 0;
481 printf("## offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv);
482 l = -reg_save;
483 printf("## offset regs\t%d\n",FUNC_LVAR+lvar_offsetv);
484 printf("## offset r1off\t%d\n",r1_offsetv);
485 l = 0;
486 printf("## offset carg0\t%d\n",CALLEE_ARG+r1_offsetv);
487 l = my_func_args;
488 printf("## offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args);
489 #endif
490 }
491
492
493 static void
494 lvar(int l)
495 {
496 if (is_code(fnptr)) {
497 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
498 printf("%d(%%esp)",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET));
499 } else
500 printf("%d(%%ebp)",CODE_LVAR(l));
501 } else if (l<0) { /* local variable */
502 printf("%d(%%ebp)",FUNC_LVAR(l));
503 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */
504 printf("%d(%%esp)",CALLER_ARG(l-ARG_LVAR_OFFSET));
505 } else { /* callee's arguments */
506 printf("%d(%%ebp)",CALLEE_ARG(l));
507 }
508 }
509
510
511 #define use_int(reg) if (reg==-1) reg=use_int0()
512
513 static int
514 use_int0() {
515 int i = creg;
516 if (!i||!ireg||!is_int_reg(i)) {
517 if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; }
518 if (!ireg) {
519 ireg = get_register();
520 }
521 i = ireg;
522 }
523 if (!regs[i]) regs[i]=USING_REG;
524 creg = ireg = i;
525 return i;
526 }
527
528 #define is_data_reg(reg) (REG_EAX<=reg&&reg<=REG_EDX)
529 #define is_pointer_reg(reg) (REG_ESI<=reg&&reg<=REG_EBP)
530
531 static int
532 use_register(int reg0, int reg1, int move)
533 {
534 /*
535 reg0 becomes reg1, if (move) copy the content.
536 if reg1 is used, reg0 contains old value.
537 */
538
539 char *move_op;
540 code_clear_stack_reg(reg1);
541 move_op = (regs[reg1]||regs[reg1])?"\txchg %s,%s\n":"\tmovl %s,%s\n";
542 if (move && reg0!=reg1) {
543 printf(move_op,reg_name[reg0],reg_name[reg1]);
544 if (!regs[reg1]) regs[reg1]=USING_REG;
545 }
546 return reg0;
547 }
548
549 #define use_data_reg(reg,keep) \
550 if (reg==-1||!is_data_reg(reg)) reg=use_data_reg0(keep,reg)
551
552 int
553 use_data_reg0(int keep,int reg)
554 {
555 int ptreg =0;
556 int i;
557 if (is_pointer_reg(creg)) {
558 free_register(ptreg=creg);
559 ireg = creg = 0;
560 }
561 if (is_pointer_reg(ireg)) {
562 free_register(ireg);
563 ireg = 0;
564 }
565 i = reg==USING_REG?creg:reg;
566 #ifdef __APPLE__
567 if (regs[i]==PTRC_REG) clear_ptr_cache_reg(i);
568 #endif
569 if (!i||!ireg||!is_data_reg(i)) {
570 if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; }
571 if (!ireg) {
572 ireg = get_data_register();
573 }
574 i = ireg;
575 }
576 if (!regs[i]) regs[i]=USING_REG;
577 creg = ireg = i;
578 if (ptreg && keep) {
579 printf("\tmovl %s,%s\n",reg_name[ptreg],reg_name[creg]);
580 }
581 return i;
582 }
583
584 static void
585 set_freg(int reg,int mode)
586 {
587 }
588
589 static void
590 set_ireg(int reg,int mode)
591 {
592 if (!is_int_reg(reg)) error(-1);
593 if (reg!=creg) {
594 #ifdef __APPLE__
595 if (regs[reg]==PTRC_REG)
596 clear_ptr_cache_reg(reg);
597 #endif
598 if (ireg && reg!=ireg ) {
599 if (regs[ireg]!=REG_VAR) free_register(ireg);
600 if (mode) {
601 printf("\tmovl %s,%s\n",reg_name[ireg],reg_name[reg]);
602 }
603 }
604 if (creg>0 && regs[creg]!=REG_VAR) free_register(creg);
605 if (creg==lreg) lreg = 0;
606 }
607 creg = ireg = reg;
608 if (!regs[reg]) regs[reg]=USING_REG;
609 }
610
611 #define is_long_reg(reg) (reg==REG_LCREG||reg==REG_L)
612 #define use_longlong(reg) \
613 if (reg==-1||is_long_reg(reg)) reg=use_longlong0(reg)
614
615 static int
616 use_longlong0(int reg)
617 {
618 int i = reg==USING_REG?creg:reg;
619 if (ireg) { if (regs[ireg]!=REG_VAR) free_register(ireg); ireg=0; }
620 if (!lreg||!regs[lreg]) {
621 // long long mode use all registers
622 code_save_stacks();
623 #ifdef __APPLE__
624 clear_ptr_cache();
625 #endif
626 }
627 i = lreg = (reg==USE_CREG)?REG_LCREG:reg;
628 if (!regs[i]) regs[i]=USING_REG;
629 if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG;
630 if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG;
631 creg = lreg = i;
632 return i;
633 }
634
635 static void
636 set_lreg(int reg,int mode)
637 {
638 use_longlong(reg);
639 }
640
641 char *
642 l_edx(int i) {
643 return i==REG_L?"%edi":"%edx";
644 }
645 char *
646 l_eax(int i) {
647 return i==REG_L?"%esi":"%eax";
648 }
649
650 extern void
651 code_init(void)
652 {
653
654 /* called only once */
655
656 init_src = init_src0;
657 size_of_int = SIZE_OF_INT;
658 size_of_pointer = SIZE_OF_INT;
659 size_of_short = SIZE_OF_SHORT;
660 size_of_float = SIZE_OF_FLOAT;
661 size_of_double = SIZE_OF_DOUBLE;
662 size_of_longlong = SIZE_OF_LONGLONG;
663 endian = ENDIAN;
664 lp64 = 1;
665 struct_align = size_of_int;
666
667
668 // MAX_REGISTER=6;
669 MAX_DATA_REG=4;
670 MAX_POINTER=3;
671 MAX_REGISTER_VAR=2;
672
673 reg_name[REG_EAX] = "%eax";
674 reg_name[REG_EBX] = "%ebx";
675 reg_name[REG_ECX] = "%ecx";
676 reg_name[REG_EDX] = "%edx";
677 reg_name[REG_ESI] = "%esi";
678 reg_name[REG_EDI] = "%edi";
679 reg_name[REG_EBP] = "%ebp";
680 reg_name[REG_ESP] = "%esp";
681 reg_name_l[REG_EAX] = "%al";
682 reg_name_l[REG_EBX] = "%bl";
683 reg_name_l[REG_ECX] = "%cl";
684 reg_name_l[REG_EDX] = "%dl";
685 reg_name_w[REG_EAX] = "%ax";
686 reg_name_w[REG_EBX] = "%bx";
687 reg_name_w[REG_ECX] = "%cx";
688 reg_name_w[REG_EDX] = "%dx";
689
690 }
691
692 extern void
693 emit_reinit()
694 {
695 /* called for each file */
696 output_mode = -1;
697 #ifdef __APPLE__
698 init_ptr_cache();
699 #endif
700 }
701
702
703 char *
704 register_name(int i,int byte)
705 {
706 if (i<=0) {
707 error(REG_ERR);
708 return "%eax";
709 }
710 if (byte==1 && i <= REG_EDX) {
711 return reg_name_l[i];
712 } else if (byte==SIZE_OF_SHORT && i <= REG_EDX) {
713 return reg_name_w[i];
714 } else {
715 return reg_name[i]; /* 0 or 4 means int */
716 }
717 }
718
719 void
720 gexpr_code_init(void){
721 // use_register(creg,REG_EAX,0);
722 set_ireg(CREG_REGISTER,0);
723 }
724
725 void
726 code_gexpr(int e){
727 if ((is_int_reg(creg))&&regs[creg]==REG_VAR)
728 creg = ireg = 0;
729 else if ((creg==REG_L)&&regs[creg]==REG_VAR)
730 creg = lreg = 0;
731 }
732
733 int
734 get_register(void)
735 { /* 使われていないレジスタを調べる */
736 int i,reg,j;
737 for(i=1;i<MAX_REGISTER+1;i++) {
738 if (! regs[i]) { /* 使われていないなら */
739 regs[i]=1; /* そのレジスタを使うことを宣言し */
740 return i; /* その場所を表す番号を返す */
741 }
742 }
743 #ifdef __APPLE__
744 /* PTR_CACHE をつぶす */
745 if ((i=last_ptr_cache())) {
746 clear_ptr_cache_reg(i);
747 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */
748 return i; /* その場所を表す番号を返す */
749 }
750 #endif
751 /* search register stack */
752 for(i=0;i<reg_sp;i++) {
753 if ((reg=reg_stack[i])>=0) {
754 code_assign_lvar(
755 (j=new_lvar(SIZE_OF_INT)),reg,0);
756 reg_stack[i]= j-REG_LVAR_OFFSET;
757 return reg;
758 }
759 }
760 error(RGERR);
761 return -1; /* 空いている場所がないなら、それを表す -1 を返す */
762 }
763
764 static int
765 get_data_register(void)
766 { /* 使われていないレジスタを調べる */
767 int i,reg,j;
768 for(i=REG_EAX;i<=REG_EDX;i++) {
769 if (! regs[i]) { /* 使われていないなら */
770 regs[i]=1; /* そのレジスタを使うことを宣言し */
771 return i; /* その場所を表す番号を返す */
772 }
773 }
774 #ifdef __APPLE__
775 /* PTR_CACHE をつぶす */
776 while ((i=last_ptr_cache())) {
777 clear_ptr_cache_reg(i);
778 if (is_data_reg(i)) {
779 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */
780 return i; /* その場所を表す番号を返す */
781 }
782 }
783 #endif
784 /* search register stack */
785 for(i=0;i<reg_sp;i++) {
786 if (is_data_reg(i) && (reg=reg_stack[i])>=0) {
787 code_assign_lvar(
788 (j=new_lvar(SIZE_OF_INT)),reg,0);
789 reg_stack[i]= j-REG_LVAR_OFFSET;
790 return reg;
791 }
792 }
793 error(-1);
794 return -1; /* 空いている場所がないなら、それを表す -1 を返す */
795 }
796
797 void
798 free_register(int i) { /* いらなくなったレジスタを開放 */
799 if (i==REG_L) {
800 reg_var=0;
801 regs[REG_ESI]=regs[REG_EDI]=0;
802 } else if (regs[i]==REG_VAR) { reg_var--;
803 } else if(i==REG_LCREG) { //? REG_L?
804 regs[REG_EAX]=regs[REG_EDX]=0;
805 }
806 regs[i]=0;
807 }
808
809 extern void
810 use_ptr_cache(int r)
811 {
812 #ifdef __APPLE__
813 regs[r]=PTRC_REG;
814 #else
815 error(-1);
816 #endif
817 }
818
819 extern void
820 code_ptr_cache_def(int r,NMTBL *nptr)
821 {
822 #ifdef __APPLE__
823 char *rrn = register_name(r,0);
824 if (nptr->sc==STATIC && !(is_code(nptr)||is_function(nptr))) {
825 printf("\tleal _%s-_%d(%%ebx),%s\n",nptr->nm,
826 goffset_label,rrn);
827 } else {
828 printf("\tmovl L_%s$non_lazy_ptr-_%d(%%ebx),%s\n",
829 nptr->nm,
830 goffset_label,rrn);
831 }
832 #else
833 error(-1);
834 #endif
835 }
836
837 /*
838 ESI,EDI are used as register variable
839 (both in integer and long long mode)
840 */
841
842 int
843 get_input_register_var(int i,NMTBL *nptr,int is_code)
844 {
845 if (is_code) {
846 if (i>=MAX_CODE_INPUT_REGISTER_VAR) return 0;
847 i += REG_EDI;
848 regs[i]=INPUT_REG;
849 return list3n(REGISTER,i,nptr);
850 } else {
851 if (i>=MAX_INPUT_REGISTER_VAR) return 0;
852 i += REG_EDI;
853 regs[i]=INPUT_REG;
854 return list3n(REGISTER,i,nptr);
855 }
856 }
857
858 int
859 get_input_dregister_var(int i,NMTBL *nptr,int is_code,int d)
860 {
861 return 0;
862 }
863
864 int
865 get_input_lregister_var(int i,NMTBL *nptr,int is_code)
866 {
867 int h,l;
868 if (is_code) {
869 if (i+1>=MAX_CODE_INPUT_REGISTER_VAR) return 0;
870 h = REG_ESI;
871 l = REG_EDI;
872 regs[h]=regs[l]=INPUT_REG;
873 return list2(LREGISTER,REG_L);
874 }
875 return 0;
876 }
877
878 int
879 get_dregister(int d)
880 {
881 return -1;
882 }
883
884 int
885 get_lregister_var(NMTBL *n)
886 {
887 int h,l;
888 h = REG_ESI;
889 l = REG_EDI;
890 if (regs[h]==0&&regs[l]==0) {
891 regs[h]=regs[l]=REG_VAR; regs[REG_L]=REG_VAR;
892 reg_var=2;
893 return list2(LREGISTER,REG_L);
894 }
895 return list3n(LVAR,new_lvar(SIZE_OF_LONGLONG),0);
896 }
897
898 int
899 get_lregister()
900 {
901 return -1;
902 }
903
904
905 int
906 register_full(void)
907 {
908 int i;
909 for(i=1;i<MAX_REGISTER+1;i++) {
910 if (! regs[i]) {
911 return 0;
912 }
913 }
914 return 1;
915 }
916
917 int
918 free_register_count(int d)
919 {
920 int i,count;
921 count = 0;
922 for(i=1;i<MAX_REGISTER+1;i++) {
923 if (! regs[i]) count++;
924 }
925 return d?0:count;
926 }
927
928 void
929 free_all_register(void)
930 {
931 int i;
932 for(i=1;i<MAX_REGISTER+REAL_MAX_LREGISTER+1;i++) {
933 regs[i]=0;
934 }
935 lreg = creg = ireg = 0;
936 reg_var = 0;
937 return;
938 }
939
940 extern int
941 code_register_overlap(int s,int t)
942 {
943 if (car(s)==REGISTER) {
944 if (car(t)==REGISTER) return cadr(s)==cadr(t);
945 if (car(t)==LREGISTER)
946 return cadr(s)==REG_ESI|| cadr(s)==REG_EDI;
947 } else if (car(s)==LREGISTER) {
948 if (car(t)==LREGISTER) return 1;
949 if (car(t)==REGISTER)
950 return cadr(t)==REG_ESI|| cadr(t)==REG_EDI;
951 }
952 return 0;
953 }
954
955 void
956 register_usage(char *s)
957 {
958 int i;
959 printf("## %d: %s:",lineno,s);
960 if (creg) printf(" creg=%s ",register_name(creg,0));
961 for(i=1;i<MAX_REGISTER+1;i++) {
962 printf("%d",regs[i]);
963 }
964 #if 0
965 printf(" regs_stack",register_name(creg,0);
966 for(i=reg_sp;i>=0;i--) {
967 if(reg_stack[i]>=0)
968 printf(" %s",register_name(reg_stack[i],0));
969 }
970 #endif
971 printf("## f:%d",freg_sp);
972 printf("\n");
973 }
974
975 void
976 code_arg_register(NMTBL *fnptr)
977 {
978 int args = fnptr->dsp;
979 NMTBL *n;
980 int reg_var = 0;
981 int freg_var = 0;
982 int type;
983 int reg;
984 int offset = 0;
985 int is_code0 = is_code(fnptr);
986
987 while (args) {
988 /* process in reverse order */
989 n = ncadddr(args);
990 type = n->ty;
991 // n->dsp = offset;
992 // printf("### %s %d %d\n",n->nm,n->dsp,n->ty);
993 if (scalar(type)) {
994 if ((reg = get_input_register_var(reg_var,n,is_code0))) {
995 n->sc = REGISTER;
996 n->dsp = cadr(reg);
997 regs[n->dsp]= INPUT_REG;
998 reg_var++;
999 caddr(args)=SIZE_OF_INT; /* why we need this? */
1000 }
1001 offset+=SIZE_OF_INT;
1002 } else if (type==FLOAT||type==DOUBLE) {
1003 if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) {
1004 n->sc = DREGISTER;
1005 n->dsp = cadr(reg);
1006 fregs[n->dsp]= INPUT_REG;
1007 freg_var++;
1008 caddr(args)=size(type); /* why we need this? */
1009 }
1010 offset+=size(type);
1011 } else
1012 offset+=size(type);
1013 args = cadr(args);
1014 }
1015 }
1016
1017 void
1018 gexpr_init(void)
1019 {
1020 text_mode(0);
1021 if (reg_sp>0) error(-1);
1022 if (freg_sp>0) error(-1);
1023 reg_sp = 0;
1024 freg_sp = 0;
1025 stack_depth = 0;
1026 gexpr_code_init();
1027 regs[creg]=1;
1028 register_usage("gexpr_init");
1029 }
1030
1031
1032 void
1033 emit_init(void)
1034 {
1035 int i;
1036 for(i=1;i<REAL_MAX_REGISTER+1;i++) regs[i]=0;
1037 free_all_register();
1038 reg_sp = 0;
1039 freg_sp = 0;
1040 }
1041
1042 int
1043 pop_register(void)
1044 { /* レジスタから値を取り出す */
1045 return reg_stack[--reg_sp];
1046 }
1047
1048 void
1049 emit_pop_free(int xreg)
1050 {
1051 if (xreg>=0 && xreg!=creg && regs[xreg]!=REG_VAR) {
1052 free_register(xreg);
1053 }
1054 }
1055
1056
1057 int
1058 get_register_var(NMTBL *nptr)
1059 {
1060 int i;
1061 for(i=REG_ESI;i<REG_EBP;i++) {
1062 if (! regs[i]) { /* 使われていないなら */
1063 regs[i]=REG_VAR; /* そのレジスタを使うことを宣言し */
1064 return list3n(REGISTER,i,nptr); /* その場所を表す番号を返す */
1065 }
1066 }
1067 return list3n(LVAR,new_lvar(SIZE_OF_INT),0);
1068 }
1069
1070 int
1071 get_dregister_var(NMTBL *nptr,int d)
1072 {
1073 return list3n(LVAR,new_lvar(d?SIZE_OF_DOUBLE:SIZE_OF_FLOAT),0);
1074 }
1075
1076
1077 int
1078 emit_push()
1079 {
1080 int new_reg,old;
1081 new_reg = get_register(); /* 絶対に取れる */
1082 // who free new_reg?
1083 if (new_reg==creg) error(-1);
1084 old = creg;
1085 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */
1086 ireg = creg = new_reg;
1087 if (!regs[creg]) regs[creg]=USING_REG;
1088 return old;
1089 }
1090
1091 int
1092 emit_pop(int type)
1093 {
1094 int xreg,reg;
1095 xreg=pop_register();
1096 if (xreg<= -REG_LVAR_OFFSET) {
1097 reg = get_register();
1098 code_rlvar(REG_LVAR_OFFSET+xreg,reg);
1099 free_lvar(REG_LVAR_OFFSET+xreg);
1100 xreg = reg;
1101 }
1102 return xreg;
1103 }
1104
1105 void
1106 code_label(int labelno)
1107 {
1108 #ifdef __APPLE__
1109 clear_ptr_cache();
1110 #endif
1111 printf("_%d:\n",labelno);
1112 }
1113
1114 void
1115 code_gvar(int e1,int creg) {
1116 use_int(creg);
1117 #ifdef __APPLE__
1118 int r = get_ptr_cache(ncaddr(e1));
1119 if (cadr(e1)) {
1120 printf("\tleal %d(%s),%s\n", cadr(e1),register_name(r,0),
1121 register_name(creg,0));
1122 } else {
1123 printf("\tmovl %s,%s\n", register_name(r,0), register_name(creg,0));
1124 }
1125 #else
1126 if (cadr(e1)) {
1127 printf("\tmovl $%s+%d,%s\n",(ncaddr(e1))->nm,cadr(e1),
1128 register_name(creg,0));
1129 } else {
1130 printf("\tmovl $%s,%s\n",(ncaddr(e1))->nm,register_name(creg,0));
1131 }
1132 #endif
1133
1134 }
1135
1136 void
1137 code_rgvar(int e1,int creg) {
1138 use_int(creg);
1139 #ifdef __APPLE__
1140 int r = get_ptr_cache(ncaddr(e1));
1141 if (cadr(e1)) {
1142 printf("\tmovl %d(%s),%s\n", cadr(e1),register_name(r,0),
1143 register_name(creg,0));
1144 } else {
1145 printf("\tmovl (%s),%s\n", register_name(r,0), register_name(creg,0));
1146 }
1147 #else
1148 if (cadr(e1)) {
1149 printf("\tmovl %s+%d,%s\n",(ncaddr(e1))->nm,cadr(e1),
1150 register_name(creg,0));
1151 } else
1152 printf("\tmovl %s,%s\n",(ncaddr(e1))->nm,register_name(creg,0));
1153 #endif
1154
1155 }
1156
1157 static char *
1158 cload(int sign,int sz) {
1159 return sz==1?(sign?"movsbl":"movzbl"):
1160 sz==SIZE_OF_SHORT?(sign?"movswl":"movzwl"):"movl";
1161 }
1162
1163 void
1164 code_crgvar(int e1,int creg,int sign,int sz){
1165 use_int(creg);
1166 #ifdef __APPLE__
1167 int r = get_ptr_cache(ncaddr(e1));
1168 if (cadr(e1)) {
1169 printf("\t%s %d(%s),%s\n", cload(sign,sz),cadr(e1),register_name(r,0),
1170 register_name(creg,0));
1171 } else {
1172 printf("\t%s (%s),%s\n", cload(sign,sz),
1173 register_name(r,0), register_name(creg,0));
1174 }
1175 #else
1176 if (cadr(e1)) {
1177 printf("\t%s %s+%d,%s\n",cload(sign,sz),
1178 (ncaddr(e1))->nm,cadr(e1),register_name(creg,0));
1179 } else
1180 printf("\t%s %s,%s\n",cload(sign,sz),
1181 (ncaddr(e1))->nm,register_name(creg,0));
1182 #endif
1183
1184 }
1185
1186
1187 void
1188 code_lvar(int e2,int creg) {
1189 use_int(creg);
1190 printf("\tlea "); lvar(e2);
1191 printf(",%s\n",register_name(creg,0));
1192 }
1193
1194
1195 void
1196 code_register(int e2,int creg) {
1197 use_int(creg);
1198 if (e2!=creg)
1199 printf("\tmovl %s,%s\n",register_name(e2,0),register_name(creg,0));
1200 }
1201
1202
1203 void
1204 code_rlvar(int e2,int reg) {
1205 use_int(reg);
1206 printf("\tmovl "); lvar(e2);
1207 printf(",%s\n",register_name(reg,0));
1208 }
1209
1210 extern void
1211 code_i2c(int reg)
1212 {
1213 use_data_reg(reg,1);
1214 printf("\t%s %s,%s\n",cload(1,1),
1215 register_name(reg,1),register_name(reg,0));
1216 }
1217
1218 extern void
1219 code_i2s(int reg)
1220 {
1221 use_data_reg(reg,1);
1222 printf("\t%s %s,%s\n",cload(1,SIZE_OF_SHORT),
1223 register_name(reg,2),register_name(reg,0));
1224 }
1225
1226 extern void
1227 code_u2uc(int reg)
1228 {
1229 use_data_reg(reg,1);
1230 printf("\t%s %s,%s\n",cload(0,1),
1231 register_name(reg,1),register_name(reg,0));
1232 }
1233
1234 extern void
1235 code_u2us(int reg)
1236 {
1237 use_data_reg(reg,1);
1238 printf("\t%s %s,%s\n",cload(0,SIZE_OF_SHORT),
1239 register_name(reg,2),register_name(reg,0));
1240 }
1241
1242 void
1243 code_crlvar(int e2,int reg,int sign,int sz) {
1244 use_int(reg);
1245 printf("\t%s ",cload(sign,sz)); lvar(e2);
1246 printf(",%s\n",register_name(reg,0));
1247
1248 }
1249
1250
1251 void
1252 code_fname(NMTBL *n,int creg) {
1253 use_int(creg);
1254 #ifdef __APPLE__
1255 if (n->sc==STATIC) {
1256 printf("\tleal _%s-_%d(%%ebx),%s\n", n->nm, goffset_label,
1257 register_name(creg,0));
1258 return;
1259 }
1260 int r = get_ptr_cache(n);
1261 printf("\tmovl %s,%s\n", register_name(r,0), register_name(creg,0));
1262 #else
1263 printf("\tmovl $%s,%s\n",n->nm,register_name(creg,0));
1264 #endif
1265 }
1266
1267 void
1268 code_label_value(int label,int reg) {
1269 use_int(reg);
1270 #ifdef __APPLE__
1271 printf("\tleal _%d-_%d(%%ebx),%s\n",
1272 label,goffset_label,register_name(reg,0));
1273 #else
1274 printf("\tleal _%d,%s\n",label,register_name(reg,0));
1275 #endif
1276 }
1277
1278 void
1279 code_const(int e2,int creg) {
1280 use_int(creg);
1281 printf("\tmovl $%d,%s\n",e2,register_name(creg,0));
1282 }
1283
1284 void
1285 code_neg(int creg) {
1286 use_int(creg);
1287 printf("\tnegl %s\n", register_name(creg,0));
1288 }
1289
1290
1291 void
1292 code_not(int creg) {
1293 use_int(creg);
1294 printf("\tnotl %s\n", register_name(creg,0));
1295 }
1296
1297
1298 void
1299 code_lnot(int creg) {
1300 char *xrn;
1301
1302 use_data_reg(creg,1);
1303 xrn = register_name(creg,1);
1304 printf("\tcmpl $0,%s\n", register_name(creg,0));
1305 printf("\tsete %s\n", xrn);
1306 printf("\tmovzbl %s,%s\n", xrn,register_name(creg,0));
1307 }
1308
1309 void
1310 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) {
1311 char *xrn;
1312 if (car(e2)==REGISTER) {
1313 use_int(reg);
1314 printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0));
1315 if (use)
1316 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0));
1317 return;
1318 }
1319 g_expr(e2);
1320 xrn = register_name(creg,0);
1321 use_int(reg);
1322 printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn);
1323 if (use)
1324 printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0));
1325 }
1326
1327
1328 void
1329 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) {
1330 char *xrn;
1331 if (car(e2)==REGISTER) {
1332 use_int(reg);
1333 if (use)
1334 printf("\tmovl %s,%s\n",register_name(cadr(e2),0),register_name(reg,0));
1335 printf("\taddl $%d,%s\n",dir,register_name(cadr(e2),0));
1336
1337 return;
1338 }
1339 g_expr(e2);
1340 emit_push();
1341 xrn = register_name((e2=emit_pop(0)),0);
1342 use_int(reg);
1343 if (use)
1344 printf("\t%s (%s),%s\n",cload(sign,sz),xrn,register_name(reg,0));
1345 printf("\t%s $%d,(%s)\n",(sz==1)?"addb":(sz==SIZE_OF_SHORT)?"addw":"addl",dir,xrn);
1346 emit_pop_free(e2);
1347 }
1348
1349
1350
1351 void
1352 code_return(int creg) {
1353 use_int(creg);
1354 printf("\tleal _%d,%s\n",retcont,register_name(creg,0));
1355 }
1356
1357
1358 void
1359 code_environment(int creg) {
1360 use_int(creg);
1361 printf("\tmovl %%ebp,%s\n",register_name(creg,0));
1362 }
1363
1364 static int rexpr_bool(int e1,int reg);
1365 #if FLOAT_CODE
1366 static int drexpr_bool(int e1,int reg);
1367 #endif
1368
1369 void
1370 code_bool(int e1,int reg) {
1371 char *xrn;
1372 int e2,e3;
1373 if (rexpr_bool(e1,reg)) return;
1374 #if FLOAT_CODE
1375 if (drexpr_bool(e1,reg)) return;
1376 #endif
1377 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */
1378 if (use) {
1379 use_int(reg);
1380 xrn = register_name(reg,0);
1381 printf("\txorl %s,%s\n",xrn,xrn);
1382 jmp(e3=fwdlabel());
1383 fwddef(e2);
1384 printf("\tmovl $1,%s\n",xrn);
1385 fwddef(e3);
1386 } else {
1387 fwddef(e2);
1388 }
1389 }
1390
1391 static char *
1392 code_gt(int cond) {
1393 return (cond?"g":"le");
1394 }
1395
1396 static char *
1397 code_ugt(int cond) {
1398 return (cond?"a":"be");
1399 }
1400
1401 static char *
1402 code_ge(int cond) {
1403 return (cond?"ge":"l");
1404 }
1405
1406 static char *
1407 code_uge(int cond) {
1408 return (cond?"ae":"b");
1409 }
1410
1411 static char *
1412 code_eq(int cond) {
1413 return (cond?"e":"ne");
1414 }
1415
1416 void
1417 code_cmp_crgvar(int e1,int reg,int sz,int label,int cond) {
1418 use_int(reg);
1419 #ifdef __APPLE__
1420 int r = get_ptr_cache(ncaddr(e1));
1421 if (cadr(e1)) {
1422 if (sz==1)
1423 printf("\tcmpb $0,%d(%s)\n",cadr(e1),register_name(r,0));
1424 else if (sz==SIZE_OF_SHORT)
1425 printf("\tcmpw $0,%d(%s)\n",cadr(e1),register_name(r,0));
1426 } else {
1427 if (sz==1)
1428 printf("\tcmpb $0,(%s)\n",register_name(r,0));
1429 else if (sz==SIZE_OF_SHORT)
1430 printf("\tcmpw $0,(%s)\n",register_name(r,0));
1431 }
1432 #else
1433 if (cadr(e1)) {
1434 if (sz==1)
1435 printf("\tcmpb $0,%s+%d\n",(ncaddr(e1))->nm,cadr(e1));
1436 else if (sz==SIZE_OF_SHORT)
1437 printf("\tcmpw $0,%s+%d\n",(ncaddr(e1))->nm,cadr(e1));
1438 } else {
1439 if (sz==1)
1440 printf("\tcmpb $0,%s\n",(ncaddr(e1))->nm);
1441 else if (sz==SIZE_OF_SHORT)
1442 printf("\tcmpw $0,%s\n",(ncaddr(e1))->nm);
1443 }
1444 #endif
1445 jcond(label,cond);
1446 }
1447
1448
1449 void
1450 code_cmp_crlvar(int e1,int reg,int sz,int label,int cond) {
1451 use_int(reg);
1452 if (sz==1) {
1453 printf("\tcmpb $0,"); lvar(e1); printf("\n");
1454 } else if (sz==SIZE_OF_SHORT) {
1455 printf("\tcmpw $0,"); lvar(e1); printf("\n");
1456 }
1457 jcond(label,cond);
1458 }
1459
1460
1461 void
1462 code_cmp_rgvar(int e1,int reg,int label,int cond) {
1463 use_int(reg);
1464 #ifdef __APPLE__
1465 int r = get_ptr_cache(ncaddr(e1));
1466 if (cadr(e1))
1467 printf("\tcmpl $0,%d(%s)\n",cadr(e1),register_name(r,0));
1468 else
1469 printf("\tcmpl $0,(%s)\n",register_name(r,0));
1470 #else
1471 if (cadr(e1))
1472 printf("\tcmpl $0,%s+%d\n",(ncaddr(e1))->nm,cadr(e1));
1473 else
1474 printf("\tcmpl $0,%s\n",(ncaddr(e1))->nm);
1475 #endif
1476 jcond(label,cond);
1477 }
1478
1479
1480 void
1481 code_cmp_rlvar(int e1,int reg,int label,int cond) {
1482 use_int(reg);
1483 printf("\tcmpl $0,"); lvar(e1); printf("\n");
1484 jcond(label,cond);
1485 }
1486
1487
1488 void
1489 code_cmp_register(int e2,int label,int cond) {
1490 use_int(e2);
1491 printf("\tcmpl $0,%s\n",register_name(e2,0));
1492 jcond(label,cond);
1493 }
1494
1495
1496 void
1497 code_string(int e1,int creg)
1498 {
1499 char *s;
1500 int lb;
1501 NMTBL *n = ncaddr(e1);
1502 if ((lb=attr_value(n,LABEL))) {
1503 // already defined
1504 return code_label_value(lb,creg) ;
1505 }
1506
1507 use_int(creg);
1508 s=n->nm;
1509 lb = emit_string_label();
1510 ascii(s);
1511 if (output_mode==TEXT_EMIT_MODE) {
1512 printf(".text\n");
1513 } else {
1514 text_mode(0);
1515 }
1516 #ifdef __APPLE__
1517 printf("\tleal _%d-_%d(%%ebx),%s\n",lb,
1518 goffset_label,
1519 register_name(creg,0));
1520 #else
1521 printf("\tlea _%d,%s\n",lb,register_name(creg,0));
1522 #endif
1523 set_attr(n,LABEL,lb);
1524 }
1525
1526 #define MAX_COPY_LEN 20
1527
1528 /* ARG_ORDER==1 case do not allow library call in emit_copy
1529 */
1530
1531 void
1532 emit_copy(int from,int to,int length,int offset,int value,int det)
1533 {
1534 int dreg;
1535 char *drn,*frn;
1536 char *trn;
1537 use_int(from);
1538 use_int(to);
1539 frn = register_name(from,0);
1540 trn = register_name(to,0);
1541
1542 /* length <0 means upward direction copy */
1543 switch (length) {
1544 case 0: break;
1545 case 1: case -1:
1546 drn = register_name(dreg = get_data_register(),1);
1547 printf("\tmovb %d(%s),%s\n",offset,frn,drn);
1548 printf("\tmovb %s,%d(%s)\n",drn,offset,trn);
1549 free_register(dreg);
1550 break;
1551 case 2: case -2:
1552 drn = register_name(dreg = get_data_register(),2);
1553 printf("\tmovw %d(%s),%s\n",offset,frn,drn);
1554 printf("\tmovw %s,%d(%s)\n",drn,offset,trn);
1555 free_register(dreg);
1556 break;
1557 case 4: case -4:
1558 drn = register_name(dreg = get_register(),0);
1559 printf("\tmovl %d(%s),%s\n",offset,frn,drn);
1560 printf("\tmovl %s,%d(%s)\n",drn,offset,trn);
1561 free_register(dreg);
1562 break;
1563 default:
1564 if (length <0) {
1565 if (length > -MAX_COPY_LEN) {
1566 for(;length<=-4;length+=4,offset-=4)
1567 emit_copy(from,to,-4,offset-4,0,det);
1568 for(;length<=-2;length+=2,offset-=2)
1569 emit_copy(from,to,-2,offset-2,0,det);
1570 if(length<0)
1571 emit_copy(from,to,length,offset-1,0,det);
1572 break;
1573 }
1574 } else if (length <=MAX_COPY_LEN) {
1575 for(;length>=4;length-=4,offset+=4)
1576 emit_copy(from,to,4,offset,0,det);
1577 for(;length>=2;length-=2,offset+=2)
1578 emit_copy(from,to,2,offset,0,det);
1579 if(length>0)
1580 emit_copy(from,to,length,offset,0,det);
1581 break;
1582 }
1583 // should be parallel_rassign....
1584 // clear_ptr_cache();
1585 // code_save_stacks();
1586
1587 printf("\tpushl %%esi\n");
1588 printf("\tpushl %%edi\n");
1589 printf("\tpushl %%ecx\n");
1590 printf("\tpushl %s\n",register_name(from,0));
1591 printf("\tpushl %s\n",register_name(to,0));
1592 printf("\tpopl %%edi\n");
1593 printf("\tpopl %%esi\n");
1594 if (length<0) {
1595 printf("\tmovl $%d,%%ecx\n",-length/4);
1596 printf("\taddl $%d,%%esi\n",-length-4);
1597 printf("\taddl $%d,%%edi\n",-length-4
1598 +(to==REG_ESP?4*4:0)
1599 );
1600 printf("\tstd\n\trep\n\tmovsl\n");
1601 printf("\tpopl %%ecx\n");
1602 printf("\tpopl %%edi\n");
1603 printf("\tpopl %%esi\n");
1604 if(length%4) {
1605 offset = offset+length/SIZE_OF_INT;
1606 length=length%4;
1607 emit_copy(from,to,length,offset,0,det);
1608 }
1609 } else {
1610 printf("\tmovl $%d,%%ecx\n",length/4);
1611 if (to==REG_ESP)
1612 printf("\taddl $%d,%%edi\n",4*4);
1613 printf("\tcld\n\trep\n\tmovsl\n");
1614 printf("\tpopl %%ecx\n");
1615 printf("\tpopl %%edi\n");
1616 printf("\tpopl %%esi\n");
1617 if(length%4) {
1618 offset = offset+length/SIZE_OF_INT;
1619 length=length%4;
1620 emit_copy(from,to,length,offset,0,det);
1621 }
1622 }
1623 }
1624 if (value) {
1625 /* creg must point top of the destination data */
1626 /* this code is necessary for the value of assignment or function call */
1627 /* otherwise we don't need this */
1628 if(creg!=to) {
1629 if (regs[creg]!=REG_VAR) free_register(creg); creg=to;
1630 }
1631 }
1632 }
1633
1634 static int
1635 push_struct(int e4,int t, int arg)
1636 {
1637 int length,dreg;
1638 g_expr(e4);
1639 length=size(t);
1640 if(length%SIZE_OF_INT) {
1641 length += SIZE_OF_INT - (length%SIZE_OF_INT);
1642 }
1643 emit_push();
1644 code_lvar(cadr(arg),USE_CREG);
1645 dreg = emit_pop(0);
1646
1647 // copy dreg to creg with length
1648 // try small amount copy
1649 /* downward direction copy */
1650 emit_copy(dreg,creg,length,0,0,1);
1651 emit_pop_free(dreg);
1652 /* we have value in creg, it may be changed */
1653 return length/SIZE_OF_INT;
1654 }
1655
1656 static int
1657 simple_arg(int e3)
1658 {
1659 return !contains_p(e3,not_simple_p);
1660 }
1661
1662 #define caller_arg_offset_v(arg) (ARG_LVAR_OFFSET+(arg)*SIZE_OF_INT)
1663
1664 /*
1665 Eary implementation uses pushl arg for function call. gcc
1666 use the same arguement evaluation order. Of course, the
1667 order is unspecified in C language, but it is better to
1668 use same argument evaluation order. Especially for test
1669 program.
1670 */
1671 #define ARG_ORDER 1
1672 #if (ARG_ORDER==1)
1673
1674 static int delayed_arg;
1675
1676 #endif
1677
1678 static int
1679 compute_complex_arg(int e3,int reg_arg_list,int arg) {
1680 int t=caddr(e3);
1681 int e4 = car(e3);
1682 reg_arg_list = list2(arg,reg_arg_list);
1683 #if ARG_ORDER==1
1684 delayed_arg = list2(assign_expr0(arg,e4,t,t),delayed_arg);
1685 #else
1686 g_expr_u(assign_expr0(arg,e4,t,t));
1687 #endif
1688
1689
1690
1691 car(e3) = arg;
1692 return reg_arg_list;
1693 }
1694
1695
1696 static void
1697 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) {
1698 int nargs=0,reg_arg=0,freg_arg=0;
1699 int t=caddr(e3);
1700 if(scalar(t)) {
1701 nargs ++ ; reg_arg++; freg_arg++;
1702 } else if (t==LONGLONG||t==ULONGLONG||t==DOUBLE) {
1703 nargs ++ ; reg_arg++;
1704 nargs ++ ; reg_arg++;
1705 } else if (t==FLOAT) {
1706 reg_arg ++ ; freg_arg++;
1707 nargs += size(t)/SIZE_OF_INT;
1708 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
1709 nargs += round4(size(t))/SIZE_OF_INT;
1710 } else {
1711 error(TYERR);
1712 nargs ++ ;
1713 }
1714 *pnargs += nargs;
1715 *preg_arg += reg_arg;
1716 *pfreg_arg += freg_arg;
1717 }
1718
1719 #define AS_SAVE 1
1720 #define AS_ARG 0
1721
1722 static int
1723 get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg)
1724 {
1725 if(scalar(t)) {
1726 if (mode==AS_SAVE) {
1727 if (parse_mode)
1728 return get_register_var(0);
1729 return list3n(LVAR,new_lvar(size(t)),0);
1730 } else
1731 return list3n(LVAR,caller_arg_offset_v(nargs),0);
1732 } else if (t==LONGLONG||t==ULONGLONG) {
1733 if (mode==AS_SAVE) {
1734 if (parse_mode)
1735 return get_lregister_var(0);
1736 return list3n(LVAR,new_lvar(size(t)),0);
1737 } else
1738 return list3n(LVAR,caller_arg_offset_v(nargs),0);
1739 } else if (t==FLOAT) {
1740 if (mode==AS_SAVE) {
1741 if (parse_mode)
1742 return get_dregister_var(0,0);
1743 return list3n(LVAR,new_lvar(size(t)),0);
1744 } else
1745 return list3n(LVAR,caller_arg_offset_v(nargs),0);
1746 } else if (t==DOUBLE) {
1747 if (mode==AS_SAVE) {
1748 if (parse_mode)
1749 return get_dregister_var(0,1);
1750 return list3n(LVAR,new_lvar(size(t)),0);
1751 } else
1752 return list3n(LVAR,caller_arg_offset_v(nargs),0);
1753 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
1754 if (mode==AS_SAVE) {
1755 if (parse_mode)
1756 return get_register_var(0);
1757 return list3n(LVAR,new_lvar(size(t)),0);
1758 } else
1759 return list3n(LVAR,caller_arg_offset_v(nargs),0);
1760 } else {
1761 error(-1);
1762 if (parse_mode)
1763 return get_register_var(0);
1764 return list3n(LVAR,new_lvar(size(t)),0);
1765 }
1766 }
1767
1768 static void
1769 code_call(int e2,NMTBL *fn,int jmp)
1770 {
1771 if (car(e2) == FNAME) {
1772 #ifdef __APPLE__
1773 printf("\tcall\tL_%s$stub\n",fn->nm);
1774 #else
1775 printf("\tcall\t%s\n",fn->nm);
1776 #endif
1777 } else {
1778 printf("\tcall\t*%s\n",register_name(REG_EAX,0));
1779 }
1780 }
1781
1782 int
1783 function(int e1)
1784 {
1785
1786 int e2,e3,e4,e5,nargs,t;
1787 int arg,reg_arg,freg_arg,arg_assign;
1788 int dots;
1789 int reg_arg_list=0,ret_type,special_lvar;
1790 NMTBL *fn = 0;
1791 int jmp = 0;
1792 int complex_;
1793 int pnargs,preg_arg,pfreg_arg;
1794 int stargs;
1795 int half_register = 0;
1796 #if (ARG_ORDER==1)
1797 int save_delayed_arg = delayed_arg;
1798 int as_save = AS_ARG; // 1st pushed argment will evaluate at the last
1799 delayed_arg = 0;
1800 #else
1801 const int as_save = AS_SAVE;
1802 #endif
1803
1804 special_lvar = -1;
1805 ret_type = function_type(cadddr(e1),&dots);
1806 if (caddr(cadddr(e1))==0) dots=1;
1807
1808 arg_assign = 0;
1809 e2 = cadr(e1);
1810 if (car(e2) == FNAME) {
1811 fn=ncaddr(e2);
1812 } else {
1813 if (car(e2)==INDIRECT) e2=cadr(e2); // (*func)(i) case
1814 jmp = list3(REGISTER,REG_EAX,0);
1815
1816 if (!simple_arg(e2)) {
1817 e3=get_register_var(0);
1818 reg_arg_list = list2(e3,reg_arg_list);
1819 g_expr_u(assign_expr0(e3,e2,INT,INT));
1820 e2=e3;
1821 }
1822 arg_assign = list2(assign_expr0(jmp,e2,INT,INT),arg_assign);
1823 }
1824 /* First we execute complex argument to avoid interaction with
1825 input variables. Remain the last complex argument in complex_. */
1826 stargs = 0;
1827 complex_ = 0;
1828 nargs = reg_arg = freg_arg = 0;
1829 pnargs = preg_arg = pfreg_arg = 0;
1830 for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) {
1831 t=caddr(e3);
1832 if (reg_arg==3 && (t==DOUBLE||t==LONGLONG||t==ULONGLONG)) {
1833 half_register=1;
1834 }
1835 if ((e5= !simple_arg(car(e3)))) {
1836 if (complex_) {
1837 arg = get_input_arg(caddr(complex_),as_save,
1838 pnargs,preg_arg,pfreg_arg);
1839 #if ARG_ORDER==1
1840 as_save = AS_SAVE;
1841 #endif
1842 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
1843 }
1844 // memorise last complex arg parameter
1845 pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg;
1846 complex_ = e3;
1847 }
1848 if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
1849 // The struct should be pushed after complex arguments.
1850 if (e5) { // compute address only, complex_ is me now. Clear it.
1851 complex_ = 0;
1852 e4 = car(e3);
1853 if (car(e4)==RSTRUCT) e4 = cadr(e4);
1854 if (!simple_arg(e4)) {
1855 // Calculate complex struct address here.
1856 // If simple, leave it.
1857 arg = get_register_var(0);
1858 #if ARG_ORDER==1
1859 delayed_arg = list2(
1860 assign_expr0(arg,e4,INT,INT),
1861 delayed_arg);
1862 #else
1863 g_expr_u(assign_expr0(arg,e4,INT,INT));
1864 #endif
1865 car(e3)=arg;
1866 reg_arg_list = list2(arg,reg_arg_list);
1867
1868 car(e3) = rvalue_t(arg,INT);
1869 }
1870 }
1871 stargs = list4(e3,stargs,nargs,reg_arg);
1872 }
1873 increment_function_arg(e3,&nargs,&reg_arg,&freg_arg);
1874 }
1875 #if (ARG_ORDER==1)
1876 if (complex_) {
1877 arg = get_input_arg(caddr(complex_),as_save,
1878 pnargs,preg_arg,pfreg_arg);
1879 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
1880 }
1881 for(;delayed_arg;delayed_arg = cadr(delayed_arg)) {
1882 g_expr_u(car(delayed_arg));
1883 }
1884 #endif
1885
1886 /* now all input register vars are free */
1887 code_save_stacks();
1888
1889 // set_lreg(LREG_LREGISTER,0);
1890 set_freg(FREG_FREGISTER,0);
1891 set_ireg(CREG_REGISTER,0);
1892
1893 // Struct arguments need emit_copy. it destructs 3 input registers.
1894 // But it returns no value on a register. So calculate it here.
1895 // We cannot do this in the previous loop, because the copied struct may be
1896 // override by other complex arguments. But before this we have to check
1897 // complex_.
1898
1899 // ARG_ORDER==1 case put the last value on the top of stack.
1900 // emit_copy/push_struct must preserve argument stack, i.e.
1901 // no library call is allowed.
1902
1903 if (stargs) {
1904 #if (ARG_ORDER!=1)
1905 if (complex_) {
1906 arg = get_input_arg(caddr(complex_),AS_SAVE,
1907 pnargs,preg_arg,pfreg_arg);
1908 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
1909 }
1910 #endif
1911 for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) {
1912 e3 = car(stargs);
1913 e4 = car(e3);
1914 t = caddr(e3);
1915 arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0);
1916 push_struct(e4,t,arg);
1917 car(e3)=0; // done
1918
1919
1920 }
1921 #if (ARG_ORDER!=1)
1922 } else {
1923 // last complex argument can use input register
1924 if (complex_) {
1925 arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg)
1926 ;
1927 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg);
1928
1929 car(complex_) = 0; // done.
1930
1931
1932 }
1933 #endif
1934 }
1935
1936 nargs = reg_arg = freg_arg = 0;
1937 // calc stack arguments first, it may requires extra registers,
1938 // and we can still use input registers now.
1939 for (e3 = e1; e3;
1940 increment_function_arg(e3,&nargs,&reg_arg,&freg_arg),
1941 e3 = cadr(e3)) {
1942 if (!(e4=car(e3))) continue;
1943 t=caddr(e3);
1944 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg);
1945 if (car(arg)!=LVAR) continue;
1946 g_expr_u(assign_expr0(arg,e4,t,t));
1947 car(e3)=0; // done
1948 }
1949 if (max_func_args<nargs) max_func_args=nargs;
1950 for(;arg_assign;arg_assign=cadr(arg_assign)) {
1951 g_expr_u(car(arg_assign));
1952 }
1953 clear_ptr_cache();
1954 code_call(e2,fn,jmp);
1955 free_register_var(reg_arg_list);
1956 if (ret_type==DOUBLE||ret_type==FLOAT) {
1957 } else if (ret_type==LONGLONG||ret_type==ULONGLONG) {
1958 use_longlong0(USE_CREG);
1959 } else if (ret_type==VOID) {
1960 } else {
1961 if (use)
1962 set_ireg(RET_REGISTER,0);
1963 else
1964 set_ireg(CREG_REGISTER,0);
1965 }
1966 #if (ARG_ORDER==1)
1967 delayed_arg = save_delayed_arg;
1968 #endif
1969 return ret_type;
1970 }
1971
1972 void
1973 code_alloca(int e1,int reg)
1974 {
1975 char *crn;
1976
1977 if (!is_const(e1)) {
1978 g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15)));
1979 use_int(reg);
1980 } else {
1981 use_int(reg);
1982 code_const(round16(cadr(e1)),reg);
1983 }
1984 crn = register_name(reg,0);
1985 printf("\tsubl\t%s, %%esp\n",crn);
1986 if (!max_func_arg_label) max_func_arg_label = fwdlabel();
1987 printf("\tmovl $%s%d,%s\n",lpfx,max_func_arg_label ,crn);
1988 printf("\tadd\t%%esp, %s\n",crn);
1989 }
1990
1991 void
1992 code_frame_pointer(int e3) {
1993 use_int(e3);
1994 printf("\tmovl %s,%%ebp\n",register_name(e3,0));
1995 }
1996
1997 int
1998 code_frame_pointer_register()
1999 {
2000 return list2(REGISTER,REG_fp);
2001 }
2002
2003 void
2004 code_fix_frame_pointer(int disp_offset) {
2005 // must be empty
2006 }
2007
2008 void
2009 code_jmp(char *s) {
2010 #ifdef __APPLE__
2011 printf("\tjmp\tL_%s$stub\n",s);
2012 #else
2013 printf("\tjmp %s\n",s);
2014 #endif
2015 }
2016
2017
2018 void
2019 code_indirect_jmp(int e2) {
2020 use_int(e2);
2021 printf("\tjmp *%s\n",register_name(e2,0));
2022 }
2023
2024 void
2025 code_rindirect(int e1, int reg,int offset, int sign,int byte)
2026 {
2027 char *crn,*op;
2028 g_expr(e1);
2029 op=cload(sign,byte);
2030 crn = register_name(creg,0);
2031 use_int(reg);
2032 printf("\t%s %d(%s),%s\n",op,offset,crn,register_name(reg,0));
2033 }
2034
2035 #if FLOAT_CODE
2036 int
2037 code_drindirect(int e1, int reg,int offset, int d)
2038 {
2039 g_expr(e1);
2040 printf("\t%s %d(%s)\n",fload(d),offset,register_name(creg,0));
2041 return DOUBLE;
2042 }
2043 #endif
2044
2045 #if LONGLONG_CODE
2046
2047 static void
2048 lload(int creg,int offset,int reg)
2049 {
2050 char *crn = register_name(creg,0);
2051 use_longlong(reg);
2052 if((reg==REG_L&&creg==REG_ESI)||(creg==REG_EAX)) {
2053 printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg));
2054 printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg));
2055 } else {
2056 printf("\tmovl %d(%s),%s\n",offset,crn,l_eax(reg));
2057 printf("\tmovl %d(%s),%s\n",offset+SIZE_OF_INT,crn,l_edx(reg));
2058 }
2059 }
2060
2061 int
2062 code_lrindirect(int e1, int reg, int offset, int us)
2063 {
2064 int reg0;
2065 g_expr(e1);
2066 reg0=creg;
2067 use_longlong(reg);
2068 lload(reg0,offset,reg);
2069 return LONGLONG;
2070 }
2071 #endif
2072
2073 char *
2074 move(int byte)
2075 {
2076 return byte==1?"movb":byte==SIZE_OF_SHORT?"movw":"movl";
2077 }
2078
2079 void
2080 code_assign_gvar(int e2,int creg,int byte) {
2081 if (byte) { use_data_reg(creg,1);
2082 } else { use_int(creg); }
2083 #ifdef __APPLE__
2084 int r = get_ptr_cache(ncaddr(e2));
2085 if (cadr(e2))
2086 printf("\t%s %s,%d(%s)\n",move(byte),register_name(creg,byte),
2087 cadr(e2),register_name(r,0));
2088 else
2089 printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),
2090 register_name(r,0));
2091 #else
2092 if (cadr(e2))
2093 printf("\t%s %s,%s+%d\n",move(byte),register_name(creg,byte),(ncaddr(e2))->nm,cadr(e2));
2094 else
2095 printf("\t%s %s,%s\n",move(byte),register_name(creg,byte),(ncaddr(e2))->nm);
2096 #endif
2097 }
2098
2099 void
2100 code_assign_lvar(int e2,int creg,int byte) {
2101 if (byte) { use_data_reg(creg,1);
2102 } else { use_int(creg); }
2103 printf("\t%s %s,",move(byte),register_name(creg,byte));
2104 lvar(e2); printf("\n");
2105 }
2106
2107 void
2108 code_assign_register(int e2,int byte,int creg) {
2109 use_int(creg);
2110 if (creg!=e2)
2111 printf("\tmovl %s,%s\n",register_name(creg,0),register_name(e2,0));
2112 }
2113
2114 void
2115 code_assign(int e2,int byte,int creg) {
2116 use_int(e2);
2117 if (byte) { use_data_reg(creg,1);
2118 } else { use_int(creg); }
2119 printf("\t%s %s,(%s)\n",move(byte),register_name(creg,byte),register_name(e2,0));
2120 }
2121
2122 void
2123 code_register_assop(int e2,int reg, int op,int byte) {
2124 // reg <= reg(e2) op=reg
2125 use_int(reg);
2126 tosop(op,e2,reg);
2127 }
2128
2129 void
2130 code_assop(int op,int creg,int byte,int sign) {
2131 int xreg;
2132 // (*pop()) op = creg
2133 // creg should be ecx
2134
2135 use_int(creg);
2136 xreg = emit_pop(0); /* pop e3 value */
2137 emit_push();
2138 ld_indexx(byte,0,creg,ireg,sign);
2139 tosop(op,ireg,xreg);
2140 emit_pop_free(xreg);
2141 if (byte) {
2142 use_data_reg(ireg,1);
2143 }
2144 xreg = emit_pop(0); /* pop e3 value */
2145 printf("\t%s %s,(%s)\n",move(byte),register_name(ireg,byte),register_name(xreg,0));
2146 emit_pop_free(xreg);
2147 }
2148
2149 int
2150 tosop_operand_safe_p(int op)
2151 {
2152 switch(op) {
2153 case ADD: case SUB: case CMP:
2154 case BAND: case EOR: case BOR:
2155 case MUL: case UMUL:
2156 return 1;
2157 default: return 0;
2158 }
2159 }
2160
2161 void
2162 tosop(int op,int reg,int oreg)
2163 {
2164 int ox=0;
2165 char *orn,*crn;
2166 // creg = creg op oreg
2167
2168 use_int(reg);
2169
2170 if(oreg==-1) {
2171 error(-1);
2172 } else if (oreg<= -REG_LVAR_OFFSET) {
2173 ox = get_register(); if (ox<0) error(-1);
2174 code_rlvar(oreg+REG_LVAR_OFFSET,ox);
2175 free_lvar(oreg+REG_LVAR_OFFSET);
2176 oreg = ox;
2177 }
2178
2179 switch(op) {
2180 case LSHIFT:
2181 case ULSHIFT:
2182 shift("sall",oreg,reg);
2183 if(ox) free_register(ox);
2184 return;
2185 case RSHIFT:
2186 shift("sarl",oreg,reg);
2187 if(ox) free_register(ox);
2188 return;
2189 case URSHIFT:
2190 shift("shrl",oreg,reg);
2191 if(ox) free_register(ox);
2192 return;
2193 }
2194 // regs[oreg]=1;
2195 orn = register_name(oreg,0);
2196 crn = register_name(reg,0);
2197 switch(op) {
2198 case ADD:
2199 printf("\taddl %s,%s\n",orn,crn);
2200 break;
2201 case SUB:
2202 printf("\tsubl %s,%s\n",orn,crn);
2203 break;
2204 case CMP:
2205 printf("\tcmpl %s,%s\n",orn,crn);
2206 break;
2207 case BAND:
2208 printf("\tandl %s,%s\n",orn,crn);
2209 break;
2210 case EOR:
2211 printf("\txorl %s,%s\n",orn,crn);
2212 break;
2213 case BOR:
2214 printf("\torl %s,%s\n",orn,crn);
2215 break;
2216 case MUL:
2217 case UMUL:
2218 printf("\t%s %s,%s\n","imull",orn,crn);
2219 break;
2220 case DIV:
2221 case UDIV:
2222 case MOD:
2223 case UMOD:
2224 #ifdef __APPLE__
2225 if (regs[REG_EDX]==PTRC_REG)
2226 clear_ptr_cache_reg(REG_EDX);
2227 #endif
2228 use_register(reg,REG_EAX,1);
2229 if (oreg==REG_EAX) oreg=reg;
2230 if (oreg==REG_EDX) {
2231 use_register(oreg,REG_ECX,1);
2232 oreg = REG_ECX;
2233 }
2234 orn = register_name(oreg,0);
2235 printf((op==DIV||op==MOD)?
2236 "\tcltd\n\tidivl %s\n":
2237 "\txor %%edx,%%edx\n\tdivl %s\n",orn);
2238 set_ireg((op==MOD||op==UMOD)?REG_EDX:REG_EAX,0);
2239 set_ireg(reg,1);
2240 break;
2241 }
2242 if(ox && ox!=ireg) free_register(ox);
2243 }
2244
2245 int
2246 code_const_op_p(int op,int e)
2247 {
2248 if (car(e)!=CONST) return 0;
2249 if (op==DIV||op==UDIV) return ilog(cadr(e));
2250 if (op==MOD||op==UMOD) return 0;
2251 else return 1;
2252 }
2253
2254 void
2255 oprtc(int op,int reg,int orn)
2256 {
2257 char *crn;
2258 int datareg;
2259 use_int(reg);
2260 crn = register_name(reg,0);
2261 orn = cadr(orn);
2262 datareg=is_data_reg(reg);
2263
2264 switch(op) {
2265 case LSHIFT:
2266 case ULSHIFT:
2267 printf("\tsall $%d,%s\n",orn,crn);
2268 return;
2269 case DIV:
2270 orn = ilog(orn);
2271 case RSHIFT:
2272 printf("\tsarl $%d,%s\n",orn,crn);
2273 return;
2274 case UDIV:
2275 orn = ilog(orn);
2276 case URSHIFT:
2277 printf("\tshrl $%d,%s\n",orn,crn);
2278 return;
2279 case ADD:
2280 printf("\taddl $%d,%s\n",orn,crn);
2281 break;
2282 case SUB: case CMP:
2283 printf("\tsubl $%d,%s\n",orn,crn);
2284 break;
2285 case BAND:
2286 if (datareg&&(orn & ~255)==~255)
2287 printf("\tandb $%d,%s\n",orn,register_name(reg,1));
2288 else if (datareg&&(orn & ~65535)==~65535)
2289 printf("\tandw $%d,%s\n",orn,register_name(reg,2));
2290 else
2291 printf("\tandl $%d,%s\n",orn,crn);
2292 break;
2293 case EOR:
2294 printf("\txorl $%d,%s\n",orn,crn);
2295 break;
2296 case BOR:
2297 if (datareg&&(orn & ~255)==0)
2298 printf("\tor $%d,%s\n",orn,register_name(reg,1));
2299 else if (datareg&&(orn & ~65535)==0)
2300 printf("\tor $%d,%s\n",orn,register_name(reg,2));
2301 else
2302 printf("\torl $%d,%s\n",orn,crn);
2303 break;
2304 case MUL:
2305 case UMUL:
2306 if (ilog(orn)) {
2307 printf("\tsall $%d,%s\n",ilog(orn),crn);
2308 } else
2309 printf("\t%s $%d,%s\n","imull",orn,crn);
2310 break;
2311 default:
2312 error(-1);
2313 }
2314 }
2315
2316
2317 void
2318 shift(char *op, int oreg,int reg)
2319 {
2320 int dreg;
2321 use_register(oreg,REG_ECX,1);
2322 dreg = (reg==REG_ECX)?oreg:reg;
2323 printf("\t%s %%cl,%s\n",op,register_name(dreg,0));
2324 set_ireg(dreg,0);
2325 set_ireg(reg,1);
2326 }
2327
2328 void
2329 ld_indexx(int byte, int n, int xreg,int reg,int sign)
2330 {
2331 if (byte) {
2332 use_data_reg(reg,1);
2333 } else {
2334 use_int(reg);
2335 }
2336 if (n)
2337 printf("\t%s %d(%s),%s\n",cload(sign,byte),n,
2338 register_name(xreg,0),register_name(reg,0));
2339 else
2340 printf("\t%s (%s),%s\n",cload(sign,byte),
2341 register_name(xreg,0),register_name(reg,0));
2342 }
2343
2344 int
2345 code_csvalue()
2346 {
2347 return glist2(REGISTER,creg); /* for switch value */
2348 }
2349
2350 void
2351 code_cmpdimm(int e, int csreg,int label,int cond)
2352 {
2353 /* used in dosiwtch() */
2354 set_ireg(csreg,0);
2355 printf("\tcmpl $%d,%s\n",e,register_name(creg,0));
2356 jcond(label,cond);
2357 }
2358
2359 void
2360 code_opening(char *filename)
2361 {
2362 printf("\t.file \"%s\"\n",filename);
2363 printf("\t.version\t\"01.01\"\n");
2364 /* printf("gcc2_compiled.:\n"); */
2365 // printf(".text\n");
2366 }
2367
2368 void
2369 code_closing()
2370 {
2371 global_table();
2372 printf("\t.ident \"Micro-C compiled\"\n");
2373 }
2374
2375 static char *
2376 code_cond(int op,int cond)
2377 {
2378 switch(op) {
2379 case GT: return code_gt(cond);
2380 case UGT: return code_ugt(cond);
2381 case GE: return code_ge(cond);
2382 case UGE: return code_uge(cond);
2383 case LT: return code_ge(!cond);
2384 case ULT: return code_uge(!cond);
2385 case LE: return code_gt(!cond);
2386 case ULE: return code_ugt(!cond);
2387 case EQ: return code_eq(cond);
2388 case NEQ: return code_eq(!cond);
2389 default: return 0;
2390 }
2391 }
2392
2393 static int
2394 rexpr_bool(int e1,int reg)
2395 {
2396 char *s;
2397 if (!(s=code_cond(car(e1),1))) return 0;
2398 g_expr(list3(CMP,cadr(e1),caddr(e1)));
2399 use_data_reg(reg,1);
2400 printf("\tset%s\t%s\n",s,register_name(reg,1));
2401 printf("\tmovzbl %s,%s\n",register_name(reg,1),register_name(reg,0));
2402 return 1;
2403 }
2404
2405 int
2406 rexpr(int e1, int l1, int cond,int t)
2407 {
2408 g_expr(list3(CMP,cadr(e1),caddr(e1)));
2409 printf("\tj%s\t_%d\n",code_cond(car(e1),cond),l1);
2410 return l1;
2411 }
2412
2413
2414 static void
2415 jcond(int l, char cond)
2416 {
2417 printf("\tj%s\t_%d\n",cond==LT?code_ge(0):cond?"ne":"e",l);
2418 }
2419
2420 void
2421 jmp(int l)
2422 {
2423 printf("\tjmp\t_%d\n",l);
2424 control = 0;
2425 /* align? */
2426 /*
2427 this is not allowed because of ? operator
2428 use_register(creg,REG_EAX,0);
2429 */
2430 }
2431
2432 void
2433 code_comment(char *s)
2434 {
2435 printf("## %s",s);
2436 }
2437
2438
2439 void
2440 code_enter(char *name)
2441 {
2442 text_mode(0);
2443 printf("\t.align 4\n");
2444 #ifndef __APPLE__
2445 if (stmode!=STATIC)
2446 printf(".globl %s\n",name);
2447 printf("\t.type\t%s,@function\n",name);
2448 printf("%s:\n",name);
2449 #else
2450 if (stmode!=STATIC)
2451 printf(".globl _%s\n",name);
2452 printf("_%s:\n",name);
2453 clear_ptr_cache();
2454 #endif
2455 }
2456
2457
2458 void
2459 code_enter1(int args)
2460 {
2461 code_disp_label=fwdlabel();
2462 printf("\tlea -_%d(%%ebp),%%esp\n",code_disp_label);
2463
2464 // printf("## args %d disp %d code_disp_offset=%d\n",args,disp,code_disp_offset);
2465 #ifdef __APPLE__
2466 printf("\tcall\t___i686.get_pc_thunk.bx\n");
2467 printf("_%d:\n",labelno);
2468 goffset_label = labelno;
2469 labelno++;
2470 regs[REG_EBX] = 1;
2471 #endif
2472 }
2473
2474 void
2475 code_leave(char *name)
2476 {
2477 code_offset_set(fnptr);
2478 #ifndef __APPLE__
2479 printf("_%d:\n",labelno);
2480 printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
2481 local_table();
2482 labelno++;
2483 #else
2484 local_table();
2485 #endif
2486 free_all_register();
2487 }
2488
2489 void
2490 enter(char *name)
2491 {
2492 text_mode(0);
2493 printf("\t.align 2\n");
2494 #ifndef __APPLE__
2495 if (stmode!=STATIC)
2496 printf(".globl %s\n",name);
2497 printf("%s:\n",name);
2498 printf("\t.type\t%s,@function\n",name);
2499 #else
2500 if (stmode!=STATIC)
2501 printf(".globl _%s\n",name);
2502 printf("_%s:\n",name);
2503 #endif
2504
2505 // lvar_offset_label = fwdlabel();
2506 r1_offset_label = fwdlabel();
2507 max_func_args = 0;
2508
2509 printf("\tpushl %%ebp\n");
2510 printf("\tmovl %%esp,%%ebp\n");
2511 printf("\tpushl %%ebx\n");
2512 printf("\tpushl %%esi\n");
2513 printf("\tpushl %%edi\n");
2514 printf("\tlea -%s%d(%%ebp),%%esp\n",lpfx,r1_offset_label);
2515 #ifdef __APPLE__
2516 printf("\tcall\t___i686.get_pc_thunk.bx\n");
2517 printf("_%d:\n",labelno);
2518 goffset_label = labelno;
2519 labelno++;
2520 regs[REG_EBX] = 1;
2521 clear_ptr_cache();
2522 #endif
2523
2524 control=1;
2525 }
2526
2527 void
2528 enter1()
2529 {
2530 text_mode(0);
2531 }
2532
2533 void
2534 code_label_call(int l)
2535 {
2536 printf("\tcall\tL_%d\n",l);
2537 }
2538
2539 void
2540 code_ret()
2541 {
2542 printf("\tret\n");
2543 control=0;
2544 }
2545
2546 static void
2547 make_return_continuation()
2548 {
2549 int ty = cadr(fnptr->ty);
2550 fwddef(retcont);
2551 if (ty==FLOAT||ty==DOUBLE) {
2552 printf("\tfldl %d(%%ebp)\n",-SIZE_OF_DOUBLE);
2553 printf("\tmovl %s,%%ebp\n",reg_name[REG_ESI]);
2554 } else if (ty==LONGLONG||ty==ULONGLONG) {
2555 set_lreg(RET_LREGISTER,0);
2556 printf("\tmovl %d(%%ebp),%%ebp\n",disp-SIZE_OF_INT);
2557 } else if (ty>0&&( car(ty)==STRUCT || car(ty)==UNION)) {
2558 set_ireg(RET_REGISTER,0);
2559 printf("\tmovl %d(%%ebp),%s\n",disp-SIZE_OF_INT,
2560 register_name(creg,0));
2561 printf("\tmovl %s,%%ebp\n",reg_name[REG_EDI]);
2562 } else if (ty!=VOID) {
2563 set_ireg(RET_REGISTER,0);
2564 printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg,0));
2565 printf("\tmovl %s,%%ebp\n",reg_name[REG_EDI]);
2566 }
2567 }
2568
2569 void
2570 leave(int control, char *name)
2571 {
2572
2573 #ifdef __APPLE__
2574 disp &= -(SIZE_OF_INT*4); // 16byte alignment
2575 disp -= 12;
2576 #else
2577 disp &= -SIZE_OF_INT;
2578 #endif
2579 if (control)
2580 code_set_return_register(1);
2581 if (retcont) {
2582 if (control)
2583 jmp(retlabel);
2584 make_return_continuation();
2585 }
2586 fwddef(retlabel);
2587 code_offset_set(fnptr);
2588
2589 printf("\tlea %d(%%ebp),%%esp\n",-12);
2590 printf("\tpopl %%edi\n");
2591 printf("\tpopl %%esi\n");
2592 printf("\tpopl %%ebx\n");
2593 printf("\tleave\n");
2594 printf("\tret\n");
2595 #ifndef __APPLE__
2596 printf("_%d:\n",labelno);
2597 printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
2598 #endif
2599 local_table();
2600 labelno++;
2601 free_all_register();
2602 }
2603
2604 int
2605 code_get_fixed_creg(int reg,int type) {
2606 if (type==FLOAT||type==DOUBLE) {
2607 return 0;
2608 } else if (type==LONGLONG||type==ULONGLONG) {
2609 use_longlong(reg);
2610 return reg;
2611 } else {
2612 if (reg==USE_CREG) {
2613 if (regs[CREG_REGISTER]==0) {
2614 set_ireg(CREG_REGISTER,is_int_reg(creg)&&regs[creg]==USING_REG);
2615 return CREG_REGISTER;
2616 }
2617 }
2618 use_int(reg);
2619 return reg;
2620 }
2621 }
2622
2623 void
2624 code_set_fixed_creg(int reg,int mode,int type) {
2625 if (type==FLOAT||type==DOUBLE) {
2626 } else if (type==LONGLONG||type==ULONGLONG) {
2627 } else {
2628 set_ireg(reg,mode);
2629 }
2630 }
2631
2632 int
2633 code_set_return_register(int mode) {
2634 // before goto leave code, set return register
2635 if (cadr(fnptr->ty)==FLOAT) {
2636 // set_freg(RET_FREGISTER,mode);
2637 return 0;
2638 } else if (cadr(fnptr->ty)==DOUBLE) {
2639 // set_dreg(RET_DREGISTER,mode);
2640 return 0;
2641 } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) {
2642 set_lreg(RET_LREGISTER,mode);
2643 return ireg;
2644 } else if (cadr(fnptr->ty)==VOID) {
2645 return 0;
2646 } else {
2647 set_ireg(RET_REGISTER,mode);
2648 return ireg;
2649 }
2650 }
2651
2652 void
2653 gen_gdecl(char *n, int gpc)
2654 {
2655 // must be empty
2656 }
2657
2658 extern void
2659 ascii(char *s)
2660 {
2661 #ifdef __APPLE__
2662 printf("\t.ascii \"");
2663 #else
2664 printf("\t.string \"");
2665 #endif
2666 while(*s) {
2667 if (*s=='\n')
2668 printf("%cn",92);
2669 else if (*s<' ')
2670 printf("%c%03o",92,*s);
2671 else if (*s=='\\')
2672 printf("\\\\");
2673 else if (*s==34)
2674 printf("%c%c",92,34);
2675 else
2676 printf("%c",*s);
2677 s++;
2678 }
2679 #ifdef __APPLE__
2680 printf("\\0%c\n",34);
2681 #else
2682 printf("%c\n",34);
2683 #endif
2684 }
2685
2686 extern int
2687 emit_string_label()
2688 {
2689 int lb;
2690 cstring_mode();
2691 lb=fwdlabel();
2692 printf("_%d:\n",lb);
2693 return lb;
2694 }
2695
2696 extern void
2697 emit_string(char *s,int t)
2698 {
2699 t = type_value(t);
2700 if (car(t)==ARRAY &&
2701 (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) {
2702 ascii(s);
2703 } else {
2704 int l = emit_string_label();
2705 ascii(s);
2706 emit_label(l);
2707 }
2708 return;
2709 }
2710
2711 void
2712 code_align(int t)
2713 {
2714 int d;
2715 switch(t) {
2716 case CHAR: case UCHAR: return;
2717 case SHORT: case USHORT: d = data_alignment & 1; break;
2718 default: d = data_alignment & 3;
2719 }
2720 if (d) {
2721 printf("\t.align 2\n");
2722 data_alignment = 0;
2723 }
2724 }
2725
2726 extern void
2727 emit_global(NMTBL *n,int a,int e)
2728 {
2729 int t = type_value(n->ty);
2730 if (e>0 && car(e)==STRING && t>0 && car(t)==ARRAY &&
2731 (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) {
2732 cstring_mode();
2733 } else
2734 data_mode(n->nm);
2735 code_align(a);
2736 #ifdef __APPLE__
2737 if (n && n->sc!=STATIC)
2738 printf(".globl\t_%s\n",n->nm);
2739 printf("_%s:\n",n->nm);
2740 #else
2741 if (n && n->sc!=STATIC)
2742 printf(".globl\t%s\n",n->nm);
2743 printf("%s:\n",n->nm);
2744 #endif
2745 }
2746
2747 extern void
2748 emit_space(int sp)
2749 {
2750 data_mode(0);
2751 printf("\t.space\t%d\n",sp);
2752 }
2753
2754 extern void
2755 emit_char(int d)
2756 {
2757 data_mode(0);
2758 printf("\t.byte %d\n",d);
2759 }
2760
2761 extern void
2762 emit_short(int d)
2763 {
2764 data_mode(0);
2765 printf("\t.short %d\n",d);
2766 }
2767
2768 extern void
2769 emit_int(int d)
2770 {
2771 data_mode(0);
2772 printf("\t.long %d\n",d);
2773 }
2774
2775 extern void
2776 emit_longlong(int e)
2777 {
2778 #if LONGLONG_CODE
2779 long long ll = lcadr(e);
2780 data_mode(0);
2781 #if (ENDIAN_L==0)
2782 printf("\t.long\t0x%x,0x%x\n",code_l1(ll),code_l2(ll));
2783 #else
2784 printf("\t.long\t0x%x,0x%x\n",code_l2(ll),code_l1(ll));
2785 #endif
2786 #endif
2787 }
2788
2789 extern void
2790 emit_double(int e)
2791 {
2792 #if FLOAT_CODE
2793 double d = dcadr(e);
2794 data_mode(0);
2795 #if (ENDIAN_D==0)
2796 printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d));
2797 #else
2798 printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d));
2799 #endif
2800 #endif
2801 }
2802
2803 extern void
2804 emit_float(int e)
2805 {
2806 #if FLOAT_CODE
2807 float f = dcadr(e);
2808 data_mode(0);
2809 printf("\t.long\t0x%x\n",*(int *)&f);
2810 #endif
2811 }
2812
2813 extern void
2814 emit_address(char *s,int offset)
2815 {
2816 data_mode(0);
2817 #ifdef __APPLE__
2818 if (offset)
2819 printf("\t.long _%s+%d\n",s,offset);
2820 else
2821 printf("\t.long _%s\n",s);
2822 #else
2823 if (offset)
2824 printf("\t.long %s+%d\n",s,offset);
2825 else
2826 printf("\t.long %s\n",s);
2827 #endif
2828 }
2829
2830 extern void
2831 emit_label(int labelno)
2832 {
2833 data_mode(0);
2834 printf("\t.long _%d\n",labelno);
2835 }
2836
2837 extern void
2838 emit_data_closing(NMTBL *n)
2839 {
2840 #ifdef DOT_SIZE
2841 int lb;
2842 #endif
2843 if (mode==GDECL) {
2844 data_mode(0);
2845 #ifdef DOT_SIZE
2846 lb=fwdlabel();
2847 printf("_%d:\n",lb);
2848 printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm);
2849 #endif
2850 }
2851 }
2852
2853 #if LONGLONG_CODE
2854 static long long ll0 = 1LL;
2855
2856 static int
2857 code_l1(long long d)
2858 {
2859 int *i = (int *)&ll0; int *j = (int *)&d;
2860 return (i[1] == 1)?j[1]:j[0];
2861 }
2862
2863 static int
2864 code_l2(long long d)
2865 {
2866 int *i = (int *)&ll0; int *j = (int *)&d;
2867 return (i[1] == 1)?j[0]:j[1];
2868 }
2869 #endif
2870
2871 void
2872 global_table(void)
2873 {
2874 #ifndef __APPLE__
2875 NMTBL *n;
2876 int init;
2877 init=0;
2878 for(n=global_list;n;n = n->next) {
2879 if (is_code(n) || is_function(n)) {
2880 }
2881 if ((n->sc == GVAR||n->sc == STATIC) && n->dsp != -1) {
2882 if (is_code(n)||is_function(n)) continue;
2883 /* n->dsp = -1 means initialized global */
2884 if (init==0) {
2885 data_mode(0);
2886 init=1;
2887 }
2888 printf(".comm %s,%d\n",n->nm,size(n->ty));
2889 // .lcomm?
2890 }
2891 }
2892
2893 #else
2894
2895 NMTBL *n;
2896 int init;
2897 init=0;
2898 for(n=global_list;n;n = n->next) {
2899 if ((n->sc == GVAR) && n->dsp != -1) {
2900 if (is_code(n)||is_function(n)) continue;
2901 /* n->dsp = -1 means initialized global */
2902 if (init==0) {
2903 data_mode(0);
2904 init=1;
2905 }
2906 printf(".comm _%s,%d\n",n->nm,size(n->ty));
2907 } else if ((n->sc==STATIC) && n->dsp != -1) {
2908 /* n->dsp = -1 means initialized global */
2909 if (is_code(n)||is_function(n)) {
2910 printf("\t.set L_%s$stub,_%s\n",n->nm,n->nm);
2911 continue;
2912 }
2913 if (init==0) {
2914 data_mode(0);
2915 init=1;
2916 }
2917 printf(".lcomm _%s,%d\n",n->nm,size(n->ty));
2918 }
2919 }
2920 init=0;
2921 for(n = global_list;n!=&null_nptr;n = n->next) {
2922 if (n->sc == GVAR ||
2923 ((is_code(n) || is_function(n)) &&has_attr(n,FNAME)) ) {
2924 if (init==0) {
2925 printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n");
2926 init=1;
2927 }
2928 printf("L_%s$non_lazy_ptr:\n\t.indirect_symbol _%s\n\t.long\t0\n",
2929 n->nm,n->nm);
2930 }
2931 }
2932 for(n = global_list;n!=&null_nptr;n = n->next) {
2933 if (n->sc==EXTRN1) {
2934 if (!(is_code(n) || is_function(n))) {
2935 printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n");
2936 printf("L_%s$non_lazy_ptr:\n\t.indirect_symbol _%s\n\t.long\t0\n",
2937 n->nm,n->nm);
2938 }
2939 printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n");
2940 printf("L_%s$stub:\n",n->nm);
2941 printf("\t.indirect_symbol _%s\n",n->nm);
2942 printf("\thlt ; hlt ; hlt ; hlt ; hlt\n");
2943 }
2944 }
2945 printf(" .subsections_via_symbols\n");
2946 printf(" .section __TEXT,__textcoal_nt,coalesced,pure_instructions\n");
2947 printf(".weak_definition ___i686.get_pc_thunk.bx\n");
2948 printf(".private_extern ___i686.get_pc_thunk.bx\n");
2949 printf("___i686.get_pc_thunk.bx:\n");
2950 printf(" movl (%%esp), %%ebx\n");
2951 printf(" ret\n");
2952 #endif
2953 }
2954
2955
2956 void
2957 local_table(void)
2958 {
2959 NMTBL *n;
2960 int init;
2961 init=0;
2962 /* static local variables */
2963 for(n=local_static_list;n;n = n->next) {
2964 if (n->sc == STATIC) {
2965 if (init==0) {
2966 data_mode(0);
2967 init=1;
2968 }
2969 #ifdef __APPLE__
2970 if (n->dsp!= -1) /* -1 means initialized global */
2971 printf(".lcomm _%s,%d\n",n->nm,size(n->ty));
2972 #else
2973 if (n->dsp!= -1) /* -1 means initialized global */
2974 printf(".lcomm %s,%d\n",n->nm,size(n->ty));
2975 #endif
2976 }
2977 }
2978 }
2979
2980 void
2981 cstring_mode(int align)
2982 {
2983 if (output_mode!=RODATA_EMIT_MODE) {
2984 #ifndef __APPLE__
2985 printf(".section\t.rodata\n\t.align 2\n");
2986 #else
2987 printf("\t.cstring\n");
2988 #endif
2989 output_mode = RODATA_EMIT_MODE;
2990 }
2991 }
2992
2993 void
2994 text_mode(int align)
2995 {
2996 if (output_mode!=TEXT_EMIT_MODE) {
2997 printf(".text\n");
2998 // printf("\t.align 2\n");
2999 output_mode = TEXT_EMIT_MODE;
3000 }
3001 }
3002
3003 void
3004 data_mode(char *name)
3005 {
3006 if (output_mode!=DATA_EMIT_MODE) {
3007 printf(".data\n");
3008 output_mode = DATA_EMIT_MODE;
3009 }
3010 #ifndef __APPLE__
3011 if (name)
3012 printf("\t.type\t%s,@object\n",name);
3013 #endif
3014 }
3015
3016 #if FLOAT_CODE
3017
3018 /* floating point */
3019
3020
3021 char *
3022 fstore(int d)
3023 {
3024 return use?
3025 (d?"fstl":"fsts"):
3026 (d?"fstpl":"fstps")
3027 ;
3028 }
3029
3030 char *
3031 fstore_u(int d)
3032 {
3033 return d?"fstpl":"fstps";
3034 }
3035
3036 char *
3037 fload(int d)
3038 {
3039 return d?"fldl":"flds";
3040 }
3041
3042
3043 void code_dassign_gvar(int e2,int freg,int d)
3044 {
3045 #ifdef __APPLE__
3046 int r = get_ptr_cache(ncaddr(e2));
3047 if (cadr(e2))
3048 printf("\t%s %d(%s)\n",fstore(d),cadr(e2),register_name(r,0));
3049 else
3050 printf("\t%s (%s)\n",fstore(d),register_name(r,0));
3051 #else
3052 if (cadr(e2))
3053 printf("\t%s %s+%d\n",fstore(d),(ncaddr(e2))->nm,cadr(e2));
3054 else
3055 printf("\t%s %s\n",fstore(d),(ncaddr(e2))->nm);
3056 #endif
3057 }
3058
3059 void code_dassign_lvar(int e2,int freg,int d)
3060 {
3061 printf("\t%s ",fstore(d)); lvar(e2); printf("\n");
3062 }
3063
3064 void code_dassign_dregister(int e,int d,int freg)
3065 {
3066 error(-1);
3067 }
3068
3069 void code_dassign(int e2,int freg,int d)
3070 {
3071 printf("\t%s (%s)\n",fstore(d),register_name(e2,0));
3072 }
3073
3074 static double d0 = 1.0;
3075
3076 static int
3077 code_d1(double d)
3078 {
3079 int *i = (int *)&d0; int *j = (int *)&d;
3080 return (i[1] == 0x3ff00000)?j[0]:j[1];
3081 }
3082
3083 static int
3084 code_d2(double d)
3085 {
3086 int *i = (int *)&d0; int *j = (int *)&d;
3087 return (i[1] == 0x3ff00000)?j[1]:j[0];
3088 }
3089
3090 void code_dconst(int e2,int freg,int d)
3091 {
3092 int lb;
3093 double value = dcadr(e2);
3094
3095 if (value==0.0) {
3096 printf("\tfldz\n"); return;
3097 }
3098 if (value==1.0) {
3099 printf("\tfld1\n"); return;
3100 }
3101 #ifdef __APPLE__
3102 printf(" \t.literal8\n\t.align 3\n");
3103 #else
3104 printf(" \t.section\t.rodata\n\t.align 8\n");
3105 #endif
3106 lb=fwdlabel();
3107 printf("_%d:\n",lb);
3108 #if ENDIAN_D==0
3109 printf("\t.long\t0x%x,0x%x\n",code_d1(value),code_d2(value));
3110 #endif
3111 if (output_mode==TEXT_EMIT_MODE) {
3112 printf(".text\n");
3113 } else {
3114 text_mode(0);
3115 }
3116 #ifdef __APPLE__
3117 printf("\tfldl _%d-_%d(%%ebx)\n",lb,goffset_label);
3118 #else
3119 printf("\tfldl _%d\n",lb);
3120 #endif
3121 }
3122
3123 void
3124 code_builtin_fabsf(int e)
3125 {
3126 }
3127 void
3128 code_builtin_fabs(int e)
3129 {
3130 }
3131 void
3132 code_builtin_inff()
3133 {
3134 }
3135 void
3136 code_builtin_inf()
3137 {
3138 }
3139
3140 void code_dneg(int freg,int d)
3141 {
3142 printf("\tfchs\n");
3143 }
3144
3145 void code_d2i(int reg)
3146 {
3147 use_int(reg);
3148 printf("\tlea -%d(%%esp),%%esp\n",SIZE_OF_INT*2);
3149 printf("\tfnstcw (%%esp)\n");
3150 printf("\tmovl (%%esp), %s\n",register_name(creg,0));
3151 printf("\tmovb $12, 1(%%esp)\n");
3152 printf("\tfldcw (%%esp)\n");
3153 printf("\tfistpl %d(%%esp)\n",SIZE_OF_INT);
3154 printf("\tmovl %s, (%%esp)\n",register_name(creg,0));
3155 printf("\tfldcw (%%esp)\n");
3156 printf("\tpopl %s\n",register_name(creg,0));
3157 printf("\tpopl %s\n",register_name(creg,0));
3158 }
3159
3160 void code_i2d(int reg)
3161 {
3162 printf("\tpushl %s\n",register_name(creg,0));
3163 printf("\tfildl (%%esp)\n");
3164 printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT);
3165 }
3166
3167 void code_d2u(int reg)
3168 {
3169 use_int(reg);
3170 printf("\tlea -%d(%%esp),%%esp\n",SIZE_OF_INT*3);
3171 printf("\tfnstcw (%%esp)\n");
3172 printf("\tmovl (%%esp), %s\n",register_name(reg,0));
3173 printf("\tmovb $12, 1(%%esp)\n");
3174 printf("\tfldcw (%%esp)\n");
3175 printf("\tmovl %s, (%%esp)\n",register_name(reg,0));
3176 printf("\tfistpll %d(%%esp)\n",SIZE_OF_INT);
3177 printf("\tfldcw (%%esp)\n");
3178 printf("\tmovl %d(%%esp),%s\n",SIZE_OF_INT,register_name(reg,0));
3179 printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT*3);
3180 }
3181
3182 void code_u2d(int reg)
3183 {
3184 printf("\tpushl %s\n",register_name(creg,0));
3185 printf("\tpushl %s\n",register_name(creg,0));
3186 printf("\tmovl $0, %d(%%esp)\n",SIZE_OF_INT);
3187 printf("\tfildll (%%esp)\n");
3188 printf("\tlea %d(%%esp),%%esp\n",SIZE_OF_INT*2);
3189 }
3190
3191 void code_d2f(int reg) { }
3192 void code_f2d(int reg) { }
3193 void code_f2i(int reg) { code_d2i(reg); }
3194 void code_f2u(int reg) { code_d2u(reg); }
3195 void code_i2f(int reg) { code_i2d(reg); }
3196 void code_u2f(int reg) { code_u2d(reg); }
3197
3198 void code_drgvar(int e2,int d,int freg)
3199 {
3200 #ifdef __APPLE__
3201 int r = get_ptr_cache(ncaddr(e2));
3202 if (cadr(e2))
3203 printf("\t%s %d(%s)\n",fload(d),cadr(e2),register_name(r,0));
3204 else
3205 printf("\t%s (%s)\n",fload(d),register_name(r,0));
3206 #else
3207 if (cadr(e2))
3208 printf("\t%s %s+%d\n",fload(d),(ncaddr(e2))->nm,cadr(e2));
3209 else
3210 printf("\t%s %s\n",fload(d),(ncaddr(e2))->nm);
3211 #endif
3212 }
3213
3214
3215 void code_drlvar(int e2,int d,int freg)
3216 {
3217 printf("\t%s ",fload(d)); lvar(e2); printf("\n");
3218 }
3219
3220 void code_cmp_drgvar(int e2,int reg,int d,int label,int cond)
3221 {
3222 #ifdef __APPLE__
3223 int r = get_ptr_cache(ncaddr(e2));
3224 if (cadr(e2))
3225 printf("\tfcomp %d(%s)\n",cadr(e2),register_name(r,0));
3226 else
3227 printf("\tfcomp (%s)\n",register_name(r,0));
3228 #else
3229 if (cadr(e2))
3230 printf("\tfcomp %s+%d\n",(ncaddr(e2))->nm,cadr(e2));
3231 else
3232 printf("\tfcomp %s\n",(ncaddr(e2))->nm);
3233 #endif
3234 jcond(label,cond);
3235 }
3236
3237 void code_cmp_drlvar(int e2,int reg,int d,int label,int cond)
3238 {
3239 printf("\tfcomp "); lvar(e2); printf("\n");
3240 jcond(label,cond);
3241 }
3242
3243 void dtosop(int op,int reg,int e1)
3244 {
3245 switch(op) {
3246 case FADD:
3247 case DADD: printf("\tfaddp %%st,%%st(1)\n"); break;
3248 case FSUB:
3249 case DSUB: printf("\tfsubp %%st,%%st(1)\n"); break;
3250 case FDIV:
3251 case DDIV: printf("\tfdivp %%st,%%st(1)\n"); break;
3252 case FMUL:
3253 case DMUL: printf("\tfmulp %%st,%%st(1)\n"); break;
3254 case FCMP:
3255 case DCMP:
3256 printf("\tfucompp\n");
3257 printf("\tfnstsw\t%%ax\n");
3258 #ifdef __APPLE__
3259 if (regs[REG_EAX]==PTRC_REG)
3260 clear_ptr_cache_reg(REG_EAX);
3261 #endif
3262 break;
3263 }
3264 }
3265
3266 void
3267 code_dassop(int op,int reg,int d) {
3268 /* we have lvalue in creg, applied floating value is in %st(0) */
3269 emit_dpop(d); /* do nothing for 387 */
3270 printf("\t%s (%s)\n",fload(d),register_name(creg,0));
3271 dtosop(op,reg,0);
3272 printf("\t%s (%s)\n",fstore(d),register_name(creg,0));
3273 }
3274
3275 void
3276 code_register_dassop(int reg,int op,int d) {
3277 error(-1);
3278 }
3279
3280 void
3281 code_dpreinc(int e1,int e2,int d,int freg) {
3282 g_expr(e2);
3283 printf("\t%s (%s)\n",fload(d),register_name(creg,0));
3284 printf("\tfld1\n");
3285 if (caddr(e1)>0)
3286 printf("\tfaddp %%st,%%st(1)\n");
3287 else
3288 printf("\tfsubrp %%st,%%st(1)\n");
3289 printf("\t%s (%s)\n",fstore(d),register_name(creg,0));
3290 }
3291
3292 void
3293 code_dpostinc(int e1,int e2,int d,int freg) {
3294 g_expr(e2);
3295 printf("\t%s (%s)\n",fload(d),register_name(creg,0));
3296 if (use)
3297 printf("\t%s (%s)\n",fload(d),register_name(creg,0));
3298 printf("\tfld1\n");
3299 if (caddr(e1)>0)
3300 printf("\tfaddp %%st,%%st(1)\n");
3301 else
3302 printf("\tfsubrp %%st,%%st(1)\n");
3303 printf("\t%s (%s)\n",(use?fstore_u(d):fstore(d)),register_name(creg,0));
3304 }
3305
3306 #define COND_BRANCH 1
3307 #define COND_VALUE 2
3308
3309 /* return 1 if boolean expression */
3310
3311 int
3312 drexpr0(int e1, int e2,int l1, int op,int cond,int reg,int mode)
3313 {
3314 char *s;
3315 if (!cond) {
3316 switch(op) {
3317 case FOP+GT:
3318 return drexpr0(e2,e1,l1,FOP+GE,1,reg,mode);
3319 case FOP+GE:
3320 return drexpr0(e2,e1,l1,FOP+GT,1,reg,mode);
3321 case FOP+EQ:
3322 op=FOP+NEQ; break;
3323 case FOP+NEQ:
3324 op=FOP+EQ; break;
3325 case DOP+GT:
3326 return drexpr0(e2,e1,l1,DOP+GE,1,reg,mode);
3327 case DOP+GE:
3328 return drexpr0(e2,e1,l1,DOP+GT,1,reg,mode);
3329 case DOP+EQ:
3330 op=DOP+NEQ; break;
3331 case DOP+NEQ:
3332 op=DOP+EQ; break;
3333 default: return 0;
3334 }
3335 }
3336 s = "e";
3337 switch(op) {
3338 case DOP+GE:
3339 case FOP+GE:
3340 g_expr(list3(DCMP,e1,e2));
3341 printf("\ttestb\t$5,%%ah\n");
3342 break;
3343 case DOP+GT:
3344 case FOP+GT:
3345 g_expr(list3(DCMP,e1,e2));
3346 printf("\ttestb\t$69,%%ah\n");
3347 break;
3348 case DOP+EQ:
3349 case FOP+EQ:
3350 g_expr(list3(DCMP,e1,e2));
3351 printf("\tandb\t$69,%%ah\n");
3352 printf("\txorb\t$64,%%ah\n");
3353 break;
3354 case DOP+NEQ:
3355 case FOP+NEQ:
3356 g_expr(list3(DCMP,e1,e2));
3357 printf("\tandb\t$69,%%ah\n");
3358 printf("\txorb\t$64,%%ah\n");
3359 s = "ne";
3360 break;
3361 default:
3362 return 0;
3363 }
3364 if (mode==COND_BRANCH) {
3365 printf("\tj%s\t_%d\n",s,l1);
3366 } else {
3367 use_data_reg(reg,0);
3368 printf("\tset%s\t%s\n",s,register_name(reg,1));
3369 printf("\tmovzbl\t%s,%s\n",
3370 register_name(reg,1),register_name(reg,0));
3371 }
3372 return 1;
3373 }
3374
3375 int
3376 drexpr(int e1, int e2,int l1, int op,int cond)
3377 {
3378 drexpr0(e1, e2,l1, op,cond,USE_CREG,COND_BRANCH);
3379 return l1;
3380 }
3381
3382 static int
3383 drexpr_bool(int e1, int reg)
3384 {
3385 return drexpr0(cadr(e1), caddr(e1),0, car(e1),1,reg,COND_VALUE);
3386 }
3387
3388
3389 void
3390 code_dregister(int e2,int freg,int d)
3391 {
3392 error(-1);
3393 }
3394
3395 void
3396 code_cmp_dregister(int e2,int d,int label,int cond)
3397 {
3398 if (e2!=USE_CREG)
3399 error(-1);
3400 #ifdef __APPLE__
3401 if (regs[REG_EAX]==PTRC_REG)
3402 clear_ptr_cache_reg(REG_EAX);
3403 #endif
3404 printf("\tfldz\n");
3405 printf("\tfucompp\n");
3406 printf("\tfnstsw\t%%ax\n");
3407 printf("\tandb\t$69,%%ah\n");
3408 printf("\txorb\t$64,%%ah\n");
3409 jcond(label,cond);
3410 }
3411
3412 int pop_fregister()
3413 {
3414 if (freg_sp<0) { error(-1); return -1;}
3415 // printf("## fpop: %d\n",freg_sp-1);
3416 return freg_stack[--freg_sp];
3417 }
3418
3419 int
3420 emit_dpop(int d)
3421 {
3422 int xreg;
3423 if ((xreg=pop_fregister())==-1) {
3424 } else if (xreg<= -REG_LVAR_OFFSET) {
3425 code_drlvar(REG_LVAR_OFFSET+xreg,1,freg);
3426 free_lvar(xreg+REG_LVAR_OFFSET);
3427 /* pushed order is reversed. We don't need this for commutable
3428 operator, but it is ok to do this. */
3429 printf("\tfxch\t%%st(1)\n");
3430 }
3431 return xreg;
3432 }
3433
3434
3435 void emit_dpop_free(int e1,int d)
3436 {
3437 }
3438
3439 void emit_dpush(int type)
3440 {
3441 if (freg_sp>=MAX_FPU_STACK) code_save_fstacks();
3442 if (freg_sp>MAX_MAX) error(-1);
3443 freg_stack[freg_sp++]=-1;
3444 // printf("## fpush:%d\n",freg_sp);
3445 }
3446
3447 #endif
3448
3449 void
3450 code_save_stacks()
3451 {
3452 /* registers stacks are saved in local variable */
3453 int i,reg;
3454 for(i=0;i<reg_sp;i++) {
3455 if ((reg=reg_stack[i])>=0) {
3456 code_assign_lvar(
3457 (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0);
3458 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
3459 if (regs[reg]!=REG_VAR) free_register(reg);
3460 }
3461 }
3462 #if FLOAT_CODE
3463 code_save_fstacks();
3464 #endif
3465 }
3466
3467 static void
3468 code_clear_stack_reg(int reg1)
3469 {
3470 /* specified registers stacks are saved in local variable */
3471 /* temporal registers are saved in local variable */
3472 int i,reg;
3473 if (regs[reg1]==PTRC_REG)
3474 clear_ptr_cache_reg(reg1);
3475
3476 for(i=0;i<reg_sp;i++) {
3477 if ((reg=reg_stack[i])>=0 && reg==reg1) {
3478 code_assign_lvar(
3479 (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0);
3480 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET;
3481 if (regs[reg]!=REG_VAR) free_register(reg);
3482 }
3483 }
3484 }
3485
3486 #if FLOAT_CODE
3487 void
3488 code_save_fstacks()
3489 {
3490 /* stacks in fpu are saved in local variable */
3491 int xreg,sp,uses;
3492 uses = use; use = 0;
3493 sp=freg_sp;
3494 while(sp-->0) {
3495 if ((xreg=freg_stack[sp])==-1) {
3496 code_dassign_lvar(
3497 (freg_stack[sp]=new_lvar(SIZE_OF_DOUBLE)),freg,1);
3498 freg_stack[sp]= freg_stack[sp]-REG_LVAR_OFFSET;
3499 }
3500 }
3501 use = uses;
3502 }
3503 #endif
3504
3505
3506
3507 #if LONGLONG_CODE
3508
3509
3510 /* 64bit int part */
3511
3512 static void
3513 pcond(char *s,int l1)
3514 {
3515 printf("\tj%s\t_%d\n",s,l1);
3516 }
3517
3518 int
3519 lrexpr(int e1, int e2,int l1, int op,int cond)
3520 {
3521 int l2;
3522 code_save_stacks();
3523 g_expr(e1);
3524 emit_lpush();
3525 g_expr(e2);
3526 // we are sure %ecx is free
3527 // %ebx is used in Intel Mac
3528 stack_depth -= SIZE_OF_INT * 2;
3529 printf("\tpopl %%ecx\n"); // LSW
3530 printf("\tcmpl %%edx,(%%esp)\n"); // MSW
3531 printf("\tpopl %%edx\n");
3532 l2 = fwdlabel();
3533 // cond==0 jump on false condtion ( if(x) => rexpr(.. cond=0 ...) )
3534 switch(op) {
3535 case LOP+GT:
3536 case LOP+GE:
3537 pcond(code_gt(1),cond?l1:l2);
3538 pcond(code_eq(0),cond?l2:l1);
3539 break;
3540 case LOP+UGT:
3541 case LOP+UGE:
3542 pcond(code_ugt(1),cond?l1:l2);
3543 pcond(code_eq(0), cond?l2:l1);
3544 break;
3545 case LOP+EQ:
3546 pcond(code_eq(0),(cond?l2:l1));
3547 break;
3548 case LOP+NEQ:
3549 pcond(code_eq(0),(cond?l1:l2));
3550 break;
3551 default:
3552 error(-1);
3553 }
3554 printf("\tsubl %%eax,%%ecx\n");
3555 switch(op) {
3556 case LOP+GT: pcond(code_gt(cond), l1); break;
3557 case LOP+GE: pcond(code_ge(cond), l1); break;
3558 case LOP+UGT: pcond(code_ugt(cond), l1); break;
3559 case LOP+UGE: pcond(code_uge(cond), l1); break;
3560 case LOP+EQ: pcond(code_eq(cond),l1); break;
3561 case LOP+NEQ: pcond(code_eq(!cond),l1); break;
3562 }
3563 fwddef(l2);
3564 return l1;
3565 }
3566
3567 int emit_lpop()
3568 {
3569 return 0;
3570 }
3571
3572 void code_lregister(int e2,int reg)
3573 {
3574 use_longlong(reg);
3575 if (reg!=REG_L) {
3576 printf("\tmovl %%esi,%s\n",l_eax(reg));
3577 printf("\tmovl %%edi,%s\n",l_edx(reg));
3578 }
3579 }
3580
3581 void code_cmp_lregister(int reg,int label,int cond)
3582 {
3583 char *crn;
3584 use_int(reg);
3585 crn = register_name(reg,0);
3586 printf("\tmovl %%esi,%s\n",crn);
3587 printf("\torl %%edi,%s\n",crn);
3588 printf("\ttestl %s,%s\n",crn,crn);
3589 jcond(label,cond);
3590 }
3591
3592 void code_cmp_lrgvar(int e1,int e2,int label,int cond)
3593 {
3594 char *n,*crn;
3595 use_int(e2);
3596 crn = register_name(e2,0);
3597 #ifdef __APPLE__
3598 int r = get_ptr_cache(ncaddr(e1));
3599 n = register_name(r,0);
3600 if (cadr(e1)) {
3601 printf("\tmovl %d(%s),%s\n",cadr(e1),n,crn);
3602 printf("\torl %d(%s),%s\n",cadr(e1)+4,n,crn);
3603 } else {
3604 printf("\tmovl (%s),%s\n",n,crn);
3605 printf("\torl 4(%s),%s\n",n,crn);
3606 }
3607 #else
3608 n = (ncaddr(e1))->nm;
3609 if (cadr(e1)) {
3610 printf("\tmovl %s+%d,%s\n",n,cadr(e1),crn);
3611 printf("\torl %s+%d,%s\n",n,cadr(e1)+4,crn);
3612 } else {
3613 printf("\tmovl %s,%s\n",n,crn);
3614 printf("\torl %s+4,%s\n",n,crn);
3615 }
3616 #endif
3617 printf("\ttestl %s,%s\n",crn,crn);
3618 jcond(label,cond);
3619 }
3620
3621 void code_cmp_lrlvar(int e1,int e2,int label,int cond)
3622 {
3623 char *crn;
3624 use_int(e2);
3625 crn = register_name(e2,0);
3626 printf("\tmovl "); lvar(e1); printf(",%s\n",crn);
3627 printf("\torl "); lvar(e1+4); printf(",%s\n",crn);
3628 printf("\ttestl %s,%s\n",crn,crn);
3629 jcond(label,cond);
3630 }
3631
3632 void code_lassign(int e1,int e2)
3633 {
3634 char *rn;
3635 // e1 = e2
3636 use_longlong(e2);
3637 rn = register_name(e1,0);
3638 #if ENDIAN_L==0
3639 printf("\tmovl %s,(%s)\n",l_eax(e2),rn);
3640 printf("\tmovl %s,4(%s)\n",l_edx(e2),rn);
3641 #endif
3642 }
3643
3644 void code_lassign_gvar(int e1,int e2)
3645 {
3646 char *n;
3647 use_longlong(e2);
3648 #if ENDIAN_L==0
3649 #ifdef __APPLE__
3650 int r = get_ptr_cache(ncaddr(e1));
3651 n = register_name(r,0);
3652 if (cadr(e1)) {
3653 printf("\tmovl %s,%d(%s)\n",l_eax(e2),cadr(e1),n);
3654 printf("\tmovl %s,%d(%s)\n",l_edx(e2),cadr(e1)+4,n);
3655 } else {
3656 printf("\tmovl %s,(%s)\n",l_eax(e2),n);
3657 printf("\tmovl %s,4(%s)\n",l_edx(e2),n);
3658 }
3659 #else
3660 n = (ncaddr(e1))->nm;
3661 if (cadr(e1)) {
3662 printf("\tmovl %s,%s+%d\n",l_eax(e2),n,cadr(e1));
3663 printf("\tmovl %s,%s+%d\n",l_edx(e2),n,cadr(e1)+4);
3664 } else {
3665 printf("\tmovl %s,%s\n",l_eax(e2),n);
3666 printf("\tmovl %s,%s+4\n",l_edx(e2),n);
3667 }
3668 #endif
3669 #endif
3670 }
3671
3672 void code_lassign_lvar(int e1,int e2)
3673 {
3674 use_longlong(e2);
3675 #if ENDIAN_L==0
3676 printf("\tmovl %s,",l_eax(e2)); lvar(e1); printf("\n");
3677 printf("\tmovl %s,",l_edx(e2)); lvar(e1+4); printf("\n");
3678 #endif
3679 }
3680
3681 void code_lassign_lregister(int e2,int reg)
3682 {
3683 // e2 = reg
3684 use_longlong(reg);
3685 if (e2!=reg) {
3686 printf("\tmovl %s,%s\n",l_eax(reg),l_eax(e2));
3687 printf("\tmovl %s,%s\n",l_edx(reg),l_edx(e2));
3688 }
3689 }
3690
3691 void
3692 code_lconst(int e1,int creg)
3693 {
3694 use_longlong(creg);
3695 #if ENDIAN_L==0
3696 printf("\tmovl $%d,%s\n",code_l1(lcadr(e1)),l_eax(creg));
3697 printf("\tmovl $%d,%s\n",code_l2(lcadr(e1)),l_edx(creg));
3698 #endif
3699 }
3700
3701 void code_lneg(int e1)
3702 {
3703 use_longlong(e1);
3704 printf("\tnegl %s\n",l_eax(e1));
3705 printf("\tadcl $0,%s\n",l_edx(e1));
3706 printf("\tnegl %s\n",l_edx(e1));
3707 }
3708
3709 void code_lrgvar(int e1,int e2)
3710 {
3711 char *n;
3712 use_longlong(e2);
3713 #if ENDIAN_L==0
3714 #ifdef __APPLE__
3715 int r = get_ptr_cache(ncaddr(e1));
3716 n = register_name(r,0);
3717 if (cadr(e1)) {
3718 printf("\tmovl %d(%s),%s\n",cadr(e1),n,l_eax(e2));
3719 printf("\tmovl %d(%s),%s\n",cadr(e1)+4,n,l_edx(e2));
3720 } else {
3721 printf("\tmovl (%s),%s\n",n,l_eax(e2));
3722 printf("\tmovl 4(%s),%s\n",n,l_edx(e2));
3723 }
3724 #else
3725 n = (ncaddr(e1))->nm;
3726 if (cadr(e1)) {
3727 printf("\tmovl %s+%d,%s\n",n,cadr(e1),l_eax(e2));
3728 printf("\tmovl %s+%d,%s\n",n,cadr(e1)+4,l_edx(e2));
3729 } else {
3730 printf("\tmovl %s,%s\n",n,l_eax(e2));
3731 printf("\tmovl %s+4,%s\n",n,l_edx(e2));
3732 }
3733 #endif
3734 #endif
3735 }
3736
3737 void code_lrlvar(int e1,int e2)
3738 {
3739 use_longlong(e2);
3740 #if ENDIAN_L==0
3741 printf("\tmovl "); lvar(e1); printf(",%s\n",l_eax(e2));
3742 printf("\tmovl "); lvar(e1+4); printf(",%s\n",l_edx(e2));
3743 #endif
3744 }
3745
3746 #define check_lreg(reg) if (reg==REG_L) code_lassign_lregister(reg,REG_LCREG)
3747
3748 void
3749 ltosop(int op,int reg,int e2)
3750 {
3751 char *opl,*oph,*call;
3752 int lb;
3753
3754 // e2 (operand) is on the top of the stack
3755 use_longlong(reg);
3756 opl = 0; call=0;
3757 stack_depth -= SIZE_OF_INT * 2;
3758
3759 switch(op) {
3760 case LLSHIFT:
3761 case LULSHIFT:
3762 printf("\tmovl %%ecx,4(%%esp)\n");
3763 printf("\tpopl %%ecx\n");
3764 printf("\tshldl %%eax,%%edx\n");
3765 printf("\tsall %%cl,%%eax\n");
3766 printf("\ttestb $32,%%cl\n");
3767 printf("\tje\t_%d\n",(lb=fwdlabel()));
3768 printf("\tmovl %%eax,%%edx\n");
3769 printf("\txorl %%eax,%%eax\n");
3770 fwddef(lb);
3771 printf("\tpopl %%ecx\n");
3772 check_lreg(reg);
3773 return;
3774 case LRSHIFT:
3775 printf("\tmovl %%ecx,4(%%esp)\n");
3776 printf("\tpopl %%ecx\n");
3777 printf("\tshrdl %%edx,%%eax\n");
3778 printf("\tsarl %%cl,%%edx\n");
3779 printf("\ttestb $32,%%cl\n");
3780 printf("\tje\t_%d\n",(lb=fwdlabel()));
3781 printf("\tmovl %%edx,%%eax\n");
3782 printf("\tsarl $31,%%edx\n");
3783 fwddef(lb);
3784 printf("\tpopl %%ecx\n");
3785 check_lreg(reg);
3786 return;
3787 case LURSHIFT:
3788 printf("\tmovl %%ecx,4(%%esp)\n");
3789 printf("\tpopl %%ecx\n");
3790 printf("\tshrdl %%edx,%%eax\n");
3791 printf("\tshrl %%cl,%%edx\n");
3792 printf("\ttestb $32,%%cl\n");
3793 printf("\tje\t_%d\n",(lb=fwdlabel()));
3794 printf("\tmovl %%edx,%%eax\n");
3795 printf("\txorl %%edx,%%edx\n");
3796 fwddef(lb);
3797 printf("\tpopl %%ecx\n");
3798 check_lreg(reg);
3799 return;
3800 }
3801 switch(op) {
3802 case LADD: opl="addl";oph="adcl"; break;
3803 case LSUB: opl="subl";oph="sbbl"; break;
3804 case LBAND: opl=oph="andl"; break;
3805 case LEOR: opl=oph="xorl"; break;
3806 case LBOR: opl=oph="orl"; break;
3807 case LMUL:
3808 case LUMUL:
3809 printf("\tpushl %%edx\n");
3810 printf("\tpushl %%eax\n");
3811 printf("\tpushl %%ecx\n");
3812 // 0 saved ecx
3813 // 4 c_l
3814 // 8 c_h
3815 // 12 o_l
3816 // 16 o_h
3817 printf("\tmull 12(%%esp)\n"); // c_l*o_l -> %edx,%eax
3818 printf("\tmovl 4(%%esp),%%ecx\n"); // c_l->%ecx
3819 printf("\timull 16(%%esp),%%ecx\n"); // c_l*o_h->%ecx
3820 printf("\taddl %%ecx,%%edx\n"); // %edx+%ecx->%edx
3821 printf("\tmovl 8(%%esp),%%ecx\n"); // c_h->%ecx
3822 printf("\timull 12(%%esp),%%ecx\n"); // c_h*o_l->%ecx
3823 printf("\taddl %%ecx,%%edx\n"); // %edx+%ecx->%edx
3824 printf("\tpopl %%ecx\n");
3825 // printf("\taddl $8,%%esp\n");
3826 printf("\tlea 16(%%esp),%%esp\n");
3827 return;
3828 #ifdef __APPLE__
3829 case LDIV: call="L___divdi3$stub";
3830 extern_define("__divdi3",0,FUNCTION,1); break;
3831 case LUDIV: call="L___udivdi3$stub";
3832 extern_define("__udivdi3",0,FUNCTION,1); break;
3833 case LMOD: call="L___moddi3$stub";
3834 extern_define("__moddi3",0,FUNCTION,1); break;
3835 case LUMOD: call="L___umoddi3$stub";
3836 extern_define("__umoddi3",0,FUNCTION,1); break;
3837 #else
3838 case LDIV: call="__divdi3"; break;
3839 case LUDIV: call="__udivdi3"; break;
3840 case LMOD: call="__moddi3"; break;
3841 case LUMOD: call="__umoddi3"; break;
3842 #endif
3843 default: error(-1);
3844 }
3845 if (opl) {
3846 printf("\t%s (%%esp),%%eax\n\t%s 4(%%esp),%%edx\n",opl,oph);
3847 printf("\tlea 8(%%esp),%%esp\n");
3848 check_lreg(reg);
3849 } else if (call) {
3850 #ifdef __APPLE__
3851 clear_ptr_cache();
3852 printf("\tpushl %%edx\n");
3853 printf("\tpushl %%eax\n");
3854 printf("\tcall %s\n",call);
3855 printf("\tlea 16(%%esp),%%esp\n");
3856 #else
3857 printf("\tpushl %%edx\n");
3858 printf("\tpushl %%eax\n");
3859 printf("\tcall %s\n",call);
3860 printf("\tlea 16(%%esp),%%esp\n");
3861 #endif
3862 check_lreg(reg);
3863 } else {
3864 error(-1);
3865 }
3866 }
3867
3868 int code_lconst_op_p(int op,int e) {
3869 long long l;
3870 if (car(e)==CONST) l = cadr(e);
3871 else if (car(e)==LCONST) l = lcadr(e);
3872 else return 0;
3873
3874 switch(op) {
3875 case LLSHIFT:
3876 case LULSHIFT:
3877 case LRSHIFT:
3878 case LURSHIFT:
3879 return (0<=l&&l<=63);
3880 case LMUL:
3881 case LUMUL:
3882 case LUDIV:
3883 /* case LDIV: */
3884 return -0x10000000LL<l&&l<0x10000000LL && ilog(l);
3885 case LADD:
3886 case LSUB:
3887 case LBAND:
3888 case LEOR:
3889 case LBOR:
3890 return 1;
3891 default:
3892 return 0;
3893 }
3894 }
3895
3896 void loprtc(int op,int reg,int e) {
3897 char *opl,*oph=0;
3898 int vl,il;
3899 int vh;
3900 long long l=0;
3901
3902 if (car(e)==CONST) l = cadr(e);
3903 else if (car(e)==LCONST) l = lcadr(e);
3904 else error(-1);
3905
3906 vl = code_l1(l);
3907 vh = code_l2(l);
3908 il = l;
3909
3910 use_longlong(reg);
3911 opl = 0;
3912
3913 switch(op) {
3914 case LMUL: case LUMUL:
3915 vl=il=ilog(il);
3916 case LLSHIFT:
3917 case LULSHIFT:
3918 if (il==0) return;
3919 else if (il==32) {
3920 code_register(regv_l(reg),regv_h(reg));
3921 code_const(0,regv_l(reg));
3922 return;
3923 } else if (il>32) {
3924 code_register(regv_l(reg),regv_h(reg));
3925 printf("\tsall $%d,%s\n",(int)il-32,l_edx(reg));
3926 code_const(0,regv_l(reg));
3927 return;
3928 }
3929 printf("\tshldl $%d,%s,%s\n",vl,l_eax(reg),l_edx(reg));
3930 printf("\tsall $%d,%s\n",(int)il,l_eax(reg)); return;
3931 case LRSHIFT:
3932 if (il==0) return;
3933 else if (il==32) {
3934 code_register(regv_h(reg),regv_l(reg));
3935 creg = ireg = REG_EAX;
3936 code_i2ll(reg);
3937 return;
3938 } else if (il>32) {
3939 code_register(regv_h(reg),regv_l(reg));
3940 printf("\tsarl $%d,%s\n",(int)il-32,l_eax(reg));
3941 creg = ireg = REG_EAX;
3942 code_i2ll(reg);
3943 return;
3944 }
3945 printf("\tshrdl $%d,%s,%s\n",(int)il,l_edx(reg),l_eax(reg));
3946 printf("\tsarl $%d,%s\n",(int)il,l_edx(reg));
3947 return;
3948 case LUDIV:
3949 il=ilog(il);
3950 case LURSHIFT:
3951 if (il==0) return;
3952 else if (il==32) {
3953 code_register(regv_h(reg),regv_l(reg));
3954 code_const(0,regv_h(reg));
3955 return;
3956 } else if (il>32) {
3957 if (il>64) error(-1);
3958 code_register(regv_h(reg),regv_l(reg));
3959 printf("\tsarl $%d,%s\n",(int)il-32,l_eax(reg));
3960 code_const(0,regv_h(reg));
3961 return;
3962 }
3963 printf("\tshrdl $%d,%s,%s\n",(int)il,l_edx(reg),l_eax(reg));
3964 printf("\tshrl $%d,%s\n",(int)il,l_edx(reg));
3965 return;
3966 }
3967 switch(op) {
3968 case LADD: opl="addl";oph="adcl"; break;
3969 case LSUB: opl="subl";oph="sbbl"; break;
3970 case LEOR: opl=oph="xorl"; break;
3971 case LBOR: opl=oph="orl"; break;
3972 case LBAND: opl=oph="andl"; break;
3973 default: error(-1);
3974 }
3975 printf("\t%s $%d,%s\n\t%s $%d,%s\n",opl,vl,l_eax(reg),oph,vh,l_edx(reg));
3976 }
3977
3978 void emit_lpop_free(int e1)
3979 {
3980 // printf("\taddl $8,%%esp\n");
3981 }
3982
3983 void emit_lpush()
3984 {
3985 stack_depth += SIZE_OF_INT * 2;
3986 printf("\tpushl %%edx\n\tpushl %%eax\n");
3987 }
3988
3989 void code_i2ll(int reg)
3990 {
3991 int reg0 = USE_CREG;
3992 int creg0 = creg;
3993
3994 use_longlong(reg0);
3995 use_register(creg0,REG_EAX,1);
3996
3997 printf("\tcltd\n");
3998 check_lreg(reg);
3999 lreg = creg = reg0;
4000 }
4001
4002 void code_i2ull(int reg)
4003 {
4004 code_i2ll(reg);
4005 }
4006
4007 void code_u2ll(int reg)
4008 {
4009 int reg0 = USE_CREG;
4010 int creg0 = creg;
4011
4012 use_longlong(reg0);
4013 use_register(creg0,REG_EAX,1);
4014
4015 use_longlong(reg0);
4016 printf("\txorl %%edx,%%edx\n");
4017 check_lreg(reg);
4018 lreg = creg = reg0;
4019 }
4020
4021 void code_u2ull(int reg)
4022 {
4023 code_u2ll(reg);
4024 }
4025
4026 void code_ll2i(int reg)
4027 {
4028 use_int(reg);
4029 if (REG_EAX!=reg)
4030 printf("\tmovl %%eax,%s\n",register_name(creg,0));
4031 }
4032
4033 void code_ll2u(int reg)
4034 {
4035 code_ll2i(reg);
4036 }
4037
4038 void code_ull2i(int reg)
4039 {
4040 code_ll2i(reg);
4041 }
4042
4043 void code_ull2u(int reg)
4044 {
4045 code_ll2i(reg);
4046 }
4047
4048 #if FLOAT_CODE
4049 void code_d2ll(int reg)
4050 {
4051 use_longlong(reg);
4052 #if 1
4053 printf("\tsubl $64, %%esp\n");
4054 printf("\tfnstcw 34(%%esp)\n");
4055 printf("\tmovzwl 34(%%esp), %%eax\n");
4056 printf("\tmovb $12, %%ah\n");
4057 printf("\tmovw %%ax, 32(%%esp)\n");
4058 printf("\tfldcw 32(%%esp)\n");
4059 printf("\tfistpll 52(%%esp)\n");
4060 printf("\tfldcw 34(%%esp)\n");
4061 printf("\tmovl 52(%%esp), %%eax\n");
4062 printf("\tmovl 56(%%esp), %%edx\n");
4063 printf("\taddl $64, %%esp\n");
4064 #else
4065 printf("\tsubl $40,%%esp\n");
4066 printf("\tfnstcw 2(%%esp)\n");
4067 printf("\tmovw 2(%%esp),%%ax\n");
4068 printf("\torw $3072,%%ax\n");
4069 printf("\tmovw %%ax,0(%%esp)\n");
4070 printf("\tfldcw 0(%%esp)\n");
4071 printf("\tfistpll 12(%%esp)\n");
4072 printf("\tfldcw 2(%%esp)\n");
4073 printf("\tmovl 12(%%esp),%%eax\n");
4074 printf("\tmovl 16(%%esp),%%edx\n");
4075 printf("\taddl $40,%%esp\n");
4076 #endif
4077 check_lreg(reg);
4078 }
4079
4080 void code_d2ull(int reg)
4081 {
4082 use_longlong(reg);
4083 #ifdef __APPLE__
4084 clear_ptr_cache();
4085 #endif
4086 printf("\tsubl $16,%%esp\n");
4087 printf("\tfstpl (%%esp)\n");
4088 #ifdef __APPLE__
4089 printf("\tcall L___fixunsdfdi$stub\n");
4090 extern_define("__fixunsdfdi",0,FUNCTION,1);
4091 #else
4092 printf("\tcall __fixunsdfdi\n");
4093 #endif
4094 printf("\taddl $16,%%esp\n");
4095 }
4096
4097 void code_f2ll(int reg)
4098 {
4099 code_d2ll(reg);
4100 }
4101
4102 void code_f2ull(int reg)
4103 {
4104 use_longlong(reg);
4105 #ifdef __APPLE__
4106 clear_ptr_cache();
4107 #endif
4108 printf("\tsubl $16,%%esp\n");
4109 printf("\tfstps (%%esp)\n");
4110 #ifdef __APPLE__
4111 printf("\tcall L___fixunssfdi$stub\n");
4112 extern_define("__fixunssfdi",0,FUNCTION,1);
4113 #else
4114 printf("\tcall __fixunssfdi\n");
4115 #endif
4116 printf("\taddl $16,%%esp\n");
4117 }
4118
4119 void code_ll2d(int reg)
4120 {
4121 printf("\tsubl $8,%%esp\n");
4122 printf("\tmovl %%eax,(%%esp)\n");
4123 printf("\tmovl %%edx,4(%%esp)\n");
4124 printf("\tfildll (%%esp)\n");
4125 printf("\taddl $8,%%esp\n");
4126 }
4127
4128 void code_ll2f(int reg)
4129 {
4130 code_ll2d(reg);
4131 }
4132
4133 void code_ull2d(int reg)
4134 {
4135 code_ll2d(reg);
4136 }
4137
4138 void code_ull2f(int reg)
4139 {
4140 code_ll2d(reg);
4141 }
4142
4143 #endif
4144
4145
4146 void code_lpreinc(int e1,int e2,int reg)
4147 {
4148 int dir = caddr(e1);
4149 int creg0;
4150 char *crn;
4151 if (car(e2)==LREGISTER) {
4152 use_longlong(reg);
4153 printf("\taddl $%d,%%esi\n",dir);
4154 printf("\tadcl $%d,%%edi\n",dir>0?0:-1);
4155 if (use && reg!=REG_L) {
4156 code_lregister(REG_L,reg);
4157 }
4158 return;
4159 }
4160 g_expr(e2);
4161 crn = register_name(creg0=creg,0);
4162 printf("\taddl $%d,(%s)\n",dir,crn);
4163 printf("\tadcl $%d,4(%s)\n",dir>0?0:-1,crn);
4164 use_longlong(reg);
4165 lload(creg0,0,reg);
4166 }
4167
4168 void code_lpostinc(int e1,int e2,int reg)
4169 {
4170 int dir = caddr(e1);
4171 int creg0;
4172 char *crn;
4173 if (car(e2)==LREGISTER) {
4174 use_longlong(reg);
4175 if (use && reg!=REG_L) {
4176 code_lregister(REG_L,reg);
4177 }
4178 printf("\taddl $%d,%%esi\n",dir);
4179 printf("\tadcl $%d,%%edi\n",dir>0?0:-1);
4180 return;
4181 }
4182 g_expr(e2);
4183 crn = register_name(creg0=creg,0);
4184 printf("\taddl $%d,(%s)\n",dir,crn);
4185 printf("\tadcl $%d,4(%s)\n",dir>0?0:-1,crn);
4186 if (use) {
4187 use_longlong(reg);
4188 lload(creg0,0,reg);
4189 printf("\taddl $%d,%s\n",-dir,l_eax(reg));
4190 printf("\tadcl $%d,%s\n",-dir>0?0:-1,l_edx(reg));
4191 }
4192 }
4193
4194 void code_lassop(int op,int reg)
4195 {
4196 error(-1);
4197 }
4198
4199 void
4200 code_register_lassop(int reg,int op) {
4201 error(-1);
4202 }
4203
4204
4205 #endif
4206
4207
4208
4209
4210
4211 #if CASE_CODE
4212
4213 int
4214 code_table_jump_p(int delta) { return 1; }
4215
4216 void
4217 code_table_jump(int l,int csvalue,int delta,int max,int min,int dlabel)
4218 {
4219 char *crn;
4220 // use_register(creg,csvalue,0);
4221 set_ireg(csvalue,0);
4222 crn = register_name(creg,0);
4223 printf("\tsubl\t$%d,%s\n",min,crn);
4224 printf("\tcmpl\t$%d,%s\n",max-min,crn);
4225 printf("\tja\t_%d\n",dlabel);
4226 if (delta==1) {
4227 #ifdef __APPLE__
4228 printf("\tmovl\t_%d-_%d(%%ebx,%s,4),%s\n",l,goffset_label,crn,crn);
4229 printf("\taddl\t%%ebx,%s\n",crn);
4230 printf("\tjmp\t*%s\n",crn);
4231 #else
4232 printf("\tjmp\t*_%d(,%s,4)\n",l,crn);
4233 #endif
4234 return;
4235 }
4236 #ifdef __APPLE__
4237 if (regs[REG_EAX]==PTRC_REG)
4238 clear_ptr_cache_reg(REG_EAX);
4239 #endif
4240 use_register(creg,REG_EAX,1);
4241 crn = "%eax";
4242
4243 switch(delta) {
4244 case 2:
4245 printf("\tmovl\t$1,%%edx\n");
4246 printf("\tandl\t%%eax,%%edx\n");
4247 printf("\tjne\t_%d\n",dlabel);
4248 #ifdef __APPLE__
4249 printf("\tmovl\t_%d-_%d(%%ebx,%s,2),%s\n",l,goffset_label,crn,crn);
4250 printf("\taddl\t%%ebx,%s\n",crn);
4251 printf("\tjmp\t*%s\n",crn);
4252 #else
4253 printf("\tjmp\t*_%d(,%%eax,2)\n",l);
4254 #endif
4255 break;
4256 case 4:
4257 printf("\tmovl\t$3,%%edx\n");
4258 printf("\tandl\t%%eax,%%edx\n");
4259 printf("\tjne\t_%d\n",dlabel);
4260 #ifdef __APPLE__
4261 printf("\tmovl\t_%d-_%d(%%ebx,%s),%s\n",l,goffset_label,crn,crn);
4262 printf("\taddl\t%%ebx,%s\n",crn);
4263 printf("\tjmp\t*%s\n",crn);
4264 #else
4265 printf("\tjmp\t*_%d(%%eax)\n",l);
4266 #endif
4267 break;
4268 default:
4269 printf("\tmovl $%d,%%ecx\n",delta);
4270 printf("\txor %%edx,%%edx\n\tdivl %%ecx\n");
4271 printf("\tandl\t%%edx,%%edx\n");
4272 printf("\tjne\t_%d\n",dlabel);
4273 #ifdef __APPLE__
4274 printf("\tmovl\t_%d-_%d(%%ebx,%s,4),%s\n",l,goffset_label,crn,crn);
4275 printf("\taddl\t%%ebx,%s\n",crn);
4276 printf("\tjmp\t*%s\n",crn);
4277 #else
4278 printf("\tjmp\t*_%d(,%%eax,4)\n",l);
4279 #endif
4280 break;
4281 }
4282
4283 }
4284
4285 void
4286 code_table_open(int l)
4287 {
4288 output_mode=DATA_EMIT_MODE;
4289 #ifdef __APPLE__
4290 printf(" \t.align 2\n");
4291 #else
4292 printf(" \t.section\t.rodata\n\t.align 4\n");
4293 #endif
4294 fwddef(l);
4295 }
4296
4297 void
4298 code_table_value(int label,int table_top)
4299 {
4300 #ifdef __APPLE__
4301 printf("\t.long _%d-_%d\n",label,goffset_label);
4302 #else
4303 printf("\t.long _%d\n",label);
4304 #endif
4305 }
4306
4307 void
4308 code_table_close()
4309 {
4310 text_mode(0);
4311 }
4312
4313 #endif
4314
4315
4316 #if ASM_CODE
4317
4318 /*
4319 print an operand
4320 */
4321
4322 static void
4323 emit_asm_operand(int rstr)
4324 {
4325 if (car(rstr)==REGISTER) {
4326 printf("%s",register_name(cadr(rstr),0));
4327 } else if (car(rstr)==CONST) {
4328 printf("%d",cadr(rstr));
4329 } else if (car(rstr)==FNAME) {
4330 #ifdef __APPLE__
4331 printf("_%s-_%d",ncaddr(rstr)->nm,goffset_label);
4332 #else
4333 printf("%s",ncaddr(rstr)->nm);
4334 #endif
4335 } else if (car(rstr)==LABEL) {
4336 #ifdef __APPLE__
4337 printf("_%d-_%d",cadr(rstr),goffset_label);
4338 #else
4339 printf("_%d",cadr(rstr));
4340 #endif
4341 } else {
4342 error(-1);
4343 }
4344 }
4345
4346 /*
4347 prepare asm operands
4348
4349 char *constraints string
4350 int operand expr
4351 int mode (ASM_INPUT,ASM_OUTPUT)
4352 int replacement list
4353 int output operands count
4354 int output operands replacement list
4355
4356 retrun replacement list
4357 list3( operands, next, clobber )
4358 0 can be shared in input/output
4359 1 can't be used in input
4360 */
4361
4362 int
4363 code_asm_operand(char *p,int e1,int mode,int repl,int n,int repl0)
4364 {
4365 int r;
4366 int c;
4367 int val;
4368 int clobber = 0;
4369
4370 printf("## constraint %s\n",p);
4371 if (*p=='=') {
4372 // output register
4373 p++;
4374 }
4375 if (*p=='&') {
4376 // earlyclobber
4377 p++;
4378 clobber = 1;
4379 }
4380 c = *p;
4381 if (c=='r') {
4382 if (mode==ASM_INPUT) {
4383 for(;repl0;repl0 = cadr(repl0)) {
4384 if (car(car(repl0))==REGISTER && caddr(repl0)==0) {
4385 r = cadr(car(repl0));
4386 caddr(repl0) = ASM_USED;
4387 break;
4388 }
4389 }
4390 r = get_register();
4391 } else {
4392 r = get_register();
4393 }
4394 repl = list3(list2(REGISTER,r),repl,clobber);
4395 } else if (c=='m') {
4396 repl = list3(list2(0,0),repl,clobber);
4397 } else if (c=='i') {
4398 if (car(e1)==GVAR) {
4399 e1=list3n(FNAME,0,ncaddr(e1));
4400 } else if (car(e1)==FNAME) {
4401 e1=list3n(FNAME,0,ncaddr(e1));
4402 } else if (car(e1)==STRING) {
4403 val = emit_string_label();
4404 ascii(ncaddr(e1)->nm);
4405 e1=list2(LABEL,val);
4406 } else if (car(e1)==CONST) {
4407 } else error(-1);
4408 repl = list3(e1,repl,clobber);
4409 } else if (digit(c)) {
4410 val = 0;
4411 do { val = val*10 + c-'0'; } while (digit(c=*p++));
4412 if (val>MAX_ASM_REG) error(-1); // too large register
4413 if (n-val<0) error(-1);
4414 repl = list3(car(nth(n-val-1,repl0)),repl,clobber);
4415 } else error(-1);
4416 return repl;
4417 }
4418
4419 void
4420 code_free_asm_operand(int repl)
4421 {
4422 int reg;
4423 for(;repl;repl=cadr(repl)) {
4424 if (car(car(repl))==REGISTER) {
4425 reg = cadr(car(repl));
4426 if (regs[reg]!=REG_VAR) free_register(reg);
4427 }
4428 }
4429 }
4430
4431
4432 extern void
4433 code_asm(char *asm_str,int repl)
4434 {
4435 int c,i,rstr,val;
4436 char *p;
4437 int reg[MAX_ASM_REG];
4438
4439 text_mode(0);
4440 c = *asm_str;
4441 if (c!='\t'&&c!=' ') printf("\t");
4442 for(i=0;repl && i<MAX_ASM_REG;i++) {
4443 reg[i] = car(repl);
4444 repl = cadr(repl);
4445 }
4446 p = asm_str;
4447 while((c = *p++)) {
4448 if (c=='%') {
4449 c = *p++;
4450 if (!c) { break;
4451 } else if (c=='%') {
4452 printf("%%"); continue;
4453 } else if (!digit(c)) {
4454 printf("%%%c",c); continue;
4455 }
4456 val = 0;
4457 do { val = val*10 + c-'0'; } while (digit(c=*p++)) ;
4458 p--;
4459 if (val>MAX_ASM_REG) error(-1); // too large register
4460 rstr = reg[val];
4461 emit_asm_operand(rstr);
4462 } else {
4463 printf("%c",c);
4464 }
4465 }
4466 printf("\n");
4467 }
4468
4469 #endif
4470
4471
4472 #if BIT_FIELD_CODE
4473
4474 /* bit field alignment calcuration */
4475
4476 static void
4477 set_bitsz(int type,int *pbitpos, int *pbitsize,
4478 int *psign,int *pbitsz,int *palign,int *pl)
4479 {
4480 int sign=0,bitsz=1;
4481 int align=4,l=0;
4482 *pbitpos = cadr(caddr(type));
4483 *pbitsize = caddr(caddr(type));
4484
4485 switch(cadr(type)) {
4486 case INT: sign=1; bitsz=32; align=4;break;
4487 case UNSIGNED: bitsz=32; align=4;break;
4488 case CHAR: sign=1; bitsz= 8; align=1;break;
4489 case UCHAR: bitsz= 8; align=1;break;
4490 case SHORT: sign=1; bitsz=16; align=2;break;
4491 case USHORT: sign=1; bitsz=16; align=2;break;
4492 case LONGLONG: sign=1; bitsz=64; align=4;l=1; break;
4493 case ULONGLONG: bitsz=64; align=4;l=1; break;
4494 default: error(-1);
4495 }
4496 *psign = sign;
4497 *pbitsz = bitsz;
4498 *palign = align;
4499 *pl = l;
4500 }
4501
4502 /*
4503 bit field alignment calcuration
4504 this is architecture depenedent
4505 */
4506
4507 extern int
4508 code_bit_field_disp(int type,int *poffset,int *bfd,int *sz)
4509 {
4510 int sign,bitsz,align;
4511 int i;
4512 int bitpos = *bfd;
4513 int bitpos0;
4514 int bitsize;
4515 int offset = *poffset;
4516 int l;
4517 set_bitsz(type,&bitpos0,&bitsize,&sign,&bitsz,&align,&l);
4518
4519 if (bitsize>bitsz) { error(BTERR); bitsize = bitsz; }
4520
4521 /* bfd means previous bit field bit offset */
4522 if (bitpos) {
4523 /* previous field is bit field and spaces may remain */
4524 /* calc previsous offset */
4525
4526 i= offset-(bitpos+7)/8;
4527
4528 for(l = bitpos;l>0;l -= 8,i++) {
4529 if ((i & (align-1))==0 && l+bitsize <= bitsz) {
4530 /* alignment is correct and space remains */
4531 *poffset=offset=i;
4532 i = l+bitsize;
4533 *bfd = (i==bitsz)?0:i;
4534 *sz = (i+7)/8;
4535 // printf("## bitpos=%d bitsize=%d bitsz=%d offset=%d\n",l,bitsize,bitsz,*poffset);
4536 return l;
4537 }
4538 }
4539 }
4540
4541 /* first bit-field */
4542
4543 if ((i=(offset & (align-1)))) {
4544 *poffset = (offset += (align-i));
4545 }
4546 bitpos = 0;
4547 *bfd = (bitsize==bitsz)?0:bitsize;
4548 *sz = (bitsize+7)/8;
4549
4550 // printf("## bitpos=%d bitsize=%d bitsz=%d offset=%d\n",bitpos,bitsize,bitsz,*poffset);
4551 return bitpos;
4552 }
4553
4554 /* bit field value */
4555
4556 extern void
4557 code_bit_field(int type,int adr,int reg)
4558 {
4559 int sign,bitsz,l,align;
4560 int bitsize,bitpos;
4561 int i,size;
4562 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l);
4563 size=bitsz/8;
4564 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
4565 /* this implementation returns -1 for int i:1; */
4566 if (l==1) {
4567 #if LONGLONG_CODE
4568 use_int(adr);
4569 use_longlong(reg);
4570 lload(adr,0,reg);
4571 /* shift left */
4572 if ((i=bitsz-bitsize-bitpos))
4573 loprtc(LLSHIFT,reg,list2(CONST,i));
4574 /* shift right */
4575 if ((i=bitsz-bitsize))
4576 loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i));
4577 #endif
4578 } else {
4579 use_int(adr);
4580 use_int(reg);
4581 printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0),
4582 register_name(reg,0));
4583 /* shift left */
4584 if ((i=32-bitsize-bitpos))
4585 oprtc(LSHIFT,reg,list2(CONST,i));
4586 /* shift right */
4587 if ((i=32-bitsize))
4588 oprtc(sign?RSHIFT:URSHIFT,reg,list2(CONST,i));
4589 }
4590 }
4591
4592 /* bit field replacement */
4593
4594 static void
4595 make_mask_and_or(int mask,int reg,int lreg)
4596 {
4597 printf("## mask 0x%08x ~0x%08x\n",mask,~mask);
4598 printf("\tpushl %s\n",register_name(reg,0));
4599 /* make and-mask */
4600 oprtc(BOR,reg,list2(CONST,~mask));
4601 /* do conjunction */
4602 if (lreg==-1) {
4603 printf("\tandl %s,4(%%esp)\n",register_name(reg,0));
4604 } else if (lreg==-2) {
4605 printf("\tandl %s,8(%%esp)\n",register_name(reg,0));
4606 } else {
4607 printf("\tandl %s,%s\n",register_name(reg,0),register_name(lreg,0));
4608 }
4609 /* make or-mask */
4610 printf("\tpopl %s\n",register_name(reg,0));
4611 oprtc(BAND,reg,list2(CONST,mask));
4612 /* do disjunction */
4613 if (lreg==-1) {
4614 printf("\torl %s,0(%%esp)\n",register_name(reg,0));
4615 } else if (lreg==-2) {
4616 printf("\torl %s,4(%%esp)\n",register_name(reg,0));
4617 } else {
4618 printf("\torl %s,%s\n",register_name(reg,0),register_name(lreg,0));
4619 printf("\txchg %s,%s\n",register_name(reg,0),register_name(lreg,0));
4620 }
4621 }
4622
4623 extern void
4624 code_bit_replace(int adr,int value,int type)
4625 {
4626 int sign,bitsz,l,align;
4627 int bitsize,bitpos;
4628 int mask = 0;
4629 int size;
4630 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l);
4631 size = bitsz/8;
4632 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
4633 if (l) {
4634 #if LONGLONG_CODE
4635 int push=0;
4636 use_int(adr);
4637 use_longlong(value);
4638 /* shift left */
4639 if (bitpos)
4640 loprtc(LLSHIFT,value,list2(CONST,bitpos));
4641 if (bitpos+bitsize>=32) {
4642 /* make and-mask upper */
4643 printf("\tpushl %s\n",register_name(adr,0)); push=1;
4644 printf("\t%s %d(%s),%s\n",cload(sign,size),4,register_name(adr,0),
4645 register_name(adr,0));
4646 mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31);
4647 make_mask_and_or(mask,regv_h(value),adr);
4648 printf("\tmovl 0(%%esp),%s\n",register_name(adr,0));
4649 printf("\t%s %s,4(%s)\n",move(0),
4650 l_edx(value), register_name(adr,0));
4651 }
4652 if (bitpos<32) {
4653 if (!push) { printf("\tpushl %s\n",register_name(adr,0)); push=1;}
4654 /* make and-mask lower */
4655 printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0),
4656 register_name(adr,0));
4657 mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos);
4658 make_mask_and_or(mask,regv_l(value),adr);
4659 printf("\tpopl %s\n",register_name(adr,0)); push=0;
4660 printf("\t%s %s,(%s)\n",move(0),
4661 l_eax(value), register_name(adr,0));
4662 }
4663 if (push) printf("\taddl %%sp,$4\n");
4664 #endif
4665 } else {
4666 use_int(adr);
4667 use_int(value);
4668 printf("\tpushl %s\n",register_name(adr,0));
4669 printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0),
4670 register_name(adr,0));
4671 /* shift left */
4672 if (bitpos)
4673 oprtc(LSHIFT,value,list2(CONST,bitpos));
4674 /* make and-mask */
4675 mask = make_mask(32-bitpos-bitsize,31-bitpos);
4676 make_mask_and_or(mask,value,adr);
4677 printf("\tpopl %s\n",register_name(adr,0));
4678 code_assign(adr,size==4?0:size,value);
4679 }
4680 if (use) {
4681 code_bit_field(type,adr,USE_CREG);
4682 }
4683 }
4684
4685
4686 static void
4687 make_mask_and_or_const(int mask,int reg,int c)
4688 {
4689 int a;
4690 // printf("## mask 0x%08x ~0x%08x\n",mask,~mask);
4691 a = ~mask|c;
4692 if (a!=-1) {
4693 /* do conjunction */
4694 if (reg<MAX_DATA_REG && ((a& ~0xffff)==~0xffff)) {
4695 if ((a& ~0xff)==~0xff)
4696 printf("\tandb $%d,%s\n",a&0xff,register_name(reg,1));
4697 else
4698 printf("\tandw $%d,%s\n",a&0xffff,register_name(reg,2));
4699 } else
4700 printf("\tandl $%d,%s\n",a,register_name(reg,0));
4701 }
4702 /* make or-mask */
4703 c = mask&c;
4704 if (c!=0) {
4705 /* do disjunction */
4706 if (reg<MAX_DATA_REG && (!(c& ~0xffff))) {
4707 if (!(c& ~0xff))
4708 printf("\torb $%d,%s\n",c&0xff,register_name(reg,1));
4709 else
4710 printf("\torw $%d,%s\n",c&0xffff,register_name(reg,2));
4711 } else
4712 printf("\torl $%d,%s\n",c,register_name(reg,0));
4713 }
4714 }
4715
4716 extern void
4717 code_bit_replace_const(int value,int adr,int type)
4718 {
4719 int sign,bitsz,l,align;
4720 int bitpos,bitsize,size;
4721 int mask = 0;
4722 int c,lvalue;
4723 #if LONGLONG_CODE
4724 long long lc;
4725 #endif
4726 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l);
4727 size = bitsz/8;
4728 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz);
4729 use_int(adr);
4730 if (l) {
4731 #if LONGLONG_CODE
4732 lvalue = get_register();
4733 /* shift left */
4734 lc = lcadr(value);
4735 lc <<= bitpos;
4736
4737 if (bitpos+bitsize>=32) {
4738 printf("\t%s %d(%s),%s\n",cload(sign,size),4,register_name(adr,0),
4739 register_name(lvalue,0));
4740 /* make and-mask upper */
4741 mask = make_mask(64-bitpos-bitsize,bitpos>=32?63-bitpos:31);
4742 make_mask_and_or_const(mask,lvalue,(int)(lc>>32));
4743 printf("\t%s %s,4(%s)\n",move(0),register_name(lvalue,0),
4744 register_name(adr,0));
4745 }
4746 if (bitpos<32) {
4747 printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0),
4748 register_name(lvalue,0));
4749 /* make and-mask lower */
4750 mask = make_mask(bitpos+bitsize>=32?0:32-bitpos-bitsize,31-bitpos);
4751 make_mask_and_or_const(mask,lvalue,(int)(lc));
4752 printf("\t%s %s,(%s)\n",move(0),
4753 register_name(lvalue,0),register_name(adr,0));
4754 }
4755 free_register(lvalue);
4756 #endif
4757 } else {
4758 lvalue = get_register();
4759 printf("\t%s %d(%s),%s\n",cload(sign,size),0,register_name(adr,0),
4760 register_name(lvalue,0));
4761 /* shift left */
4762 c = cadr(value);
4763 c <<= bitpos;
4764 /* make and-mask */
4765 mask = make_mask(32-bitpos-bitsize,31-bitpos);
4766 make_mask_and_or_const(mask,lvalue,c);
4767 code_assign(adr,size==4?0:size,lvalue);
4768 free_register(lvalue);
4769 }
4770 if (use)
4771 code_bit_field(type,adr,USE_CREG);
4772 }
4773
4774 #endif
4775
4776 int
4777 not_simple_p(int e3)
4778 {
4779 switch(e3) {
4780 case FUNCTION: case CONV: case STASS: case ALLOCA:
4781 case LDIV: case LUDIV: case LMOD: case LUMOD:
4782 case LMUL: case LUMUL:
4783 case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT:
4784 case DDIV: case DADD: case DSUB: case DMUL: case DMINUS:
4785 case DPOSTINC : case DPREINC : case DASSOP :
4786 case DOP+LT : case DOP+LE : case DOP+GT : case DOP+GE :
4787 case DOP+EQ : case DOP+NEQ:
4788 case RBIT_FIELD: case BASS: case BASSOP: case LCALL:
4789 case INLINE:
4790 return 1;
4791 }
4792 return 0;
4793 }
4794
4795 extern int
4796 code_arg_alignment(int args,NMTBL *n, int type0,int sz)
4797 {
4798 return code_arg_alignment0(args,n, type0,sz);
4799 }
4800
4801
4802 extern int
4803 code_lvar_alignment(int args,NMTBL *n, int type0,int sz)
4804 {
4805 return code_lvar_alignment0(args,n, type0,sz);
4806 }
4807
4808
4809 /* end */