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