Mercurial > hg > CbC > old > device
annotate mc-code-powerpc.c @ 794:032dc03be02e
i64 arg_register in inline mode
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 23 Nov 2010 09:42:08 +0900 (2010-11-23) |
parents | 3bc6c34bfa2e |
children | a5f9e5a4db1b |
rev | line source |
---|---|
326 | 1 /* Micro-C Code Generation Part for Power PC (Mac OS X) */ |
607 | 2 |
3 /* | |
4 ************************************************************************ | |
5 ** Copyright (C) 2006 Shinji Kono | |
724 | 6 ** 連絡先: 琉球大学情報工学科 河野 真治 |
7 ** (E-Mail Address: kono@ie.u-ryukyu.ac.jp) | |
607 | 8 ** |
724 | 9 ** このソースのいかなる複写,改変,修正も許諾します。ただし、 |
10 ** その際には、誰が貢献したを示すこの部分を残すこと。 | |
11 ** 再配布や雑誌の付録などの問い合わせも必要ありません。 | |
12 ** 営利利用も上記に反しない範囲で許可します。 | |
13 ** バイナリの配布の際にはversion messageを保存することを条件とします。 | |
14 ** このプログラムについては特に何の保証もしない、悪しからず。 | |
607 | 15 ** |
16 ** Everyone is permitted to do anything on this program | |
17 ** including copying, modifying, improving, | |
18 ** as long as you don't try to pretend that you wrote it. | |
19 ** i.e., the above copyright notice has to appear in all copies. | |
20 ** Binary distribution requires original version messages. | |
21 ** You don't have to ask before copying, redistribution or publishing. | |
22 ** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. | |
23 *********************************************************************** | |
24 */ | |
89 | 25 |
327 | 26 #include <stdio.h> |
89 | 27 #include "mc.h" |
327 | 28 #include "mc-parse.h" |
93 | 29 #include "mc-code.h" |
89 | 30 #include "mc-codegen.h" |
31 | |
615 | 32 #include "mc-include.c" |
324 | 33 |
664 | 34 // #undef __APPLE__ |
662 | 35 |
327 | 36 static |
667 | 37 char *init_src0 = |
38 #ifdef __APPLE__ | |
39 "\ | |
313 | 40 #define __ppc__ 1\n\ |
41 #define __BIG_ENDIAN__ 1\n\ | |
42 #define __STDC__ 1\n\ | |
469 | 43 #define __GNUC__ 1\n\ |
526 | 44 #define __inline inline\n\ |
45 #define __inline__ inline\n\ | |
313 | 46 #define __builtin_va_list int\n\ |
47 #define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\ | |
48 #define __builtin_va_arg(ap,type) (*((type *)ap)++)\n\ | |
49 #define alloca __builtin_alloca\n\ | |
616 | 50 #define __FLT_MIN__ 1.17549435e-38F\n\ |
51 #define __DBL_MIN__ 2.2250738585072014e-308\n\ | |
52 #define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L\n\ | |
636 | 53 " |
667 | 54 #else |
55 "\ | |
56 #define __inline inline\n\ | |
57 #define __extension__\n\ | |
58 #define __const const\n\ | |
59 #define __inline__ inline\n\ | |
676 | 60 #define __builtin_va_list int\n\ |
61 #define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\ | |
62 #define __builtin_va_arg(ap,type) (*((type *)ap)++)\n\ | |
63 // #define __builtin_va_arg(ap,type) (*((type *)__builtin_va_next((type),&ap)))\n\ | |
667 | 64 #define alloca __builtin_alloca\n\ |
65 #define __DBL_MIN_EXP__ (-1021)\n\ | |
66 #define __FLT_MIN__ 1.17549435e-38F\n\ | |
67 #define __CHAR_BIT__ 8\n\ | |
68 #define __WCHAR_MAX__ 2147483647\n\ | |
69 #define __DBL_DENORM_MIN__ 4.9406564584124654e-324\n\ | |
70 #define __FLT_EVAL_METHOD__ 0\n\ | |
71 #define __DBL_MIN_10_EXP__ (-307)\n\ | |
72 #define __FINITE_MATH_ONLY__ 0\n\ | |
73 #define __GNUC_PATCHLEVEL__ 0\n\ | |
74 #define __SHRT_MAX__ 32767\n\ | |
75 #define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L\n\ | |
76 #define __UINTMAX_TYPE__ long long unsigned int\n\ | |
77 #define __linux 1\n\ | |
78 #define __CHAR_UNSIGNED__ 1\n\ | |
79 #define __LDBL_MAX_EXP__ 1024\n\ | |
80 #define __linux__ 1\n\ | |
81 #define __SCHAR_MAX__ 127\n\ | |
82 #define __USER_LABEL_PREFIX__ \n\ | |
83 #define __STDC_HOSTED__ 1\n\ | |
84 #define __LDBL_HAS_INFINITY__ 1\n\ | |
85 #define __DBL_DIG__ 15\n\ | |
86 #define __FLT_EPSILON__ 1.19209290e-7F\n\ | |
87 #define _CALL_SYSV 1\n\ | |
88 #define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L\n\ | |
89 #define __unix__ 1\n\ | |
90 #define __DECIMAL_DIG__ 33\n\ | |
91 #define __gnu_linux__ 1\n\ | |
92 #define __LDBL_HAS_QUIET_NAN__ 1\n\ | |
93 #define __GNUC__ 4\n\ | |
94 #define __DBL_MAX__ 1.7976931348623157e+308\n\ | |
95 #define __DBL_HAS_INFINITY__ 1\n\ | |
96 #define __DBL_MAX_EXP__ 1024\n\ | |
97 #define __LONG_LONG_MAX__ 9223372036854775807LL\n\ | |
98 #define __PPC__ 1\n\ | |
99 #define __GXX_ABI_VERSION 1002\n\ | |
100 #define __FLT_MIN_EXP__ (-125)\n\ | |
101 #define __DBL_MIN__ 2.2250738585072014e-308\n\ | |
102 #define __DBL_HAS_QUIET_NAN__ 1\n\ | |
103 #define __REGISTER_PREFIX__ \n\ | |
104 #define __NO_INLINE__ 1\n\ | |
105 #define _ARCH_PPC 1\n\ | |
106 #define __FLT_MANT_DIG__ 24\n\ | |
107 #define __VERSION__ \"mc-powerpc\"\n\ | |
108 #define __BIG_ENDIAN__ 1\n\ | |
109 #define __powerpc__ 1\n\ | |
110 #define unix 1\n\ | |
111 #define __SIZE_TYPE__ unsigned int\n\ | |
112 #define __ELF__ 1\n\ | |
113 #define __FLT_RADIX__ 2\n\ | |
114 #define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L\n\ | |
115 #define __GNUC_RH_RELEASE__ 3\n\ | |
116 #define __LDBL_DIG__ 31\n\ | |
117 #define __FLT_HAS_QUIET_NAN__ 1\n\ | |
118 #define __FLT_MAX_10_EXP__ 38\n\ | |
119 #define __LONG_MAX__ 2147483647L\n\ | |
120 #define __FLT_HAS_INFINITY__ 1\n\ | |
121 #define __unix 1\n\ | |
122 #define _BIG_ENDIAN 1\n\ | |
123 #define linux 1\n\ | |
124 #define __PPC 1\n\ | |
125 #define __LDBL_MANT_DIG__ 106\n\ | |
126 #define __WCHAR_TYPE__ long int\n\ | |
127 #define __FLT_DIG__ 6\n\ | |
128 #define __powerpc 1\n\ | |
129 #define __INT_MAX__ 2147483647\n\ | |
130 #define __LONG_DOUBLE_128__ 1\n\ | |
131 #define __FLT_MAX_EXP__ 128\n\ | |
132 #define __DBL_MANT_DIG__ 53\n\ | |
133 #define __WINT_TYPE__ unsigned int\n\ | |
134 #define __LDBL_MIN_EXP__ (-968)\n\ | |
135 #define __LDBL_MAX_10_EXP__ 308\n\ | |
136 #define __DBL_EPSILON__ 2.2204460492503131e-16\n\ | |
137 #define PPC 1\n\ | |
138 #define powerpc 1\n\ | |
139 #define __INTMAX_MAX__ 9223372036854775807LL\n\ | |
140 #define __FLT_DENORM_MIN__ 1.40129846e-45F\n\ | |
141 #define __FLT_MAX__ 3.40282347e+38F\n\ | |
142 #define __FLT_MIN_10_EXP__ (-37)\n\ | |
143 #define __INTMAX_TYPE__ long long int\n\ | |
144 #define __GNUC_MINOR__ 1\n\ | |
145 #define __DBL_MAX_10_EXP__ 308\n\ | |
146 #define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L\n\ | |
147 #define __STDC__ 1\n\ | |
148 #define __PTRDIFF_TYPE__ int\n\ | |
149 #define __LDBL_MIN_10_EXP__ (-291)\n\ | |
150 " | |
151 #endif | |
636 | 152 #ifdef __APPLE__ |
153 "#define __APPLE__ 1\n" | |
154 #endif | |
155 ; | |
313 | 156 |
89 | 157 #define TEXT_EMIT_MODE 0 |
158 #define DATA_EMIT_MODE 1 | |
159 #define RODATA_EMIT_MODE 2 | |
160 | |
221 | 161 static void ld_indexx(int byte, int n, int xreg,int reg,int sign); |
93 | 162 static void local_table(void); |
221 | 163 static void shift(char *op, int creg,int reg); |
444 | 164 static int push_struct(int e4,int t,int arg); |
518 | 165 static void ascii(char *s); |
166 | |
662 | 167 #ifdef __APPLE__ |
168 static char lpfx[] = "L_"; | |
169 static char npfx[] = "_"; | |
170 #else | |
171 static char lpfx[] = ".LC"; | |
172 static char npfx[] = ""; | |
173 #endif | |
93 | 174 |
555 | 175 int eval_order = NORMAL; |
341 | 176 |
221 | 177 static int creg; |
178 | |
89 | 179 static int output_mode = TEXT_EMIT_MODE; |
340 | 180 int data_alignment = 0; |
89 | 181 |
182 static int code_disp_label; | |
111 | 183 static int code_setup; |
116 | 184 static int r1_offset_label; |
185 static int lvar_offset_label; | |
313 | 186 static int max_func_arg_label; |
672 | 187 #ifndef __APPLE__ |
188 static int arg_offset_label; | |
189 #endif | |
676 | 190 static int arg_offset_v = 0; |
116 | 191 |
192 static int reg_save; | |
193 static int freg_save; | |
194 | |
205 | 195 static int freg,ireg,lreg; |
147 | 196 |
238 | 197 int code_lassop_p = 1; |
198 | |
245 | 199 #define SIZE_OF_INT 4 |
200 #define SIZE_OF_SHORT 2 | |
201 #define SIZE_OF_FLOAT 4 | |
202 #define SIZE_OF_DOUBLE 8 | |
203 #define SIZE_OF_LONGLONG 8 | |
204 #define ENDIAN 1 | |
411 | 205 #define ENDIAN_L 1 |
206 #define ENDIAN_D 1 | |
245 | 207 |
205 | 208 static int reg_sp; /* REGister Stack-Pointer */ |
724 | 209 static int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ |
138 | 210 |
211 /* floating point registers */ | |
212 | |
205 | 213 static int freg_sp; /* floating point REGister Stack-Pointer */ |
724 | 214 static int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ |
89 | 215 |
206 | 216 static int lreg_sp; /* longlong REGister Stack-Pointer */ |
724 | 217 static int lreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ |
206 | 218 |
667 | 219 #ifdef __APPLE__ |
577 | 220 #define REG_sp 1 |
221 #define REG_fp 30 | |
119 | 222 #define REG_VAR_BASE 29 |
130 | 223 #define REG_VAR_MIN 18 |
119 | 224 #define MIN_TMP_REG 3 |
130 | 225 #define MAX_TMP_REG 11 |
119 | 226 |
227 #define FREG_VAR_BASE 31 | |
130 | 228 #define FREG_VAR_MIN 20 |
119 | 229 #define MIN_TMP_FREG 1 |
130 | 230 #define MAX_TMP_FREG 14 |
667 | 231 #else |
232 #define REG_sp 1 | |
233 #define REG_fp 31 | |
234 #define REG_VAR_BASE 29 | |
235 #define REG_VAR_MIN 18 | |
236 #define MIN_TMP_REG 3 | |
237 #define MAX_TMP_REG 11 | |
238 | |
239 #define FREG_VAR_BASE 31 | |
240 #define FREG_VAR_MIN 20 | |
241 #define MIN_TMP_FREG 1 | |
242 #define MAX_TMP_FREG 9 | |
243 #endif | |
119 | 244 |
724 | 245 int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ |
122 | 246 int MAX_FREGISTER=31; |
724 | 247 #define REAL_MAX_REGISTER 32 /* PowerPCのレジスタが32ということ*/ |
248 #define REAL_MAX_FREGISTER 32 /* PowerPCのレジスタが32ということ*/ | |
207 | 249 #define REAL_MAX_LREGISTER 16 |
119 | 250 |
145 | 251 #define FREG_OFFSET REAL_MAX_REGISTER |
207 | 252 #define LREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER) |
253 | |
254 #define RET_REGISTER 3 | |
255 #define RET_FREGISTER (1+FREG_OFFSET) | |
222 | 256 #define RET_LREGISTER_H 3 /* high word */ |
207 | 257 #define RET_LREGISTER_L 4 /* low word */ |
258 #define RET_LREGISTER LREG_OFFSET | |
145 | 259 |
122 | 260 int MAX_INPUT_REGISTER_VAR = 11-MIN_TMP_REG; |
261 int MAX_CODE_INPUT_REGISTER_VAR = 11-MIN_TMP_REG; | |
667 | 262 int MAX_INPUT_DREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG; |
263 int MAX_INPUT_FREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG; | |
264 int MAX_CODE_INPUT_DREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG; | |
265 int MAX_CODE_INPUT_FREGISTER_VAR = MAX_TMP_FREG-MIN_TMP_FREG; | |
119 | 266 |
207 | 267 static int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ |
268 REAL_MAX_LREGISTER]; | |
269 static int regv_h0[REAL_MAX_LREGISTER]; | |
270 static int regv_l0[REAL_MAX_LREGISTER]; | |
211 | 271 #define regv_h(i) regv_h0[(i)-LREG_OFFSET] |
272 #define regv_l(i) regv_l0[(i)-LREG_OFFSET] | |
205 | 273 |
274 static int *regs = powerpc_regs; | |
119 | 275 |
207 | 276 #define CREG_REGISTER (MAX_TMP_REG) |
277 #define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET) | |
278 #define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET) | |
206 | 279 |
280 | |
119 | 281 static int max_reg_var, max_freg_var; |
282 | |
660 | 283 #ifdef __APPLE__ |
119 | 284 static char *reg_name[] = { |
285 "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9", | |
286 "r10","r11","r12","r13","r14","r15","r16","r17","r18","r19", | |
287 "r20","r21","r22","r23","r24","r25","r26","r27","r28","r29", | |
145 | 288 "r30","r31", |
119 | 289 "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9", |
290 "f10","f11","f12","f13","f14","f15","f16","f17","f18","f19", | |
291 "f20","f21","f22","f23","f24","f25","f26","f27","f28","f29", | |
292 "f30","f31" | |
293 }; | |
660 | 294 #else |
295 // PS3 (PowerPC Fedora Core) | |
296 static char *reg_name[] = { | |
297 "0","1","2","3","4","5","6","7","8","9", | |
298 "10","11","12","13","14","15","16","17","18","19", | |
299 "20","21","22","23","24","25","26","27","28","29", | |
300 "30","31", | |
301 "0","1","2","3","4","5","6","7","8","9", | |
302 "10","11","12","13","14","15","16","17","18","19", | |
303 "20","21","22","23","24","25","26","27","28","29", | |
304 "30","31" | |
305 }; | |
306 #endif | |
119 | 307 |
716 | 308 #define round4(i) align(i,4) |
309 #define round16(i) align(i,16) | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
310 |
207 | 311 #define register_name(i) reg_name[i] |
312 #define fregister_name(i) reg_name[i] | |
313 #define lregister_name_low(i) reg_name[regv_l(i)] | |
210 | 314 #define lregister_name_high(i) reg_name[regv_h(i)] |
207 | 315 |
431 | 316 #define DEBUG_REG 1 |
317 #if DEBUG_REG | |
467 | 318 char *rn(int i) { return register_name(i); } |
319 char *fn(int i) { return fregister_name(i); } | |
320 char *lln(int i) { return lregister_name_low(i); } | |
321 char *lhn(int i) { return lregister_name_high(i); } | |
322 int ll(int i) { return regv_l(i); } | |
323 int lh(int i) { return regv_h(i); } | |
431 | 324 #endif |
221 | 325 |
207 | 326 #define is_int_reg(i) (0<=i&&i<REAL_MAX_REGISTER) |
327 #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) | |
328 #define is_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER) | |
147 | 329 |
221 | 330 #define use_int(reg) if (reg==USE_CREG) reg=use_int0() |
331 static | |
332 int use_int0() { | |
333 int i = creg; | |
233 | 334 if (!i||!ireg||!is_int_reg(i)) { |
590 | 335 if (lreg) { if (regs[lreg]!=REG_VAR) free_register(lreg); lreg = 0; } |
205 | 336 if (!ireg) ireg = get_register(); |
222 | 337 // else if (ireg!=i) free_register(i); |
206 | 338 i = ireg; |
205 | 339 } |
207 | 340 if (!regs[i]) regs[i]=USING_REG; |
221 | 341 creg = i; |
147 | 342 return i; |
343 } | |
344 | |
222 | 345 #if LONGLONG_CODE |
346 #define use_longlong(reg) if (reg==USE_CREG) reg=use_longlong0() | |
347 | |
348 static | |
349 int use_longlong0() { | |
350 int i = creg; | |
351 if (!is_longlong_reg(i)) { | |
590 | 352 if (ireg) { if (regs[ireg]!=REG_VAR) free_register(ireg); ireg=0; } |
226 | 353 if (!lreg||!regs[lreg]) lreg = get_lregister(); |
222 | 354 // else if (lreg!=i) free_register(i); |
355 i = lreg; | |
356 } | |
357 if (!regv_l(i)) regv_l(i) = get_register(); | |
358 if (!regv_h(i)) regv_h(i) = get_register(); | |
359 if (!regs[i]) regs[i]=USING_REG; | |
360 if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG; | |
361 if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG; | |
362 creg = i; | |
363 return i; | |
364 } | |
365 #endif | |
366 | |
367 | |
221 | 368 #if FLOAT_CODE |
369 #define use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0() | |
370 static | |
371 int use_float0() { | |
372 int i = creg; | |
207 | 373 if (!is_float_reg(i)) { |
590 | 374 if (lreg) { if (regs[lreg]!=REG_VAR) free_register(lreg); lreg = 0; } |
207 | 375 if (!freg) freg = get_dregister(0); |
590 | 376 else if (freg!=i) if (regs[i]!=REG_VAR) free_register(i); |
207 | 377 i = freg; |
378 } | |
379 if (!regs[i]) regs[i]=USING_REG; | |
221 | 380 creg = i; |
147 | 381 return i; |
382 } | |
221 | 383 static |
384 int use_double0() { | |
385 int i = creg; | |
207 | 386 if (!is_float_reg(i)) { |
590 | 387 if (lreg) { if (regs[lreg]!=REG_VAR) free_register(lreg); lreg = 0; } |
207 | 388 if (!freg) freg = get_dregister(1); |
590 | 389 else if (freg!=i) if (regs[i]!=REG_VAR) free_register(i); |
207 | 390 i = freg; |
391 } | |
392 if (!regs[i]) regs[i]=USING_REG; | |
221 | 393 creg = i; |
147 | 394 return i; |
395 } | |
221 | 396 #endif |
397 | |
195 | 398 |
399 #if FLOAT_CODE | |
663 | 400 #ifdef __APPLE__ |
119 | 401 static |
348 | 402 NMTBL float_zero = {"_float_zero",0,STATIC,FLOAT,0}; |
119 | 403 static |
348 | 404 NMTBL float_one = {"_float_one",0,STATIC,FLOAT,0}; |
663 | 405 #else |
406 static | |
407 NMTBL float_zero = {"__float_zero",0,STATIC,FLOAT,0}; | |
408 static | |
409 NMTBL float_one = {"__float_one",0,STATIC,FLOAT,0}; | |
410 #endif | |
119 | 411 |
412 | |
413 static char * fload(int d); | |
414 static int code_d1(double d); | |
415 static int code_d2(double d); | |
195 | 416 #endif |
206 | 417 #if LONGLONG_CODE |
418 static int code_l1(long long ll); | |
419 static int code_l2(long long ll); | |
420 #endif | |
195 | 421 |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
422 static void code_save_input_registers(int dots); |
207 | 423 static void set_ireg(int,int); |
119 | 424 static void set_freg(int,int); |
195 | 425 static void set_lreg(int,int); |
287 | 426 static void jcond(int l, char cond); |
431 | 427 static void register_usage(char *s); |
428 | |
119 | 429 |
153 | 430 static int max_func_args; |
431 static int my_func_args; | |
119 | 432 #define ARG_LVAR_OFFSET 0x10000000 |
433 | |
126 | 434 /* |
89 | 435 |
97 | 436 r0 return value etc. |
437 r3-r10 input register | |
326 | 438 r22-r29 saved register variable (input register for code segment) |
89 | 439 r30 stack pointer |
440 r31 0 | |
441 r1 frame pointer | |
97 | 442 |
443 f0 return value etc. | |
444 f1-r8 input register | |
445 f24-f31 saved register variable | |
116 | 446 |
672 | 447 function call stack frame (Mac OS X) |
375 | 448 <-------r1_offset------------------------------> |
672 | 449 r30 |
375 | 450 <------------lvar_offset0------> |
672 | 451 <--lvar_offset--> r1 |
116 | 452 r+ +------------+---+---------------+----------+--------------+----+ - |
122 | 453 callee arg xx register save local caller arg xx |
245 | 454 reg_save disp max_func_args*SIZE_OF_INT |
119 | 455 lvar>0 lvar<0 lvar>0x1000 0000 |
127 | 456 |
672 | 457 function call stack frame (PS3) |
676 | 458 <---------------r1_offset------------------------------> |
459 r30--> | |
460 <--arg_offset--> | |
461 xxx<----------lvar_offset--> <----r1 | |
462 r+ +------+---+------+---------------+----------+--------------+----+ - | |
672 | 463 callee arg reg arg register save local caller arg xx |
464 reg_save disp max_func_args*SIZE_OF_INT | |
465 lvar>0 lvar<0 lvar>0x1000 0000 | |
466 | |
467 | |
127 | 468 code segment stack frame |
469 | |
724 | 470 * gotoを呼び出した関数のr1 ! r1(goto前のr1) |
128 | 471 # * r30 <---r1_offset---------> r1 |
127 | 472 r+ +----------+--+----------+----------------+-----------+----------+----+ |
473 cousin arg xx reg save !callee arg !code local caller arg xx | |
474 r20-r29 lvar>0 lvar<0 lvar>0x1000 000 | |
475 f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> | |
245 | 476 *SIZE_OF_INT *SIZE_OF_INT |
127 | 477 |
89 | 478 */ |
667 | 479 |
480 | |
481 #ifdef __APPLE__ | |
482 | |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
483 #define arg_offset 24 |
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
484 #define arg_offset1 24 |
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
485 |
230 | 486 #define func_disp_offset 68 |
672 | 487 #define func_disp_offset1 16 |
649 | 488 #define code_disp_offset0 (0) |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
489 |
667 | 490 #else |
491 | |
672 | 492 #define arg_offset (8) |
676 | 493 #define arg_offset0 (8) |
672 | 494 #define arg_offset1 (8) |
495 | |
496 #define func_disp_offset (8) | |
667 | 497 #define code_disp_offset0 (0) |
498 | |
499 #endif | |
500 | |
501 int disp_offset = 0; | |
502 | |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
503 #define CODE_LVAR(l) ((l)+code_disp_offset0) |
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
504 #define CODE_CALLER_ARG(l) ((l)+arg_offset1) |
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
505 #define FUNC_LVAR(l) ((l)+disp_offset) |
676 | 506 #ifdef __APPLE__ |
672 | 507 #define CALLEE_ARG(l) ((l)+arg_offset) |
676 | 508 #else |
509 #define CALLEE_ARG(l) ((l)+arg_offset+((l>=arg_offset_v)?arg_offset0:0)) | |
510 #endif | |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
511 #define CALLER_ARG(l) ((l)+arg_offset1) |
89 | 512 |
647 | 513 |
116 | 514 void |
515 code_offset_set() | |
516 { | |
126 | 517 #if 0 |
121 | 518 int l; |
126 | 519 #endif |
647 | 520 int lvar_offsetv = |
672 | 521 round16(-disp+max_func_args*SIZE_OF_INT)+func_disp_offset; |
676 | 522 int r1_offsetv = round16(lvar_offsetv-reg_save); |
647 | 523 |
662 | 524 printf(".set %s%d,%d\n",lpfx,lvar_offset_label,r1_offsetv-lvar_offsetv); |
577 | 525 if (r1_offsetv-lvar_offsetv > 65000) error(-1); |
526 // too large function arguments? | |
662 | 527 printf(".set %s%d,%d\n",lpfx,r1_offset_label,r1_offsetv); |
313 | 528 if (max_func_arg_label) { |
662 | 529 printf(".set %s%d,%d\n",lpfx,max_func_arg_label, |
647 | 530 round16(max_func_args*SIZE_OF_INT)+24); |
313 | 531 max_func_arg_label = 0; |
532 } | |
533 | |
417 | 534 #if 0 |
468 | 535 printf("## reg_save %d\n",reg_save); |
536 printf("## function %s\n",fnptr->nm); | |
121 | 537 l = ARG_LVAR_OFFSET; |
468 | 538 printf("## offset call0\t%d\n",CALLER_ARG); |
245 | 539 l = ARG_LVAR_OFFSET+max_func_args*SIZE_OF_INT; |
468 | 540 printf("## offset calln\t%d %d\n",CALLER_ARG,max_func_args*SIZE_OF_INT); |
121 | 541 l = disp; |
468 | 542 printf("## offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp); |
121 | 543 l = 0; |
468 | 544 printf("## offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv); |
121 | 545 l = -reg_save; |
468 | 546 printf("## offset regs\t%d\n",FUNC_LVAR+lvar_offsetv); |
547 printf("## offset r1off\t%d\n",r1_offsetv); | |
121 | 548 l = 0; |
468 | 549 printf("## offset carg0\t%d\n",CALLEE_ARG+r1_offsetv); |
121 | 550 l = my_func_args; |
468 | 551 printf("## offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args); |
126 | 552 #endif |
116 | 553 } |
111 | 554 |
375 | 555 static int large_offset_reg; |
119 | 556 |
660 | 557 #ifdef __APPLE__ |
558 | |
119 | 559 static void |
375 | 560 lvar(int l) |
116 | 561 { |
375 | 562 char *rn; |
563 if (!large_offset_reg) { | |
544 | 564 if (is_code(fnptr)) { |
375 | 565 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
566 printf("lo16(%d)(r1)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); |
375 | 567 } else |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
568 printf("lo16(%d)(r30)\n",CODE_LVAR(l)); |
375 | 569 } else if (l<0) { /* local variable */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
570 printf("lo16(%d)(r30)\n",FUNC_LVAR(l)); |
375 | 571 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
572 printf("lo16(%d)(r1)\n",CALLER_ARG(l-ARG_LVAR_OFFSET)); |
375 | 573 } else { /* callee's arguments */ |
662 | 574 printf("lo16(%d+%s%d)(r30)\n",CALLEE_ARG(l),lpfx,lvar_offset_label); |
375 | 575 } |
576 } else { | |
577 rn = register_name(large_offset_reg); | |
544 | 578 if (is_code(fnptr)) { |
375 | 579 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
580 printf("lo16(%d)(%s)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET),rn); |
375 | 581 } else |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
582 printf("lo16(%d)(%s)\n",CODE_LVAR(l),rn); |
375 | 583 } else if (l<0) { /* local variable */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
584 printf("lo16(%d)(%s)\n",FUNC_LVAR(l),rn); |
375 | 585 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
586 printf("lo16(%d)(%s)\n",CALLER_ARG(l-ARG_LVAR_OFFSET),rn); |
375 | 587 } else { /* callee's arguments */ |
662 | 588 printf("lo16(%d+%s%d)(%s)\n",CALLEE_ARG(l),lpfx,lvar_offset_label,rn); |
375 | 589 } |
590 free_register(large_offset_reg); | |
116 | 591 } |
592 } | |
111 | 593 |
119 | 594 /* if size of local variables / input variables is more then 64k, |
595 lo16 does not work. We have to use ha16 also. But we can't know | |
596 the exact size in one path compile. We may safely use lvar16ha | |
326 | 597 if disp or max_func_args > 32k. Of course this is redundant for |
119 | 598 smaller offset. But who cares who use very large local variables? |
599 */ | |
96 | 600 |
375 | 601 #define LARGE_OFFSET(l) (l<-32000||l>32000) |
95 | 602 |
119 | 603 static void |
375 | 604 lvar_intro(int l) |
119 | 605 { |
375 | 606 char *rn; |
607 large_offset_reg=0; | |
544 | 608 if (is_code(fnptr)) { |
375 | 609 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
610 if (LARGE_OFFSET(CODE_CALLER_ARG(l-ARG_LVAR_OFFSET))) { |
375 | 611 rn=register_name(large_offset_reg=get_register()); |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
612 printf("\taddis %s,r1,ha16(%d)\n",rn, |
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
613 CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); |
375 | 614 } |
615 } else { | |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
616 if (LARGE_OFFSET(CODE_LVAR(l))) { |
375 | 617 rn=register_name(large_offset_reg=get_register()); |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
618 printf("\taddis %s,r30,ha16(%d)\n",rn,CODE_LVAR(l)); |
375 | 619 } |
620 } | |
119 | 621 } else if (l<0) { /* local variable */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
622 if (LARGE_OFFSET(FUNC_LVAR(l))) { |
375 | 623 rn=register_name(large_offset_reg=get_register()); |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
624 printf("\taddis %s,r30,ha16(%d)\n",rn,FUNC_LVAR(l)); |
375 | 625 } |
125 | 626 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
627 if (LARGE_OFFSET(CALLER_ARG(l-ARG_LVAR_OFFSET))) { |
375 | 628 rn=register_name(large_offset_reg=get_register()); |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
629 printf("\taddis %s,r1,ha16(%d)\n",rn,CALLER_ARG(l-ARG_LVAR_OFFSET)); |
375 | 630 } |
119 | 631 } else { /* callee's arguments */ |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
632 if (LARGE_OFFSET(CALLEE_ARG(l))) { |
375 | 633 rn=register_name(large_offset_reg=get_register()); |
662 | 634 printf("\taddis %s,r30,ha16(%d+%s%d)\n", |
635 rn,CALLEE_ARG(l),lpfx,lvar_offset_label); | |
375 | 636 } |
119 | 637 } |
638 } | |
89 | 639 |
660 | 640 #else /* PS3 */ |
641 | |
642 static void | |
643 lvar(int l) | |
644 { | |
645 char *rn; | |
646 if (!large_offset_reg) { | |
647 if (is_code(fnptr)) { | |
648 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
649 printf("%d@l(1)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); | |
650 } else | |
667 | 651 printf("%d@l(%d)\n",CODE_LVAR(l),REG_fp); |
660 | 652 } else if (l<0) { /* local variable */ |
667 | 653 printf("%d@l(%d)\n",FUNC_LVAR(l),REG_fp); |
660 | 654 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
655 printf("%d@l(1)\n",CALLER_ARG(l-ARG_LVAR_OFFSET)); | |
656 } else { /* callee's arguments */ | |
672 | 657 printf("%d+%s%d@l(%d)\n",CALLEE_ARG(l),lpfx,lvar_offset_label,REG_fp) ; |
660 | 658 } |
659 } else { | |
660 rn = register_name(large_offset_reg); | |
661 if (is_code(fnptr)) { | |
662 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
663 printf("%d@l(%s)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET),rn); | |
664 } else | |
665 printf("%d@l(%s)\n",CODE_LVAR(l),rn); | |
666 } else if (l<0) { /* local variable */ | |
667 printf("%d@l(%s)\n",FUNC_LVAR(l),rn); | |
668 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
669 printf("%d@l(%s)\n",CALLER_ARG(l-ARG_LVAR_OFFSET),rn); | |
670 } else { /* callee's arguments */ | |
662 | 671 printf("%d+%s%d@l(%s)\n",CALLEE_ARG(l),lpfx,lvar_offset_label,rn); |
660 | 672 } |
673 free_register(large_offset_reg); | |
674 } | |
675 } | |
676 | |
677 /* if size of local variables / input variables is more then 64k, | |
678 lo16 does not work. We have to use ha16 also. But we can't know | |
679 the exact size in one path compile. We may safely use lvar16ha | |
680 if disp or max_func_args > 32k. Of course this is redundant for | |
681 smaller offset. But who cares who use very large local variables? | |
682 */ | |
683 | |
684 #define LARGE_OFFSET(l) (l<-32000||l>32000) | |
685 | |
686 static void | |
687 lvar_intro(int l) | |
688 { | |
689 char *rn; | |
690 large_offset_reg=0; | |
691 if (is_code(fnptr)) { | |
692 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
693 if (LARGE_OFFSET(CODE_CALLER_ARG(l-ARG_LVAR_OFFSET))) { | |
694 rn=register_name(large_offset_reg=get_register()); | |
673 | 695 printf("\taddis %s,1,%d@ha\n",rn, |
660 | 696 CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); |
697 } | |
698 } else { | |
699 if (LARGE_OFFSET(CODE_LVAR(l))) { | |
700 rn=register_name(large_offset_reg=get_register()); | |
673 | 701 printf("\taddis %s,%d,%d@ha\n",rn,REG_fp,CODE_LVAR(l)); |
660 | 702 } |
703 } | |
704 } else if (l<0) { /* local variable */ | |
705 if (LARGE_OFFSET(FUNC_LVAR(l))) { | |
706 rn=register_name(large_offset_reg=get_register()); | |
673 | 707 printf("\taddis %s,%d,%d@ha\n",rn,REG_fp,FUNC_LVAR(l)); |
660 | 708 } |
709 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
710 if (LARGE_OFFSET(CALLER_ARG(l-ARG_LVAR_OFFSET))) { | |
711 rn=register_name(large_offset_reg=get_register()); | |
673 | 712 printf("\taddis %s,1,%d@ha\n",rn,CALLER_ARG(l-ARG_LVAR_OFFSET)); |
660 | 713 } |
714 } else { /* callee's arguments */ | |
715 if (LARGE_OFFSET(CALLEE_ARG(l))) { | |
716 rn=register_name(large_offset_reg=get_register()); | |
673 | 717 printf("\taddis %s,%d,%d+%s%d@ha\n", |
672 | 718 rn,REG_fp,CALLEE_ARG(l),lpfx,lvar_offset_label); |
660 | 719 } |
720 } | |
721 } | |
722 #endif | |
89 | 723 |
119 | 724 void |
221 | 725 code_lvar(int e2,int reg) { |
726 use_int(reg); | |
119 | 727 lvar_intro(e2); |
221 | 728 printf("\tla %s,",register_name(reg)); |
119 | 729 lvar(e2); |
730 } | |
95 | 731 |
89 | 732 void |
733 code_init(void) | |
734 { | |
327 | 735 /* called only once */ |
736 | |
737 init_src = init_src0; | |
738 size_of_int = SIZE_OF_INT; | |
715 | 739 size_of_pointer = SIZE_OF_INT; |
327 | 740 size_of_short = SIZE_OF_SHORT; |
741 size_of_float = SIZE_OF_FLOAT; | |
742 size_of_double = SIZE_OF_DOUBLE; | |
743 size_of_longlong = SIZE_OF_LONGLONG; | |
744 endian = ENDIAN; | |
717 | 745 struct_align = size_of_int; |
327 | 746 |
207 | 747 regv_l(RET_LREGISTER) = RET_LREGISTER_L; |
748 regv_h(RET_LREGISTER) = RET_LREGISTER_H; | |
89 | 749 } |
750 | |
327 | 751 extern void |
752 emit_reinit() | |
753 { | |
754 /* called for each file */ | |
328 | 755 /* heap is initialized here, setup ptr cache free list */ |
605 | 756 output_mode = -1; |
328 | 757 init_ptr_cache(); |
327 | 758 } |
759 | |
89 | 760 void |
761 gexpr_code_init(void){ | |
96 | 762 } |
763 | |
147 | 764 void |
765 code_gexpr(int e){ | |
590 | 766 if ((is_int_reg(creg))&®s[creg]==REG_VAR) |
767 creg = ireg = 0; | |
768 else if (is_float_reg(creg)&®s[creg]==REG_VAR) | |
769 creg = lreg = 0; | |
770 else if (is_longlong_reg(creg)&®s[creg]==REG_VAR) | |
771 creg = lreg = 0; | |
772 // if (is_int_reg(creg) && creg!=ireg) error(-1); | |
147 | 773 } |
774 | |
676 | 775 /* |
776 set variable storage type and offset | |
777 save register contents to our stack | |
778 for & operator | |
779 */ | |
89 | 780 |
109 | 781 void |
794
032dc03be02e
i64 arg_register in inline mode
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
784
diff
changeset
|
782 code_arg_register(NMTBL *fnptr, int in) |
109 | 783 { |
137 | 784 int args = fnptr->dsp; |
785 NMTBL *n; | |
786 int reg_var = 0; | |
787 int freg_var = 0; | |
788 int type; | |
789 int reg; | |
207 | 790 int i; |
137 | 791 int is_code0 = is_code(fnptr); |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
792 int dots; |
676 | 793 arg_offset_v = 0; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
794 |
794
032dc03be02e
i64 arg_register in inline mode
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
784
diff
changeset
|
795 if (in) return; |
032dc03be02e
i64 arg_register in inline mode
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
784
diff
changeset
|
796 |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
797 function_type(fnptr->ty,&dots); |
137 | 798 while (args) { |
799 /* process in reverse order */ | |
712 | 800 n = ncadddr(args); |
137 | 801 type = n->ty; |
802 if (scalar(type)) { | |
803 if ((reg = get_input_register_var(reg_var,n,is_code0))) { | |
804 n->sc = REGISTER; | |
207 | 805 n->dsp = cadr(reg); |
806 regs[n->dsp]= INPUT_REG; | |
137 | 807 reg_var++; |
712 | 808 arg_offset_v += (caddr(args)=SIZE_OF_INT); |
137 | 809 } |
138 | 810 } else if (type==FLOAT) { |
811 if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { | |
812 n->sc = DREGISTER; | |
207 | 813 n->dsp = cadr(reg); |
814 regs[n->dsp]= INPUT_REG; | |
138 | 815 freg_var++; |
712 | 816 arg_offset_v += (caddr(args)=size(type)); |
138 | 817 } |
818 } else if (type==DOUBLE) { | |
819 if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) { | |
137 | 820 n->sc = DREGISTER; |
207 | 821 n->dsp = cadr(reg); |
822 regs[n->dsp]= INPUT_REG; | |
137 | 823 freg_var++; |
712 | 824 arg_offset_v += (caddr(args)=size(type)); |
205 | 825 } |
826 } else if (type==LONGLONG||type==ULONGLONG) { | |
827 if ((reg = get_input_lregister_var(reg_var,n,is_code0))) { | |
828 n->sc = LREGISTER; | |
207 | 829 n->dsp = cadr(reg); |
830 regs[i=n->dsp]= INPUT_REG; | |
831 regs[regv_l(i)]= INPUT_REG; | |
832 regs[regv_h(i)]= INPUT_REG; | |
205 | 833 reg_var+=2; |
712 | 834 arg_offset_v += (caddr(args)=size(type)); |
137 | 835 } |
836 } | |
837 args = cadr(args); | |
838 } | |
672 | 839 if (is_function(fnptr)) { |
840 #ifndef __APPLE__ | |
673 | 841 if (dots) { |
842 arg_offset_v = | |
676 | 843 MAX_INPUT_REGISTER_VAR*SIZE_OF_INT + |
844 MAX_INPUT_DREGISTER_VAR*SIZE_OF_DOUBLE; | |
673 | 845 } |
676 | 846 printf(".set %s%d, %d\n",lpfx, arg_offset_label, |
847 arg_offset_v+ arg_offset); | |
672 | 848 #endif |
676 | 849 code_save_input_registers(dots); |
672 | 850 } |
109 | 851 } |
852 | |
208 | 853 |
89 | 854 int |
210 | 855 get_register(void) |
724 | 856 { /* 使われていないレジスタを調べる */ |
219 | 857 int i,j,reg; |
96 | 858 for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { |
724 | 859 if (regs[i]) continue; /* 使われている */ |
860 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
861 return i; /* その場所を表す番号を返す */ | |
862 } | |
863 /* PTR_CACHE をつぶす */ | |
341 | 864 if ((i=last_ptr_cache())) { |
865 clear_ptr_cache_reg(i); | |
724 | 866 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ |
867 return i; /* その場所を表す番号を返す */ | |
96 | 868 } |
869 /* search register stack */ | |
870 for(i=0;i<reg_sp;i++) { | |
120 | 871 if ((reg=reg_stack[i])>=0) { |
96 | 872 code_assign_lvar( |
245 | 873 (j=new_lvar(SIZE_OF_INT)),reg,0); |
219 | 874 reg_stack[i]= j-REG_LVAR_OFFSET; |
120 | 875 return reg; |
89 | 876 } |
877 } | |
206 | 878 #if LONGLONG_CODE |
879 /* search register stack */ | |
880 for(i=0;i<lreg_sp;i++) { | |
881 if ((reg=lreg_stack[i])>=0) { | |
219 | 882 code_lassign_lvar( |
245 | 883 (j=new_lvar(SIZE_OF_LONGLONG)),reg); |
219 | 884 lreg_stack[i]= j-REG_LVAR_OFFSET; |
206 | 885 free_register(reg); |
886 return get_register(); | |
887 } | |
888 } | |
889 #endif | |
130 | 890 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { |
891 reg =REG_VAR_BASE-i; | |
724 | 892 if (! regs[reg]) { /* 使われていないなら */ |
893 regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
130 | 894 if (i>max_reg_var) max_reg_var=i; |
724 | 895 return reg; /* その場所を表す番号を返す */ |
130 | 896 } |
897 } | |
724 | 898 /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ |
528 | 899 error(RGERR); return creg; |
89 | 900 } |
901 | |
210 | 902 #if 0 |
208 | 903 int |
904 get_register(void) | |
905 { | |
906 int i = get_register0(); | |
468 | 907 printf("## get_register %d\n",i); |
208 | 908 return i; |
909 } | |
210 | 910 #endif |
208 | 911 |
93 | 912 int |
913 pop_register(void) | |
724 | 914 { /* レジスタから値を取り出す */ |
93 | 915 return reg_stack[--reg_sp]; |
916 } | |
917 | |
195 | 918 #if FLOAT_CODE |
96 | 919 int |
210 | 920 get_dregister(int d) |
724 | 921 { /* 使われていないレジスタを調べる */ |
103 | 922 int i,reg; |
145 | 923 for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { |
724 | 924 if (regs[i]) continue; /* 使われている */ |
925 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
926 return i; /* その場所を表す番号を返す */ | |
102 | 927 } |
96 | 928 /* search register stack */ |
929 for(i=0;i<freg_sp;i++) { | |
103 | 930 if ((reg=freg_stack[i])>=0) { |
96 | 931 code_dassign_lvar( |
245 | 932 (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); |
96 | 933 freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; |
120 | 934 return reg; |
96 | 935 } |
936 } | |
130 | 937 for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) { |
145 | 938 reg =FREG_VAR_BASE-i+FREG_OFFSET; |
724 | 939 if (! regs[reg]) { /* 使われていないなら */ |
940 regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
130 | 941 if (i>max_freg_var) max_freg_var=i; |
724 | 942 return reg; /* その場所を表す番号を返す */ |
130 | 943 } |
944 } | |
724 | 945 /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ |
98 | 946 error(REG_ERR); return freg; |
96 | 947 } |
948 | |
210 | 949 #if 0 |
208 | 950 int |
951 get_dregister(int d) | |
952 { | |
953 int i = get_dregister0(d); | |
468 | 954 printf("## get_dregister %d\n",i); |
208 | 955 return i; |
956 } | |
210 | 957 #endif |
208 | 958 |
96 | 959 int |
97 | 960 pop_fregister(void) |
724 | 961 { /* レジスタから値を取り出す */ |
96 | 962 return freg_stack[--freg_sp]; |
963 } | |
195 | 964 #endif |
965 | |
530 | 966 |
195 | 967 int |
207 | 968 get_lregister0() |
969 { | |
970 int i; | |
971 for(i=LREG_OFFSET+1;i<REAL_MAX_LREGISTER+LREG_OFFSET;i++) { | |
972 if (regs[i]==0) { | |
973 return i; | |
974 } | |
975 } | |
976 return -1; | |
977 } | |
978 | |
530 | 979 static int |
980 get_lregister1(int n,int m) | |
981 { | |
982 int i; | |
983 #if 1 | |
984 for(i=LREG_OFFSET;i<REAL_MAX_LREGISTER+LREG_OFFSET;i++) { | |
985 if (regv_l(i)==n && regv_h(i)==m) { | |
986 return i; | |
987 } | |
988 } | |
989 #endif | |
990 return get_lregister0(); | |
991 } | |
992 | |
993 | |
994 static void | |
995 cleanup_lregister0() | |
996 { | |
997 int i; | |
536 | 998 // we should not have this, but powerpc's function |
999 // lost some input register variables. | |
530 | 1000 #if 1 |
1001 for(i=LREG_OFFSET+1;i<REAL_MAX_LREGISTER+LREG_OFFSET;i++) { | |
1002 if (regs[i]) { | |
1003 if(!regv_l(i) && !regv_h(i)) { | |
1004 regs[i]=0; | |
1005 // printf("## cleanup lreg 0 %d\n",i); | |
1006 } else if(!regs[regv_l(i)] && !regs[regv_h(i)]) { | |
1007 free_register(i); | |
1008 // printf("## cleanup lreg 1 %d\n",i); | |
1009 } | |
1010 } | |
1011 } | |
1012 #endif | |
1013 } | |
1014 | |
207 | 1015 int |
205 | 1016 get_lregister() |
1017 { | |
207 | 1018 int h,l,i; |
1019 i = get_lregister0(); | |
1020 if (i==-1) return -1; | |
220 | 1021 h = get_register(); |
1022 if (h==-1) return -1; | |
1023 regv_h(i) = h; | |
1024 l = get_register(); | |
590 | 1025 if (l==-1) { |
1026 if (regs[h]!=REG_VAR) free_register(h); | |
1027 if (regs[i]!=REG_VAR) free_register(i); | |
1028 return -1; | |
1029 } | |
220 | 1030 regv_l(i) = l; |
590 | 1031 if (!regs[i]) regs[i]=USING_REG; |
530 | 1032 // printf("## get_lregister %d %s %s\n",i, lregister_name_high(i), lregister_name_low(i)); |
220 | 1033 return i; |
205 | 1034 } |
1035 | |
1036 int | |
195 | 1037 get_lregister_var(NMTBL *n) |
1038 { | |
207 | 1039 int i,j,ll; |
206 | 1040 int max_reg_var_save=max_reg_var; |
207 | 1041 ll = get_lregister0(); |
255 | 1042 if (ll==-1) goto not_found; |
207 | 1043 if (regs[ll]==0) { |
1044 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { | |
724 | 1045 if (! regs[REG_VAR_BASE-i]) { /* 使われていないなら */ |
1046 /* そのレジスタを使うことを宣言し */ | |
207 | 1047 regs[REG_VAR_BASE-i]=USING_REG; |
1048 if (i>max_reg_var) max_reg_var=i; | |
1049 for(j=0;j<REG_VAR_BASE-REG_VAR_MIN;j++) { | |
1050 if (! regs[REG_VAR_BASE-j]) { | |
724 | 1051 /* 使われていないなら */ |
1052 /* そのレジスタを使うことを宣言し */ | |
590 | 1053 regs[REG_VAR_BASE-j]=REG_VAR; |
207 | 1054 if (j>max_reg_var) max_reg_var=j; |
724 | 1055 /* その場所を表す番号を返す */ |
590 | 1056 regs[ll]=REG_VAR; |
207 | 1057 regv_l(ll) = REG_VAR_BASE-j; |
1058 regv_h(ll) = REG_VAR_BASE-i; | |
711 | 1059 return list3n(LREGISTER,ll,n); |
207 | 1060 } |
206 | 1061 } |
724 | 1062 /* ひとつしかなかった */ |
207 | 1063 regs[REG_VAR_BASE-i]=0; |
1064 max_reg_var=max_reg_var_save; | |
1065 goto not_found; | |
206 | 1066 } |
1067 } | |
1068 } | |
207 | 1069 not_found: |
711 | 1070 return list3n(LVAR,new_lvar(SIZE_OF_LONGLONG),0); |
195 | 1071 } |
96 | 1072 |
93 | 1073 void |
1074 emit_pop_free(int xreg) | |
1075 { | |
590 | 1076 if (xreg>=0 && xreg!=creg && regs[xreg]!=REG_VAR) |
103 | 1077 free_register(xreg); |
93 | 1078 } |
1079 | |
211 | 1080 void |
1081 | |
724 | 1082 free_register(int i) { /* いらなくなったレジスタを開放 */ |
590 | 1083 // printf("## free_register %d\n",i); |
207 | 1084 if (is_longlong_reg(i)) { |
1085 regs[regv_l(i)]=0; | |
1086 regs[regv_h(i)]=0; | |
206 | 1087 } |
530 | 1088 regs[i]=0; |
96 | 1089 } |
1090 | |
341 | 1091 extern void |
1092 use_ptr_cache(int r) | |
1093 { | |
1094 regs[r]=PTRC_REG; | |
1095 } | |
1096 | |
89 | 1097 int |
138 | 1098 get_input_dregister_var(int i,NMTBL *n,int is_code,int d) |
99 | 1099 { |
126 | 1100 if (is_code) { |
148 | 1101 if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0; |
1102 i = FREG_VAR_BASE-i+FREG_OFFSET; | |
126 | 1103 } else { |
135 | 1104 if (i<0||i>=MAX_INPUT_DREGISTER_VAR) return 0; |
145 | 1105 i = i+MIN_TMP_FREG+FREG_OFFSET; |
126 | 1106 } |
711 | 1107 return list3n(DREGISTER,i,n); |
205 | 1108 } |
1109 | |
1110 int | |
1111 get_input_lregister_var(int i,NMTBL *n,int is_code) | |
1112 { | |
207 | 1113 int ll; |
1114 if (i!=-1) { | |
1115 if (is_code) { | |
227 | 1116 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; |
207 | 1117 i = REG_VAR_BASE-i; |
1118 } else { | |
227 | 1119 if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; |
674 | 1120 #ifndef __APPLE__ |
673 | 1121 if (i%2==1) i++; |
674 | 1122 #endif |
207 | 1123 i = i+MIN_TMP_REG; |
1124 } | |
530 | 1125 ll = get_lregister1(i,i+1); |
411 | 1126 #if ENDIAN_L==0 |
1127 regv_l(ll)=i; | |
1128 regv_h(ll)=i+1; | |
1129 #else | |
222 | 1130 regv_h(ll)=i; |
1131 regv_l(ll)=i+1; | |
411 | 1132 #endif |
207 | 1133 } else { error(-1); ll=LREG_OFFSET+2; } |
711 | 1134 return list3n(LREGISTER,ll,n); |
99 | 1135 } |
1136 | |
1137 int | |
126 | 1138 get_input_register_var(int i,NMTBL *n,int is_code) |
99 | 1139 { |
126 | 1140 if (is_code) { |
131 | 1141 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; |
126 | 1142 i = REG_VAR_BASE-i; |
1143 } else { | |
135 | 1144 if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; |
1145 i = i+MIN_TMP_REG; | |
1146 } | |
711 | 1147 return list3n(REGISTER,i,n); |
135 | 1148 } |
1149 | |
145 | 1150 /* double register case? */ |
1151 | |
135 | 1152 int |
1153 get_input_register_var_1(int i,NMTBL *n,int is_code) | |
1154 { | |
1155 if (is_code) { | |
1156 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; | |
1157 i = REG_VAR_BASE-i; | |
1158 } else { | |
1159 if (i<0||i>=MAX_INPUT_REGISTER_VAR+1) return 0; | |
126 | 1160 i = i+MIN_TMP_REG; |
1161 } | |
711 | 1162 return list3n(REGISTER,i,n); |
99 | 1163 } |
1164 | |
1165 int | |
137 | 1166 free_register_count(int d) |
103 | 1167 { |
1168 int i,count,fcount; | |
1169 fcount = count = 0; | |
1170 for(i=0;i<MAX_REGISTER;i++) { | |
205 | 1171 if (! regs[i]) count++; |
103 | 1172 } |
1173 for(i=0;i<MAX_FREGISTER;i++) { | |
205 | 1174 if (! regs[i+FREG_OFFSET]) fcount++; |
103 | 1175 } |
468 | 1176 printf("## free reg %d freg %d\n",count,fcount); |
137 | 1177 return d?fcount:count; |
103 | 1178 } |
1179 | |
205 | 1180 #if 0 |
1181 static int | |
89 | 1182 register_full(void) |
1183 { | |
1184 int i; | |
1185 for(i=0;i<MAX_REGISTER;i++) { | |
1186 if (! regs[i]) { | |
1187 return 0; | |
1188 } | |
1189 } | |
1190 return 1; | |
1191 } | |
205 | 1192 #endif |
89 | 1193 |
1194 void | |
1195 free_all_register(void) | |
1196 { | |
1197 int i; | |
468 | 1198 // printf("## free_all register\n"); |
206 | 1199 #if LONGLONG_CODE |
226 | 1200 for(i=0;i<REAL_MAX_LREGISTER;i++) { |
1201 regs[i+LREG_OFFSET]=0; | |
1202 regv_l(i+LREG_OFFSET) = 0; | |
1203 regv_h(i+LREG_OFFSET) = 0; | |
1204 } | |
206 | 1205 lreg = 0; |
222 | 1206 // set_lreg(LREG_LREGISTER,0); |
206 | 1207 #endif |
205 | 1208 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; } |
1209 for(i=0;i<MAX_FREGISTER;i++) { regs[i+FREG_OFFSET]=0; } | |
195 | 1210 #if FLOAT_CODE |
138 | 1211 freg = get_dregister(1); |
195 | 1212 set_freg(FREG_FREGISTER,0); |
1213 #endif | |
1214 ireg = creg = get_register(); | |
207 | 1215 set_ireg(CREG_REGISTER,0); |
89 | 1216 return; |
1217 } | |
1218 | |
345 | 1219 extern int |
1220 code_register_overlap(int s,int t) | |
1221 { | |
1222 switch(car(s)) { | |
1223 case REGISTER: | |
1224 switch(car(t)) { | |
1225 case DREGISTER: case FREGISTER: break; | |
1226 case REGISTER: | |
1227 if(cadr(s)==cadr(t)) return 1; | |
1228 break; | |
1229 case LREGISTER: | |
1230 if(cadr(s)==regv_l(cadr(t))) return 1; | |
1231 if(cadr(s)==regv_h(cadr(t))) return 1; | |
1232 break; | |
1233 } | |
1234 break; | |
1235 case DREGISTER: | |
1236 case FREGISTER: | |
1237 switch(car(t)) { | |
1238 case REGISTER: case LREGISTER: break; | |
1239 case DREGISTER: case FREGISTER: | |
1240 if(cadr(s)==cadr(t)) return 1; | |
1241 break; | |
1242 } | |
1243 break; | |
1244 case LREGISTER: | |
1245 switch(car(t)) { | |
1246 case DREGISTER: case FREGISTER: break; | |
1247 case REGISTER: | |
1248 if(cadr(t)==regv_l(cadr(s))) return 1; | |
1249 if(cadr(t)==regv_h(cadr(s))) return 1; | |
1250 break; | |
1251 case LREGISTER: | |
1252 if(regv_l(cadr(t))==regv_l(cadr(s))) return 1; | |
1253 if(regv_l(cadr(t))==regv_h(cadr(s))) return 1; | |
1254 if(regv_h(cadr(t))==regv_l(cadr(s))) return 1; | |
1255 if(regv_h(cadr(t))==regv_h(cadr(s))) return 1; | |
1256 break; | |
1257 } | |
1258 break; | |
1259 } | |
1260 return 0; | |
1261 } | |
1262 | |
531 | 1263 // int lreg_count; |
530 | 1264 |
89 | 1265 void |
1266 register_usage(char *s) | |
1267 { | |
207 | 1268 #if 1 |
273 | 1269 int i,j; |
1270 #endif | |
1271 #define USAGE_MAX 4 | |
1272 if (!lsrc) return; | |
467 | 1273 printf("## %d: %s:",lineno,s); |
273 | 1274 if (ireg) printf(" creg=%s",register_name(ireg)); |
1275 if (freg) printf(" freg=%s",fregister_name(freg)); | |
1276 if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg), | |
1277 lregister_name_low(lreg)); | |
1278 #if 1 | |
1279 for(j=0,i=0;i<MAX_REGISTER;i++) if (regs[i]) j++; | |
1280 if (j>USAGE_MAX) { | |
530 | 1281 printf("\n## regs(%d):",j); |
273 | 1282 for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } |
1283 } | |
1284 if (reg_sp>0) { | |
1285 printf(" stack "); | |
1286 for(i=reg_sp;i>0;i--) { | |
1287 if(reg_stack[i-1]>=0) { | |
1288 printf(" %s",register_name(reg_stack[i-1])); | |
1289 } else | |
1290 printf(",%d",reg_stack[i-1]); | |
1291 } | |
1292 } | |
1293 for(j=0,i=0;i<MAX_FREGISTER;i++) if (regs[i+FREG_OFFSET]) j++; | |
1294 if (j>USAGE_MAX) { | |
530 | 1295 printf("\n## freg(%d):",j); |
273 | 1296 for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } |
1297 } | |
1298 if (freg_sp>0) { | |
1299 printf(" fstack "); | |
1300 for(i=freg_sp;i>0;i--) { | |
1301 if(freg_stack[i-1]>=0) { | |
1302 printf(" %s",fregister_name(freg_stack[i-1])); | |
1303 } else | |
1304 printf(",%d",freg_stack[i-1]); | |
1305 } | |
1306 } | |
1307 | |
1308 for(j=0,i=0;i<REAL_MAX_LREGISTER;i++) if (regs[i+LREG_OFFSET]) j++; | |
531 | 1309 // lreg_count = j; |
273 | 1310 if (j>USAGE_MAX) { |
530 | 1311 printf("\n## lreg(%d):",j); |
273 | 1312 for(i=0;i<REAL_MAX_LREGISTER;i++) { printf("%d",regs[i+LREG_OFFSET]); } |
530 | 1313 #if 0 |
1314 for(i=0;i<REAL_MAX_LREGISTER;i++) { | |
1315 if (regs[i+LREG_OFFSET] && regv_l(i+LREG_OFFSET)) | |
1316 printf(" %s-%s", lregister_name_high(i+LREG_OFFSET),lregister_name_low(i+LREG_OFFSET)); | |
1317 else if (regv_l(i+LREG_OFFSET)) | |
1318 printf(" *%s-%s", lregister_name_high(i+LREG_OFFSET),lregister_name_low(i+LREG_OFFSET)); | |
1319 } | |
1320 #endif | |
273 | 1321 } |
1322 if (lreg_sp>0) { | |
1323 printf(" lstack "); | |
1324 for(i=lreg_sp;i>0;i--) { | |
1325 if(lreg_stack[i-1]>=0) { | |
1326 printf(" %s",lregister_name_high(lreg_stack[i-1])); | |
1327 printf(",%s",lregister_name_low(lreg_stack[i-1])); | |
1328 } else | |
1329 printf(",%d",lreg_stack[i-1]); | |
1330 } | |
1331 } | |
1332 #endif | |
1333 printf("\n"); | |
1334 } | |
1335 | |
211 | 1336 void |
1337 | |
89 | 1338 gexpr_init(void) |
1339 { | |
1340 while(reg_sp > 0) { | |
292 | 1341 error(-1); |
89 | 1342 free_register(reg_stack[--reg_sp]); |
1343 } | |
148 | 1344 while(freg_sp > 0) { |
292 | 1345 error(-1); |
148 | 1346 free_register(freg_stack[--freg_sp]); |
1347 } | |
206 | 1348 while(lreg_sp > 0) { |
292 | 1349 error(-1); |
206 | 1350 free_register(lreg_stack[--lreg_sp]); |
1351 } | |
221 | 1352 use_int0(); |
516 | 1353 text_mode(0); |
89 | 1354 gexpr_code_init(); |
1355 register_usage("gexpr_init"); | |
1356 } | |
1357 | |
1358 | |
211 | 1359 void |
1360 | |
89 | 1361 emit_init(void) |
1362 { | |
327 | 1363 /* called before each declaration */ |
1364 | |
89 | 1365 free_all_register(); |
110 | 1366 max_reg_var=-1; max_freg_var=-1; |
89 | 1367 reg_sp = 0; |
123 | 1368 freg_sp = 0; |
89 | 1369 } |
1370 | |
97 | 1371 |
89 | 1372 int |
105 | 1373 get_register_var(NMTBL *n) |
89 | 1374 { |
1375 int i; | |
99 | 1376 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { |
724 | 1377 if (! regs[REG_VAR_BASE-i]) { /* 使われていないなら */ |
1378 /* そのレジスタを使うことを宣言し */ | |
590 | 1379 regs[REG_VAR_BASE-i]=REG_VAR; |
97 | 1380 if (i>max_reg_var) max_reg_var=i; |
724 | 1381 /* その場所を表す番号を返す */ |
711 | 1382 return list3n(REGISTER,REG_VAR_BASE-i,n); |
137 | 1383 } |
96 | 1384 } |
711 | 1385 return list3n(LVAR,new_lvar(SIZE_OF_INT),0); |
96 | 1386 } |
1387 | |
1388 int | |
138 | 1389 get_dregister_var(NMTBL *n,int d) |
96 | 1390 { |
1391 int i; | |
148 | 1392 for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) { |
724 | 1393 if (! regs[FREG_VAR_BASE-i+FREG_OFFSET]) { /* 使われていないなら */ |
1394 regs[FREG_VAR_BASE-i+FREG_OFFSET]=REG_VAR; /*そのレジスタを使うことを宣言し*/ | |
97 | 1395 if (i>max_freg_var) max_freg_var=i; |
724 | 1396 /* その場所を表す番号を返す */ |
712 | 1397 return list3n(DREGISTER, |
1398 FREG_VAR_BASE-i+FREG_OFFSET,n); | |
89 | 1399 } |
1400 } | |
711 | 1401 return list3n(LVAR,new_lvar(SIZE_OF_DOUBLE),0); |
89 | 1402 } |
1403 | |
426 | 1404 int |
107 | 1405 emit_push() |
89 | 1406 { |
426 | 1407 int new_reg,old=creg; |
221 | 1408 if (!is_int_reg(creg)) error(-1); |
102 | 1409 if (reg_sp>MAX_MAX) error(-1); |
724 | 1410 new_reg = get_register(); /* 絶対に取れる */ |
590 | 1411 if (new_reg==creg) error(-1); // freed creg |
724 | 1412 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ |
147 | 1413 ireg = creg = new_reg; |
590 | 1414 if (!regs[creg]) regs[creg]=USING_REG; |
426 | 1415 return old; |
89 | 1416 } |
1417 | |
1418 int | |
93 | 1419 emit_pop(int type) |
89 | 1420 { |
112 | 1421 int xreg,reg; |
97 | 1422 xreg=pop_register(); |
1423 if (xreg<= -REG_LVAR_OFFSET) { | |
112 | 1424 reg = get_register(); |
119 | 1425 code_rlvar(REG_LVAR_OFFSET+xreg,reg); |
117 | 1426 free_lvar(REG_LVAR_OFFSET+xreg); |
112 | 1427 xreg = reg; |
97 | 1428 } |
89 | 1429 return xreg; |
1430 } | |
1431 | |
660 | 1432 #ifdef __APPLE__ |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
1433 static int code_base; |
660 | 1434 #endif |
89 | 1435 |
341 | 1436 extern void |
1437 code_ptr_cache_def(int r,NMTBL *nptr) | |
89 | 1438 { |
341 | 1439 char *rrn = register_name(r); |
660 | 1440 #ifdef __APPLE__ |
544 | 1441 if (nptr->sc==STATIC && !(is_code(nptr)||is_function(nptr))) { |
109 | 1442 printf("\taddis %s,r31,ha16(_%s-L_%d)\n", |
1443 rrn,nptr->nm,code_base); | |
1444 printf("\tla %s,lo16(_%s-L_%d)(%s)\n", | |
1445 rrn,nptr->nm,code_base,rrn); | |
1446 } else { | |
1447 printf("\taddis %s,r31,ha16(L_%s$non_lazy_ptr-L_%d)\n", | |
1448 rrn,nptr->nm,code_base); | |
1449 printf("\tlwz %s,lo16(L_%s$non_lazy_ptr-L_%d)(%s)\n", | |
1450 rrn,nptr->nm,code_base,rrn); | |
1451 } | |
660 | 1452 #else |
1453 printf("\tlis %s,%s@ha\n", | |
1454 rrn,nptr->nm); | |
1455 printf("\tla %s,%s@l(%s)\n", | |
1456 rrn,nptr->nm,rrn); | |
1457 #endif | |
89 | 1458 } |
1459 | |
245 | 1460 static char *cload(int sz) { return sz==1?"lbz":sz==SIZE_OF_SHORT?"lhz":"lwz"; } |
1461 static char *cstore(int sz) { return sz==1?"stb":sz==SIZE_OF_SHORT?"sth":"stw"; } | |
230 | 1462 |
1463 static void | |
1464 cext(int sign,int sz,int reg) | |
1465 { | |
1466 char *crn = register_name(reg); | |
1467 if (sign) { | |
1468 if (sz==1) | |
1469 printf("\textsb %s,%s\n",crn,crn); | |
245 | 1470 else if (sz==SIZE_OF_SHORT) |
230 | 1471 printf("\textsh %s,%s\n",crn,crn); |
1472 } else { | |
1473 if (sz==1) | |
1474 printf("\trlwinm %s,%s,0,0xff\n",crn,crn); | |
245 | 1475 else if (sz==SIZE_OF_SHORT) |
230 | 1476 printf("\trlwinm %s,%s,0,0xffff\n",crn,crn); |
1477 } | |
1478 } | |
1479 | |
168 | 1480 |
89 | 1481 void |
92 | 1482 code_label(int labelno) |
1483 { | |
1484 clear_ptr_cache(); | |
662 | 1485 printf("%s%d:\n",lpfx,labelno); |
92 | 1486 } |
1487 | |
367 | 1488 static void |
1489 code_add(int reg,int offset,int r) | |
1490 { | |
1491 char *crn = register_name(reg); | |
1492 char *rrn = register_name(r); | |
1493 if (offset==0) { | |
1494 if(r!=reg) | |
1495 printf("\tmr %s,%s\n",crn,rrn); | |
375 | 1496 } else if (LARGE_OFFSET(offset)) { |
660 | 1497 #ifdef __APPLE__ |
556 | 1498 printf("\tla %s,lo16(%d)(%s)\n",crn,offset,rrn); |
1499 printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset); | |
660 | 1500 #else |
1501 printf("\tla %s,%d@l(%s)\n",crn,offset,rrn); | |
1502 printf("\taddis %s,%s,%d@ha\n",crn,crn,offset); | |
1503 #endif | |
367 | 1504 } else |
1505 printf("\taddi %s,%s,%d\n",crn,rrn,offset); | |
1506 } | |
1507 | |
1508 static void | |
1509 code_ld(char *ld,int reg,int offset,int r) | |
1510 { | |
1511 char *crn = register_name(reg); | |
1512 char *rrn = register_name(r); | |
375 | 1513 if (LARGE_OFFSET(offset)) { |
660 | 1514 #ifdef __APPLE__ |
556 | 1515 printf("\taddis %s,%s,ha16(%d)\n",crn,rrn,offset); |
1516 printf("\t%s %s,lo16(%d)(%s)\n",ld,crn,offset,crn); | |
660 | 1517 #else |
1518 printf("\taddis %s,%s,%d@ha\n",crn,rrn,offset); | |
1519 printf("\t%s %s,%d@l(%s)\n",ld,crn,offset,crn); | |
1520 #endif | |
367 | 1521 } else |
1522 printf("\t%s %s,%d(%s)\n",ld,crn,offset,rrn); | |
1523 } | |
1524 | |
1525 static void | |
1526 code_ldf(char *ld,char *crn,int offset,int r) | |
1527 { | |
1528 char *rrn = register_name(r); | |
1529 int reg; | |
1530 char *lrn; | |
1531 if (offset<-32768||32767<offset) { | |
1532 lrn = register_name(reg = get_register()); | |
660 | 1533 #ifdef __APPLE__ |
556 | 1534 printf("\taddis %s,%s,ha16(%d)\n",lrn,rrn,offset); |
1535 printf("\t%s %s,lo16(%d)(%s)\n",ld,crn,offset,lrn); | |
660 | 1536 #else |
1537 printf("\taddis %s,%s,%d@ha\n",lrn,rrn,offset); | |
1538 printf("\t%s %s,%d@l(%s)\n",ld,crn,offset,lrn); | |
1539 #endif | |
367 | 1540 free_register(reg); |
1541 } else | |
1542 printf("\t%s %s,%d(%s)\n",ld,crn,offset,rrn); | |
1543 } | |
1544 | |
92 | 1545 void |
221 | 1546 code_gvar(int e1,int reg) { |
1547 use_int(reg); | |
711 | 1548 code_add(reg,cadr(e1),get_ptr_cache(ncaddr(e1))); |
89 | 1549 return; |
1550 } | |
1551 | |
1552 void | |
221 | 1553 code_rgvar(int e1,int reg) { |
1554 use_int(reg); | |
711 | 1555 code_ld("lwz",reg,cadr(e1),get_ptr_cache(ncaddr(e1))); |
89 | 1556 } |
1557 | |
1558 void | |
221 | 1559 code_crgvar(int e1,int reg,int sign,int sz){ |
1560 use_int(reg); | |
711 | 1561 code_ld(cload(sz),reg,cadr(e1),get_ptr_cache(ncaddr(e1))); |
230 | 1562 cext(sign,sz,reg); |
89 | 1563 } |
1564 | |
165 | 1565 |
1566 | |
89 | 1567 void |
221 | 1568 code_register(int e2,int reg) { |
1569 use_int(reg); | |
1570 if (reg!=e2) | |
1571 printf("\tmr %s,%s\n",register_name(reg),register_name(e2)); | |
89 | 1572 } |
1573 | |
353 | 1574 extern void |
1575 code_i2c(int reg) | |
1576 { | |
1577 use_int(reg); | |
1578 cext(1,1,reg); | |
1579 } | |
1580 | |
1581 extern void | |
1582 code_i2s(int reg) | |
1583 { | |
1584 use_int(reg); | |
1585 cext(1,SIZE_OF_SHORT,reg); | |
1586 } | |
1587 | |
1588 extern void | |
1589 code_u2uc(int reg) | |
1590 { | |
1591 use_int(reg); | |
1592 cext(0,1,reg); | |
1593 } | |
1594 | |
1595 extern void | |
1596 code_u2us(int reg) | |
1597 { | |
1598 use_int(reg); | |
1599 cext(0,SIZE_OF_SHORT,reg); | |
1600 } | |
89 | 1601 |
1602 void | |
95 | 1603 code_rlvar(int e2,int reg) { |
221 | 1604 use_int(reg); |
119 | 1605 lvar_intro(e2); |
1606 printf("\tlwz %s,",register_name(reg)); | |
1607 lvar(e2); | |
89 | 1608 } |
1609 | |
1610 void | |
165 | 1611 code_crlvar(int e2,int reg,int sign,int sz) { |
221 | 1612 use_int(reg); |
119 | 1613 lvar_intro(e2); |
165 | 1614 printf("\t%s %s,",cload(sz),register_name(reg)); |
119 | 1615 lvar(e2); |
230 | 1616 cext(sign,sz,reg); |
89 | 1617 } |
1618 | |
1619 void | |
221 | 1620 code_fname(NMTBL *n,int reg) { |
89 | 1621 int r; |
221 | 1622 use_int(reg); |
109 | 1623 r = get_ptr_cache(n); |
221 | 1624 if(r!=reg) |
1625 printf("\tmr %s,%s\n",register_name(reg),register_name(r)); | |
89 | 1626 return; |
1627 } | |
1628 | |
363 | 1629 void |
1630 code_label_value(int label,int reg) { | |
1631 char *crn; | |
1632 use_int(reg); | |
1633 crn = register_name(reg); | |
662 | 1634 #ifdef __APPLE__ |
363 | 1635 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",crn,label,code_base); |
1636 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,label,code_base,crn); | |
660 | 1637 #else |
1638 printf("\tlis %s,.LC%d@ha\n",crn,label); | |
1639 printf("\tla %s,.LC%d@l(%s)\n",crn,label,crn); | |
1640 #endif | |
363 | 1641 return; |
1642 } | |
89 | 1643 |
1644 void | |
221 | 1645 code_const(int e2,int reg) { |
1646 char *crn; | |
1647 use_int(reg); | |
1648 crn = register_name(reg); | |
527 | 1649 // printf("## 0x%08x\n",e2); |
660 | 1650 #ifdef __APPLE__ |
89 | 1651 if (-32768<e2&&e2<32768) |
1652 printf("\tli %s,%d\n",crn,e2); | |
599 | 1653 else if ((e2&0xffff)==0) |
1654 printf("\tlis %s,ha16(%d)\n",crn,e2); | |
89 | 1655 else { |
1656 printf("\tlis %s,ha16(%d)\n",crn,e2); | |
1657 printf("\taddi %s,%s,lo16(%d)\n",crn,crn,e2); | |
1658 } | |
660 | 1659 #else |
1660 if (-32768<e2&&e2<32768) | |
1661 printf("\tli %s,%d\n",crn,e2); | |
1662 else if ((e2&0xffff)==0) | |
1663 printf("\tlis %s,%d@ha\n",crn,e2); | |
1664 else { | |
1665 printf("\tlis %s,%d@ha\n",crn,e2); | |
1666 printf("\taddi %s,%s,%d@l\n",crn,crn,e2); | |
1667 } | |
1668 #endif | |
89 | 1669 } |
1670 | |
1671 void | |
107 | 1672 code_neg(int creg) { |
221 | 1673 use_int(creg); |
93 | 1674 printf("\tneg %s,%s\n", register_name(creg), register_name(creg)); |
89 | 1675 } |
1676 | |
1677 | |
1678 void | |
107 | 1679 code_not(int creg) { |
221 | 1680 use_int(creg); |
89 | 1681 printf("\tnor %s,%s,%s\n", |
1682 register_name(creg), register_name(creg),register_name(creg)); | |
1683 } | |
1684 | |
1685 | |
1686 void | |
107 | 1687 code_lnot(int creg) { |
221 | 1688 use_int(creg); |
660 | 1689 #ifdef __APPLE__ |
89 | 1690 printf("\tsubfic r0,%s,0\n", register_name(creg)); |
1691 printf("\tadde %s,r0,%s\n", register_name(creg),register_name(creg)); | |
660 | 1692 #else |
1693 printf("\tsubfic 0,%s,0\n", register_name(creg)); | |
1694 printf("\tadde %s,0,%s\n", register_name(creg),register_name(creg)); | |
1695 #endif | |
89 | 1696 } |
1697 | |
1698 void | |
168 | 1699 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
89 | 1700 char *xrn,*drn; |
1701 if (car(e2)==REGISTER) { | |
221 | 1702 use_int(reg); |
95 | 1703 printf("\taddi %s,%s,%d\n", |
168 | 1704 register_name(cadr(e2)),register_name(cadr(e2)), dir); |
587 | 1705 if (use && cadr(e2)!=reg) |
273 | 1706 printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2))); |
89 | 1707 return; |
1708 } | |
1709 g_expr(e2); | |
221 | 1710 if (!is_int_reg(creg)) error(-1); |
89 | 1711 xrn = register_name(creg); |
221 | 1712 if (reg==USE_CREG) { |
231 | 1713 reg=get_register(); if (!reg) error(-1); |
1714 drn = register_name(reg); | |
1715 set_ireg(reg,0); | |
221 | 1716 } else { |
1717 drn = register_name(reg); | |
1718 } | |
168 | 1719 printf("\t%s %s,0(%s)\n",cload(sz),drn,xrn); |
231 | 1720 if (use) cext(sign,sz,reg); |
168 | 1721 printf("\taddi %s,%s,%d\n",drn,drn,dir); |
1722 printf("\t%s %s,0(%s)\n",cstore(sz),drn,xrn); | |
89 | 1723 } |
1724 | |
1725 | |
1726 void | |
168 | 1727 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
89 | 1728 char *xrn,*crn,*nrn; |
231 | 1729 int nreg; |
89 | 1730 if (car(e2)==REGISTER) { |
221 | 1731 use_int(reg); |
587 | 1732 if (use) |
1733 printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2))); | |
89 | 1734 printf("\taddi %s,%s,%d\n", |
168 | 1735 register_name(cadr(e2)),register_name(cadr(e2)),dir); |
89 | 1736 return; |
1737 } | |
1738 g_expr(e2); | |
221 | 1739 if (!is_int_reg(creg)) error(-1); |
89 | 1740 crn = register_name(creg); |
1741 nreg=get_register(); if (!nreg) error(-1); | |
1742 nrn = register_name(nreg); | |
221 | 1743 if (reg==USE_CREG) { |
231 | 1744 reg=get_register(); if (!reg) error(-1); |
1745 xrn = register_name(reg); | |
1746 set_ireg(reg,0); | |
221 | 1747 } else { |
1748 xrn = register_name(reg); | |
1749 } | |
168 | 1750 printf("\t%s %s,0(%s)\n",cload(sz),xrn,crn); |
230 | 1751 if (use) cext(sign,sz,reg); |
168 | 1752 printf("\taddi %s,%s,%d\n",nrn,xrn,dir); |
1753 printf("\t%s %s,0(%s)\n",cstore(sz),nrn,crn); | |
89 | 1754 free_register(nreg); |
1755 } | |
1756 | |
1757 | |
1758 void | |
107 | 1759 code_return(int creg) { |
662 | 1760 |
221 | 1761 use_int(creg); |
660 | 1762 code_label_value(retcont,creg); |
89 | 1763 } |
1764 | |
577 | 1765 #define R1SAVE 0 |
89 | 1766 |
1767 void | |
107 | 1768 code_environment(int creg) { |
126 | 1769 /* save frame pointer */ |
221 | 1770 use_int(creg); |
128 | 1771 #if R1SAVE |
660 | 1772 printf("\tlwz %s,0(%s)\n",register_name(creg),register_name(1)); |
128 | 1773 #else |
667 | 1774 printf("\tmr %s,%s\n",register_name(creg),register_name(REG_fp)); |
577 | 1775 // int l = 0; |
1776 // printf("\tla %s,",register_name(creg)); | |
1777 // printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label); | |
128 | 1778 #endif |
89 | 1779 } |
1780 | |
288 | 1781 static int rexpr_bool(int e1,int reg); |
1782 | |
1783 #if FLOAT_CODE | |
1784 static int drexpr_bool(int e1,int reg); | |
1785 #endif | |
1786 | |
1787 #if LONGLONG_CODE | |
1788 static int lrexpr_bool(int e1,int reg) | |
1789 { | |
1790 return 0; | |
1791 } | |
1792 #endif | |
1793 | |
1794 | |
1795 | |
89 | 1796 void |
221 | 1797 code_bool(int e1,int reg) { |
89 | 1798 char *xrn; |
1799 int e2,e3; | |
288 | 1800 |
1801 if (rexpr_bool(e1,reg)) return; | |
1802 #if FLOAT_CODE | |
1803 else if (drexpr_bool(e1,reg)) return; | |
1804 #endif | |
1805 #if LONGLONG_CODE | |
1806 else if (lrexpr_bool(e1,reg)) return; | |
1807 #endif | |
1808 | |
89 | 1809 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ |
289 | 1810 if (use) { |
1811 use_int(reg); | |
1812 xrn = register_name(reg); | |
1813 printf("\tli %s,0\n",xrn); | |
1814 jmp(e3=fwdlabel()); | |
1815 fwddef(e2); | |
1816 printf("\tli %s,1\n",xrn); | |
1817 fwddef(e3); | |
1818 } else { | |
1819 fwddef(e2); | |
1820 } | |
89 | 1821 } |
1822 | |
433 | 1823 #define code_gt(cond) (cond?"gt":"le") |
1824 | |
1825 #define code_ugt(cond) (cond?"gt":"le") | |
1826 | |
1827 #define code_ge(cond) (cond?"ge":"lt") | |
1828 | |
1829 #define code_uge(cond) (cond?"ge":"lt") | |
1830 | |
1831 #define code_eq(cond) (cond?"eq":"ne") | |
89 | 1832 |
569 | 1833 static int cmpflag = 7; |
280 | 1834 |
1835 static void | |
1836 inc_cmpflag() | |
1837 { | |
569 | 1838 // gcc use cmpflag 4 and 7, and gcc4 believes flag 4 is preserved. |
673 | 1839 do { |
1840 cmpflag = (cmpflag+1)%8; | |
1841 } while (cmpflag!=4 && cmpflag!=7); | |
280 | 1842 } |
1843 | |
662 | 1844 #ifdef __APPLE__ |
1845 static | |
1846 char *crname_[] = { "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7" }; | |
1847 #else | |
1848 static | |
1849 char *crname_[] = { "0", "1", "2", "3", "4", "5", "6", "7" }; | |
1850 #endif | |
1851 #define crname(d) (crname_[d]) | |
1852 | |
89 | 1853 void |
287 | 1854 code_cmp_crgvar(int e1,int reg,int sz,int label,int cond) { |
221 | 1855 use_int(reg); |
711 | 1856 code_ld(cload(sz),reg,cadr(e1),get_ptr_cache(ncaddr(e1))); |
432 | 1857 cext(0,sz,reg); |
291 | 1858 inc_cmpflag(); |
662 | 1859 printf("\tcmpwi %s,%s,0\n",crname(cmpflag),register_name(reg)); |
287 | 1860 jcond(label,cond); |
89 | 1861 } |
1862 | |
1863 | |
1864 void | |
287 | 1865 code_cmp_crlvar(int e2,int reg, int sz,int label,int cond) { |
221 | 1866 char *crn; |
1867 use_int(reg); | |
1868 crn = register_name(reg); | |
119 | 1869 lvar_intro(e2); |
167 | 1870 printf("\t%s %s,",cload(sz),crn); |
160 | 1871 lvar(e2); |
230 | 1872 cext(0,sz,reg); |
287 | 1873 code_cmp_register(reg,label,cond); |
160 | 1874 } |
1875 | |
89 | 1876 |
1877 void | |
287 | 1878 code_cmp_rgvar(int e1,int reg,int label,int cond) { |
221 | 1879 use_int(reg); |
711 | 1880 code_ld("lwz",reg,cadr(e1),get_ptr_cache(ncaddr(e1))); |
287 | 1881 code_cmp_register(reg,label,cond); |
89 | 1882 } |
1883 | |
1884 | |
1885 void | |
287 | 1886 code_cmp_rlvar(int e2,int reg,int label,int cond) { |
221 | 1887 char *crn; |
1888 use_int(reg); | |
1889 crn = register_name(reg); | |
119 | 1890 lvar_intro(e2); |
1891 printf("\tlwz %s,",crn); | |
1892 lvar(e2); | |
287 | 1893 code_cmp_register(reg,label,cond); |
89 | 1894 } |
1895 | |
1896 | |
1897 void | |
287 | 1898 code_cmp_register(int e2,int label,int cond) { |
221 | 1899 use_int(e2); |
291 | 1900 inc_cmpflag(); |
662 | 1901 printf("\tcmpwi %s,%s,0\n",crname(cmpflag),register_name(e2)); |
287 | 1902 jcond(label,cond); |
89 | 1903 } |
1904 | |
1905 | |
1906 void | |
107 | 1907 code_string(int e1,int creg) |
89 | 1908 { |
95 | 1909 int lb; |
711 | 1910 NMTBL *n = ncaddr(e1); |
560 | 1911 if ((lb=attr_value(n,LABEL))) { |
1912 // already defined | |
1913 return code_label_value(lb,creg) ; | |
1914 } | |
221 | 1915 |
1916 use_int(creg); | |
319 | 1917 lb = emit_string_label(); |
560 | 1918 ascii(n->nm); |
89 | 1919 if (output_mode==TEXT_EMIT_MODE) { |
1920 printf(".text\n"); | |
1921 } else { | |
516 | 1922 text_mode(0); |
89 | 1923 } |
660 | 1924 code_label_value(lb,creg); |
560 | 1925 set_attr(n,LABEL,lb); |
89 | 1926 } |
1927 | |
778
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1928 |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1929 void |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1930 emit_strings(NMTBL *n) |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1931 { |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1932 int l = emit_string_label(); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1933 int i; |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1934 for(i = n->dsp; i; i = cadr(i)) { |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1935 ascii(scaddr(i)); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1936 } |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1937 emit_label(l); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1938 } |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1939 |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1940 void |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1941 code_strings(int e2,int reg) |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1942 { |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1943 int l = emit_string_label(); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1944 int i; |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1945 for(i = e2; i; i = cadr(i)) { |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1946 ascii(scaddr(i)); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1947 } |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1948 if (output_mode==TEXT_EMIT_MODE) { |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1949 printf(".text\n"); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1950 } else { |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1951 text_mode(0); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1952 } |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1953 code_label_value(l,reg); |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1954 } |
a177c65f3e37
large string (STRINGS)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
739
diff
changeset
|
1955 |
89 | 1956 #define MAX_COPY_LEN 20 |
417 | 1957 // #define MAX_COPY_LEN 10 |
89 | 1958 |
211 | 1959 void |
89 | 1960 emit_copy(int from,int to,int length,int offset,int value,int det) |
1961 { | |
221 | 1962 char *frn; |
1963 char *trn; | |
89 | 1964 char *drn; |
125 | 1965 char *memmove = "memmove"; |
556 | 1966 int l; |
95 | 1967 int dreg = get_register(); if (!dreg) error(-1); |
221 | 1968 |
89 | 1969 drn = register_name(dreg); |
221 | 1970 use_int(from); |
1971 use_int(to); | |
1972 frn = register_name(from); | |
1973 trn = register_name(to); | |
89 | 1974 |
1975 /* length <0 means upward direction copy */ | |
1976 switch (length) { | |
1977 case 0: break; | |
1978 case 1: case -1: | |
1979 printf("\tlbz %s,%d(%s)\n",drn,offset,frn); | |
1980 printf("\tstb %s,%d(%s)\n",drn,offset,trn); | |
1981 break; | |
1982 case 2: case -2: | |
1983 printf("\tlhz %s,%d(%s)\n",drn,offset,frn); | |
1984 printf("\tsth %s,%d(%s)\n",drn,offset,trn); | |
1985 break; | |
1986 case 4: case -4: | |
1987 printf("\tlwz %s,%d(%s)\n",drn,offset,frn); | |
1988 printf("\tstw %s,%d(%s)\n",drn,offset,trn); | |
1989 break; | |
1990 default: | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1991 if (length <0) { |
416 | 1992 if (length >= -MAX_COPY_LEN) { |
583 | 1993 free_register(dreg); dreg = 0; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1994 for(;length<=-4;length+=4,offset-=4) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1995 emit_copy(from,to,-4,offset-4,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1996 for(;length<=-2;length+=2,offset-=2) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1997 emit_copy(from,to,-2,offset-2,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1998 if(length<0) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1999 emit_copy(from,to,length,offset-1,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2000 break; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2001 } |
89 | 2002 } else if (length <=MAX_COPY_LEN) { |
583 | 2003 free_register(dreg); dreg = 0; |
89 | 2004 for(;length>=4;length-=4,offset+=4) |
2005 emit_copy(from,to,4,offset,0,det); | |
2006 for(;length>=2;length-=2,offset+=2) | |
2007 emit_copy(from,to,2,offset,0,det); | |
2008 if(length>0) | |
2009 emit_copy(from,to,length,offset,0,det); | |
2010 break; | |
2011 } | |
125 | 2012 clear_ptr_cache(); |
2013 code_save_stacks(); | |
556 | 2014 |
2015 l = list3(3,0,to); | |
2016 l = list3(4,l,from); | |
2017 parallel_rassign(l); | |
2018 | |
660 | 2019 #ifdef __APPLE__ |
416 | 2020 printf("\tli r5,%d\n",length>0?length:-length); |
417 | 2021 /* offset should be ignored */ |
125 | 2022 /* overrap must be allowed */ |
2023 printf("\tbl L_%s$stub\n",memmove); | |
660 | 2024 #else |
2025 printf("\tli 5,%d\n",length>0?length:-length); | |
2026 /* offset should be ignored */ | |
2027 /* overrap must be allowed */ | |
2028 printf("\tbl %s\n",memmove); | |
2029 #endif | |
125 | 2030 extern_define(memmove,0,FUNCTION,1); |
207 | 2031 set_ireg(RET_REGISTER,0); |
554 | 2032 //if (creg!=to) { |
2033 // free_register(to); to = creg; | |
2034 //} | |
125 | 2035 break; |
89 | 2036 } |
2037 if (value) { | |
2038 /* creg must point top of the destination data */ | |
2039 /* this code is necessary for the value of assignment or function call */ | |
2040 /* otherwise we don't need this */ | |
2041 if(creg!=to) { | |
554 | 2042 free_register(to); |
2043 // set_ireg(to,1); | |
89 | 2044 } |
2045 } | |
583 | 2046 if (dreg) free_register(dreg); |
89 | 2047 } |
2048 | |
2049 int | |
444 | 2050 push_struct(int e4,int t,int arg) |
89 | 2051 { |
95 | 2052 int length,count; |
119 | 2053 int dreg,sreg; char *drn,*crn,*srn; |
89 | 2054 g_expr(e4); |
221 | 2055 if (!is_int_reg(creg)) error(-1); |
89 | 2056 length=size(t); |
245 | 2057 if(length%SIZE_OF_INT) { |
2058 length += SIZE_OF_INT - (length%SIZE_OF_INT); | |
89 | 2059 } |
95 | 2060 dreg = get_register(); if (!dreg) error(-1); |
89 | 2061 drn = register_name(dreg); |
119 | 2062 crn = register_name(creg); |
125 | 2063 if (length<MAX_COPY_LEN) { |
2064 sreg = get_register(); if (!sreg) error(-1); | |
2065 srn = register_name(sreg); | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2066 code_lvar(cadr(arg),dreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2067 for(count=0;count<length;count+=SIZE_OF_INT) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2068 printf("\tlwz %s,%d(%s)\n",srn,count,crn); |
655 | 2069 printf("\tstw %s,%d(%s)\n",srn,count,drn); |
89 | 2070 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2071 free_register(sreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2072 free_register(dreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2073 return length/SIZE_OF_INT; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2074 } else { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2075 code_lvar(cadr(arg),dreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2076 /* downward direction copy */ |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2077 emit_copy(creg,dreg,length,0,0,1); |
89 | 2078 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2079 free_register(dreg); |
245 | 2080 return length/SIZE_OF_INT; |
89 | 2081 } |
2082 | |
655 | 2083 static void |
207 | 2084 set_ireg(int reg,int mode) |
104 | 2085 { |
207 | 2086 if (!is_int_reg(reg)) error(-1); |
104 | 2087 if (reg!=creg) { |
111 | 2088 clear_ptr_cache_reg(reg); |
208 | 2089 if (ireg && reg!=ireg ) { |
2090 free_register(ireg); | |
2091 if (mode) { | |
2092 printf("\tmr %s,%s\n",register_name(reg),register_name(ireg)); | |
2093 } | |
206 | 2094 } |
104 | 2095 free_register(creg); |
536 | 2096 if (creg==lreg) lreg = 0; |
208 | 2097 regs[reg]=USING_REG; |
104 | 2098 } |
206 | 2099 creg = ireg = reg; |
104 | 2100 } |
2101 | |
655 | 2102 static void |
104 | 2103 set_freg(int reg,int mode) |
2104 { | |
207 | 2105 if (!is_float_reg(reg)) error(-1); |
147 | 2106 if (reg!=creg) { |
222 | 2107 if (freg && reg!=freg) { |
208 | 2108 free_register(freg); |
2109 if (mode) { | |
2110 printf("\tfmr %s,%s\n",fregister_name(reg),fregister_name(freg)); | |
2111 } | |
147 | 2112 } |
222 | 2113 // if (creg!=ireg) free_register(creg); |
208 | 2114 regs[reg]=USING_REG; |
104 | 2115 } |
206 | 2116 creg = freg = reg; |
195 | 2117 } |
2118 | |
655 | 2119 static void |
195 | 2120 set_lreg(int reg,int mode) |
2121 { | |
222 | 2122 if (reg==RET_LREGISTER) { |
2123 regv_l(reg) = RET_LREGISTER_L; | |
2124 regv_h(reg) = RET_LREGISTER_H; | |
2125 } | |
207 | 2126 if (!is_longlong_reg(reg)) error(-1); |
206 | 2127 if (reg!=creg) { |
530 | 2128 if (lreg) { |
2129 if (reg!=lreg) { | |
2130 if (mode) { | |
2131 printf("\tmr %s,%s\n", | |
2132 lregister_name_low(reg),lregister_name_low(lreg)); | |
2133 printf("\tmr %s,%s\n", | |
2134 lregister_name_high(reg),lregister_name_high(lreg)); | |
2135 } | |
2136 free_register(lreg); | |
208 | 2137 } |
530 | 2138 if (lreg==creg) creg=0; |
206 | 2139 } |
530 | 2140 if (creg) free_register(creg); |
207 | 2141 regs[reg]=USING_REG; |
222 | 2142 clear_ptr_cache_reg(regv_l(reg)); |
207 | 2143 regs[regv_l(reg)]=USING_REG; |
222 | 2144 clear_ptr_cache_reg(regv_h(reg)); |
207 | 2145 regs[regv_h(reg)]=USING_REG; |
530 | 2146 creg = lreg = reg; |
206 | 2147 } |
104 | 2148 } |
2149 | |
655 | 2150 static void |
217 | 2151 set_lreg_operand(int reg,int mode) |
216 | 2152 { |
326 | 2153 // save_stack,clear_ptr_cache is assumed |
217 | 2154 if (!is_longlong_reg(reg)) { error(-1); return; } |
2155 if (mode) { | |
255 | 2156 if (regv_l(reg)!=3) |
660 | 2157 printf("\tmr %s,%s\n", register_name(3),lregister_name_high(reg)); |
255 | 2158 if (regv_l(reg)!=4) |
660 | 2159 printf("\tmr %s,%s\n", register_name(4),lregister_name_low(reg)); |
255 | 2160 } |
2161 } | |
2162 | |
655 | 2163 static void |
255 | 2164 set_lreg_operand1(int reg,int mode) |
2165 { | |
326 | 2166 // save_stack,clear_ptr_cache is assumed |
255 | 2167 if (!is_longlong_reg(reg)) { error(-1); return; } |
2168 if (mode) { | |
217 | 2169 if (regv_l(reg)!=5) |
660 | 2170 printf("\tmr %s,%s\n", register_name(5),lregister_name_high(reg)); |
217 | 2171 if (regv_l(reg)!=6) |
660 | 2172 printf("\tmr %s,%s\n", register_name(6),lregister_name_low(reg)); |
217 | 2173 } |
216 | 2174 } |
2175 | |
655 | 2176 static void |
207 | 2177 use_reg(int arg) |
104 | 2178 { |
468 | 2179 // printf("## use reg %d\n",arg); |
208 | 2180 if (arg<0||arg> REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ REAL_MAX_LREGISTER) |
2181 error(-1); | |
223 | 2182 clear_ptr_cache_reg(arg); |
207 | 2183 regs[arg]=USING_REG; |
2184 if (is_longlong_reg(arg)) { | |
228 | 2185 clear_ptr_cache_reg(regv_l(arg)); |
207 | 2186 regs[regv_l(arg)]=USING_REG; |
228 | 2187 clear_ptr_cache_reg(regv_h(arg)); |
207 | 2188 regs[regv_h(arg)]=USING_REG; |
206 | 2189 } |
104 | 2190 } |
2191 | |
676 | 2192 /* |
2193 store input argument into stack | |
2194 we need this always because of one path compiler | |
2195 */ | |
655 | 2196 static void |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2197 code_save_input_registers(int dots) |
105 | 2198 { |
119 | 2199 int args; |
2200 NMTBL *n; | |
2201 int reg; | |
2202 int tag; | |
676 | 2203 // int lvar; |
119 | 2204 int t; |
2205 /* fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); */ | |
2206 int reg_offset = 0; | |
2207 int offset = 0; | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2208 int reg_var = 0; |
119 | 2209 |
2210 for(args = fnptr->dsp;args;args = cadr(args)) { | |
712 | 2211 n = ncadddr(args); |
119 | 2212 tag = n->sc; |
2213 reg = n->dsp; | |
2214 if (!n||n==&null_nptr) error(REG_ERR); | |
2215 if (tag==REGISTER) { | |
2216 n->dsp = offset; | |
245 | 2217 offset+=SIZE_OF_INT; |
119 | 2218 t = INT; |
2219 reg += reg_offset; /* for duplicated floating point argument */ | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2220 reg_var++; |
119 | 2221 } else if (tag==DREGISTER) { |
2222 n->dsp = offset; | |
120 | 2223 t = n->ty; |
672 | 2224 #ifdef __APPLE__ |
245 | 2225 if(t==FLOAT) { offset+=SIZE_OF_FLOAT; reg_offset+=1; } |
2226 else if(t==DOUBLE) { offset+=SIZE_OF_DOUBLE; reg_offset+=2; } | |
120 | 2227 else error(-1); |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2228 reg_var += 2; |
672 | 2229 #else |
2230 if(t==FLOAT) { offset+=SIZE_OF_FLOAT; } | |
2231 else if(t==DOUBLE) { offset+=SIZE_OF_DOUBLE; } | |
2232 else error(-1); | |
2233 #endif | |
206 | 2234 } else if (tag==LREGISTER) { |
2235 n->dsp = offset; | |
2236 t = n->ty; | |
672 | 2237 offset+=SIZE_OF_LONGLONG; |
2238 reg_offset+=2; | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2239 reg_var += 2; |
122 | 2240 } else { |
534 | 2241 // n->dsp = offset; this is no allowed becase of arg reorder |
122 | 2242 offset += size(n->ty); |
119 | 2243 continue; |
122 | 2244 } |
119 | 2245 n->sc = LVAR; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2246 g_expr_u(assign_expr0( |
712 | 2247 list3n(LVAR,n->dsp,0),list3n(tag,reg,n),n->ty,t)); |
206 | 2248 if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) { |
119 | 2249 free_register(reg); |
2250 } | |
2251 } | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2252 if (dots) { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2253 while ((reg = get_input_register_var(reg_var,0,0))) { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2254 g_expr_u(assign_expr0( |
711 | 2255 list3n(LVAR,offset,0),reg,INT,INT)); |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2256 offset+=SIZE_OF_INT; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2257 reg_var++; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2258 } |
673 | 2259 #ifndef __APPLE__ |
2260 int skip = fwdlabel(); | |
2261 int freg_var = 0; | |
2262 printf("\tbne 1,%s%d\n",lpfx,skip); | |
2263 while ((reg = get_input_dregister_var(freg_var,0,0,1))) { | |
2264 g_expr_u(assign_expr0( | |
711 | 2265 list3n(LVAR,offset,0),reg,DOUBLE,DOUBLE)); |
673 | 2266 offset+=SIZE_OF_DOUBLE; |
2267 freg_var++; | |
2268 } | |
2269 fwddef(skip); | |
2270 #endif | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2271 } |
121 | 2272 my_func_args = offset; |
105 | 2273 } |
2274 | |
449 | 2275 int |
228 | 2276 not_simple_p(int e3) |
223 | 2277 { |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2278 switch (e3) { |
456 | 2279 case FUNCTION: case CONV: case LCALL: case STASS: |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2280 case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2281 case LDIV: case LUDIV: case LMOD: case LUMOD: case LASSOP: case ALLOCA: |
456 | 2282 case INLINE: |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2283 return 1; |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2284 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
2285 return 0; |
223 | 2286 } |
2287 | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2288 static int |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2289 simple_arg(int e3) |
108 | 2290 { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2291 return !contains_p(e3,not_simple_p); |
108 | 2292 } |
2293 | |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
2294 #define caller_arg_offset_v(arg) (ARG_LVAR_OFFSET+(arg)*SIZE_OF_INT) |
111 | 2295 |
715 | 2296 /* |
2297 use input register as current register | |
724 | 2298 なんで、こんなに複雑なんだ? |
2299 むしろ、INPUT_REG みたいな mark をいれたら? | |
715 | 2300 */ |
2301 | |
655 | 2302 static void |
233 | 2303 use_input_reg(int reg,int mode) |
2304 { | |
2305 if (is_int_reg(reg)) { | |
2306 if (ireg&® == ireg) { | |
2307 if (creg==ireg) creg = 0; | |
2308 ireg = 0; | |
2309 } | |
2310 if (lreg) { | |
724 | 2311 // free_regsiter(lreg) でいいんじゃないの? |
233 | 2312 if (regv_l(lreg)==reg) { |
2313 regs[lreg]=0; | |
2314 if (regv_h(lreg)>reg&®s[regv_h(lreg)]==USING_REG) { | |
2315 free_register(regv_h(lreg)); | |
2316 } | |
529 | 2317 if (creg==lreg) creg = ireg; |
431 | 2318 free_register(lreg); |
233 | 2319 lreg = 0; |
2320 } else if (regv_h(lreg)==reg) { | |
2321 regs[lreg]=0; | |
2322 if (regv_h(lreg)>reg&®s[regv_l(lreg)]==USING_REG) { | |
2323 free_register(regv_l(lreg)); | |
2324 } | |
529 | 2325 if (creg==lreg) creg = ireg; |
431 | 2326 free_register(lreg); |
233 | 2327 lreg = 0; |
2328 } | |
2329 } | |
2330 } else if (is_longlong_reg(reg)) { | |
709 | 2331 use_input_reg(regv_h(reg),mode); |
2332 use_input_reg(regv_l(reg),mode); | |
233 | 2333 } else if (is_float_reg(reg)) { |
2334 if (freg&® == freg) { | |
529 | 2335 if (creg==freg) creg = ireg; |
233 | 2336 freg = 0; |
2337 } | |
2338 } | |
2339 if (mode) use_reg(reg); | |
2340 } | |
2341 | |
271 | 2342 static int |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2343 compute_complex_arg(int e3,int reg_arg_list,int arg) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2344 int t=caddr(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2345 int e4 = car(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2346 reg_arg_list = list2(arg,reg_arg_list); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2347 if (car(arg)==REGISTER||car(arg)==DREGISTER|| |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2348 car(arg)==FREGISTER||car(arg)==LREGISTER) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2349 use_input_reg(cadr(arg),1); |
709 | 2350 g_expr_u(assign_expr0(arg,e4,t,t)); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2351 car(e3) = arg; |
271 | 2352 return reg_arg_list; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2353 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2354 |
667 | 2355 |
2356 #ifdef __APPLE__ | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2357 static void |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2358 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2359 int nargs=0,reg_arg=0,freg_arg=0; |
487 | 2360 int t=type_value(caddr(e3)); |
331 | 2361 if (t>=0&&(car(t)==BIT_FIELD)) { |
487 | 2362 t = type_value(cadr(t)); |
331 | 2363 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2364 if(scalar(t)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2365 nargs ++ ; reg_arg++; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2366 } else if (t==LONGLONG||t==ULONGLONG) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2367 nargs ++ ; reg_arg++; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2368 nargs ++ ; reg_arg++; |
475 | 2369 } else if (t==FLOAT) { |
2370 if (*preg_arg<MAX_INPUT_REGISTER_VAR) { | |
2371 reg_arg += 1; | |
2372 } | |
2373 freg_arg++; | |
2374 nargs += size(t)/SIZE_OF_INT; | |
2375 } else if (t==DOUBLE) { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2376 if (*preg_arg<MAX_INPUT_REGISTER_VAR) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2377 reg_arg += 2; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2378 } |
667 | 2379 nargs += size(t)/SIZE_OF_INT; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2380 freg_arg++; |
638 | 2381 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2382 nargs += round4(size(t))/SIZE_OF_INT; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2383 } else { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2384 error(TYERR); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2385 nargs ++ ; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2386 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2387 *pnargs += nargs; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2388 *preg_arg += reg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2389 *pfreg_arg += freg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2390 } |
667 | 2391 #else |
2392 static void | |
2393 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) { | |
2394 int nargs=0,reg_arg=0,freg_arg=0; | |
2395 int t=type_value(caddr(e3)); | |
2396 if (t>=0&&(car(t)==BIT_FIELD)) { | |
2397 t = type_value(cadr(t)); | |
2398 } | |
2399 if(scalar(t)) { | |
672 | 2400 reg_arg++; |
2401 if (*preg_arg>=MAX_INPUT_REGISTER_VAR) nargs ++ ; | |
667 | 2402 } else if (t==LONGLONG||t==ULONGLONG) { |
672 | 2403 if (*preg_arg%2==1) reg_arg++; // alignment |
2404 if (*pnargs%2==1) nargs++; // alignment | |
2405 reg_arg++; reg_arg++; | |
2406 if (*preg_arg+1>=MAX_INPUT_REGISTER_VAR) nargs += 2; | |
667 | 2407 } else if (t==FLOAT) { |
2408 freg_arg++; | |
672 | 2409 if (*pfreg_arg>=MAX_INPUT_DREGISTER_VAR) nargs += size(t)/SIZE_OF_INT; |
667 | 2410 } else if (t==DOUBLE) { |
2411 freg_arg++; | |
672 | 2412 if (*pfreg_arg>=MAX_INPUT_DREGISTER_VAR) nargs += round4(size(t))/SIZE_OF_INT; |
667 | 2413 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
2414 nargs += round4(size(t))/SIZE_OF_INT; | |
2415 } else { | |
2416 error(TYERR); | |
2417 nargs ++ ; | |
2418 } | |
2419 *pnargs += nargs; | |
2420 *preg_arg += reg_arg; | |
2421 *pfreg_arg += freg_arg; | |
2422 } | |
2423 #endif | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2424 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2425 #define AS_SAVE 1 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2426 #define AS_ARG 0 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2427 |
676 | 2428 /* |
2429 set storage type of caller's arguments | |
2430 register or stack | |
2431 this muse corprate with code_arg_register(); | |
2432 if AS_SAVE is set, register variable (or temporary local variable) | |
2433 is used. | |
2434 */ | |
2435 | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2436 static int |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2437 get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2438 { |
487 | 2439 t = type_value(t); |
331 | 2440 if (t>=0&&(car(t)==BIT_FIELD)) { |
487 | 2441 t = type_value(cadr(t)); |
331 | 2442 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2443 if(scalar(t)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2444 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2445 return get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2446 } else if (reg_arg>=MAX_INPUT_REGISTER_VAR) { |
711 | 2447 return list3n(LVAR,caller_arg_offset_v(nargs),0); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2448 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2449 return get_input_register_var(reg_arg,0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2450 } else if (t==LONGLONG||t==ULONGLONG) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2451 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2452 return get_lregister_var(0); |
259 | 2453 } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) { |
711 | 2454 return list3n(LVAR,caller_arg_offset_v(nargs),0); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2455 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2456 return get_input_lregister_var(reg_arg,0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2457 } else if (t==FLOAT) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2458 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2459 return get_dregister_var(0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2460 } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { |
711 | 2461 return list3n(LVAR,caller_arg_offset_v(nargs),0); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2462 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2463 return get_input_dregister_var(freg_arg,0,0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2464 } else if (t==DOUBLE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2465 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2466 return get_dregister_var(0,1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2467 } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { |
711 | 2468 return list3n(LVAR,caller_arg_offset_v(nargs),0); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2469 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2470 return get_input_dregister_var(freg_arg,0,0,1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2471 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2472 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2473 return get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2474 } else |
711 | 2475 return list3n(LVAR,caller_arg_offset_v(nargs),0); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2476 } else { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2477 error(-1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2478 return get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2479 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2480 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2481 |
108 | 2482 int |
89 | 2483 function(int e1) |
2484 { | |
667 | 2485 int e2,e3,e4,e5,nargs,t,r0; |
104 | 2486 int arg,reg_arg,freg_arg,arg_assign; |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
2487 int dots; |
111 | 2488 int reg_arg_list=0,ret_type,special_lvar; |
127 | 2489 NMTBL *fn = 0; |
108 | 2490 int jmp = 0; |
2491 char *jrn; | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2492 int complex_; |
569 | 2493 int pnargs=0,preg_arg=0,pfreg_arg=0; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2494 int stargs; |
95 | 2495 |
111 | 2496 special_lvar = -1; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
2497 ret_type = function_type(cadddr(e1),&dots); |
313 | 2498 if (caddr(cadddr(e1))==0) dots=1; |
108 | 2499 |
285 | 2500 arg_assign = 0; |
108 | 2501 e2 = cadr(e1); |
2502 if (car(e2) == FNAME) { | |
711 | 2503 fn=ncaddr(e2); |
108 | 2504 } else { |
285 | 2505 if (car(e2)==INDIRECT) e2=cadr(e2); // (*func)(i) case |
2506 jmp = get_register_var(0); | |
2507 if (car(jmp)!=REGISTER) error(-1); | |
2508 reg_arg_list = list2(jmp,reg_arg_list); | |
2509 if (!simple_arg(e2)) { | |
2510 g_expr_u(assign_expr0(jmp,e2,INT,INT)); | |
2511 } else | |
2512 arg_assign = list2(assign_expr0(jmp,e2,INT,INT),arg_assign); | |
108 | 2513 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2514 /* first we execute complex argument to avoid interaction with |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2515 input variables */ |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2516 stargs = 0; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2517 complex_ = 0; |
259 | 2518 nargs = reg_arg = freg_arg = 0; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2519 for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2520 t=caddr(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2521 if ((e5= !simple_arg(car(e3)))) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2522 if (complex_) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2523 arg = get_input_arg(caddr(complex_),AS_SAVE, |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2524 pnargs,preg_arg,pfreg_arg); |
271 | 2525 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2526 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2527 pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2528 complex_ = e3; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2529 } |
638 | 2530 if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2531 // The struct should be pushed after complex arguments. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2532 if (e5) { // compute address only, complex_ is me now. Clear it. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2533 complex_ = 0; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2534 e4 = car(e3); |
693 | 2535 if (car(e4)==RSTRUCT) e4 = cadr(e4); |
784 | 2536 else if (car(e4)==INDIRECT) e4 = cadr(e4); |
693 | 2537 if (!simple_arg(e4)) { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2538 // Calculate complex struct address here. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2539 // If simple, leave it. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2540 arg = get_register_var(0); |
693 | 2541 g_expr_u(assign_expr0(arg,e4,INT,INT)); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2542 car(e3)=arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2543 reg_arg_list = list2(arg,reg_arg_list); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2544 if (car(arg)==REGISTER) use_input_reg(cadr(arg),1); |
408 | 2545 else car(e3) = rvalue_t(arg,INT); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2546 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2547 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2548 stargs = list4(e3,stargs,nargs,reg_arg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2549 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2550 increment_function_arg(e3,&nargs,®_arg,&freg_arg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2551 } |
108 | 2552 |
99 | 2553 /* now all input register vars are free */ |
108 | 2554 code_save_stacks(); |
222 | 2555 // set_lreg(LREG_LREGISTER,0); |
221 | 2556 set_freg(FREG_FREGISTER,0); |
207 | 2557 set_ireg(CREG_REGISTER,0); |
108 | 2558 |
268 | 2559 // Struct arguments need emit_copy. it destructs 3 input registers. |
326 | 2560 // But it returns no value on a register. So calculate it here. |
268 | 2561 // We cannot do this in the previous loop, because the copied struct may be |
326 | 2562 // override by other complex arguments. But before this we have to check |
268 | 2563 // complex_. |
2564 | |
2565 if (stargs) { | |
2566 if (complex_) { | |
2567 arg = get_input_arg(caddr(complex_),AS_SAVE, | |
2568 pnargs,preg_arg,pfreg_arg); | |
271 | 2569 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); |
268 | 2570 } |
2571 for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) { | |
2572 e3 = car(stargs); | |
2573 e4 = car(e3); | |
2574 t = caddr(e3); | |
2575 arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0); | |
444 | 2576 push_struct(e4,t,arg); |
268 | 2577 car(e3)=0; // done |
2578 } | |
2579 } else { | |
2580 // last complex argument can use input register | |
2581 if (complex_) { | |
2582 arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg); | |
271 | 2583 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); |
268 | 2584 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2585 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2586 |
285 | 2587 nargs = reg_arg = freg_arg = 0; |
268 | 2588 // calc stack arguments first, it may requires extra registers, |
2589 // and we can still use input registers now. | |
259 | 2590 for (e3 = e1; e3; |
2591 increment_function_arg(e3,&nargs,®_arg,&freg_arg), | |
2592 e3 = cadr(e3)) { | |
2593 if (!(e4=car(e3))) continue; | |
2594 t=caddr(e3); | |
2595 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); | |
2596 if (car(arg)!=LVAR) continue; | |
2597 g_expr_u(assign_expr0(arg,e4,t,t)); | |
2598 if (t==LONGLONG||t==ULONGLONG) { | |
2599 if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { | |
2600 // half register, half memory case | |
2601 arg_assign = list2( | |
2602 assign_expr0(r0=get_input_register_var(reg_arg,0,0), | |
2603 arg,INT,INT), | |
2604 arg_assign); | |
2605 use_input_reg(cadr(r0),1); | |
2606 } | |
2607 } | |
2608 car(e3)=0; // done | |
2609 } | |
2610 nargs = reg_arg = freg_arg = 0; | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2611 for (e3 = e1; e3; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2612 increment_function_arg(e3,&nargs,®_arg,&freg_arg), |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2613 e3 = cadr(e3)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2614 if (!(e4=car(e3))) continue; |
487 | 2615 t=type_value(caddr(e3)); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2616 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); |
89 | 2617 if(scalar(t)) { |
99 | 2618 reg_arg_list = list2(arg,reg_arg_list); |
233 | 2619 /* protect from input register free */ |
2620 if (car(arg)==REGISTER) | |
2621 use_input_reg(cadr(arg),1); | |
99 | 2622 g_expr_u(assign_expr0(arg,e4,t,t)); |
202 | 2623 } else if (t==LONGLONG||t==ULONGLONG) { |
259 | 2624 if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { |
227 | 2625 // half register, half memory case |
2626 // put whole long long anyway | |
2627 arg_assign = list2( | |
232 | 2628 assign_expr0(r0=get_input_register_var(reg_arg,0,0), |
227 | 2629 arg,INT,INT), |
2630 arg_assign); | |
233 | 2631 use_input_reg(cadr(r0),1); |
530 | 2632 reg_arg_list = list2(r0,reg_arg_list); |
206 | 2633 } else { |
530 | 2634 if (car(arg)==LREGISTER) { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2635 use_input_reg(cadr(arg),1); |
530 | 2636 } |
206 | 2637 } |
2638 reg_arg_list = list2(arg,reg_arg_list); | |
2639 g_expr_u(assign_expr0(arg,e4,t,t)); | |
89 | 2640 } else if (t==DOUBLE||t==FLOAT) { |
667 | 2641 #ifdef __APPLE__ |
137 | 2642 if (reg_arg<MAX_INPUT_REGISTER_VAR) { |
119 | 2643 /* sigh... |
326 | 2644 printf requires floating value in integer registers |
119 | 2645 */ |
137 | 2646 if (dots) { |
667 | 2647 int r1; |
137 | 2648 if (car(e4)==DRLVAR) { |
2649 special_lvar = cadr(e4); | |
711 | 2650 e5 = list3n(LVAR,special_lvar,0); |
137 | 2651 } else { |
245 | 2652 special_lvar = new_lvar(SIZE_OF_DOUBLE); |
137 | 2653 g_expr(assign_expr0( |
711 | 2654 (e5=list3n(LVAR,special_lvar,0)),e4,DOUBLE,t)); |
137 | 2655 reg_arg_list = list2(e5,reg_arg_list); |
2656 e4 = list2(DREGISTER,freg); | |
2657 /* freg should not change until XXX */ | |
2658 } | |
2659 r0=get_input_register_var(reg_arg,0,0); | |
2660 r1 = reg_arg+1+MIN_TMP_REG; | |
206 | 2661 if (regs[r1]==PTRC_REG) |
2662 clear_ptr_cache_reg(list2(REGISTER,r1)); | |
137 | 2663 /* else if (regs[r1]) error(-1); */ |
2664 r1=get_input_register_var_1(reg_arg+1,0,0); | |
233 | 2665 use_input_reg(cadr(r0),1); /* protect from input register free */ |
2666 use_input_reg(cadr(r1),1); /* protect from input register free */ | |
137 | 2667 reg_arg_list = list2(r0,reg_arg_list); |
2668 reg_arg_list = list2(r1,reg_arg_list); | |
2669 arg_assign = list2( assign_expr0(r0,e5,INT,INT), arg_assign); | |
2670 arg_assign = list2( assign_expr0(r1, | |
711 | 2671 list3n(LVAR,special_lvar+SIZE_OF_INT,0), |
137 | 2672 INT,INT), arg_assign); |
111 | 2673 } |
2674 } | |
498 | 2675 if (dots && (freg_arg*8+reg_arg*4)>=32 && freg_arg<MAX_INPUT_DREGISTER_VAR) { |
496 | 2676 /* |
326 | 2677 it requires integer register and floating register and |
496 | 2678 stack value. |
119 | 2679 */ |
2680 arg_assign = list2( | |
711 | 2681 assign_expr0(list3n(LVAR,caller_arg_offset_v(nargs),0), |
138 | 2682 get_input_dregister_var(freg_arg,0,0,1),t,t), |
119 | 2683 arg_assign); |
2684 } | |
667 | 2685 #endif |
233 | 2686 reg_arg_list = list2(arg,reg_arg_list); |
208 | 2687 if (car(arg)==DREGISTER) |
233 | 2688 use_input_reg(cadr(arg),1); /* protect from input register free */ |
118 | 2689 g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ |
89 | 2690 } |
259 | 2691 // structs are finished |
89 | 2692 } |
116 | 2693 if (max_func_args<nargs) max_func_args=nargs; |
104 | 2694 for(;arg_assign;arg_assign=cadr(arg_assign)) { |
2695 g_expr_u(car(arg_assign)); | |
2696 } | |
96 | 2697 clear_ptr_cache(); |
667 | 2698 #ifndef __APPLE__ |
673 | 2699 if (dots) { |
2700 if (freg_arg) { | |
667 | 2701 // variadic function has floating value in register |
673 | 2702 printf("\tcreqv 6,6,6\n"); |
2703 } else { | |
2704 // printf("\tcrxor 6,6,6\n"); // for value in stack | |
2705 } | |
667 | 2706 } |
2707 #endif | |
89 | 2708 if (car(e2) == FNAME) { |
660 | 2709 #ifdef __APPLE__ |
108 | 2710 printf("\tbl\tL_%s$stub\n",fn->nm); |
660 | 2711 #else |
2712 printf("\tbl\t%s\n",fn->nm); | |
2713 #endif | |
89 | 2714 } else { |
108 | 2715 jrn = register_name(cadr(jmp)); |
89 | 2716 printf("\tmtctr %s\n",jrn); |
2717 printf("\tbctrl\n"); | |
2718 } | |
716 | 2719 free_register_var(reg_arg_list); |
105 | 2720 if (ret_type==DOUBLE||ret_type==FLOAT) { |
104 | 2721 set_freg(RET_FREGISTER,0); |
206 | 2722 } else if (ret_type==ULONGLONG||ret_type==LONGLONG) { |
2723 set_lreg(RET_LREGISTER,0); | |
207 | 2724 use_reg(RET_LREGISTER); |
105 | 2725 } else if (ret_type==VOID) { |
96 | 2726 } else { |
207 | 2727 set_ireg(RET_REGISTER,0); |
96 | 2728 } |
530 | 2729 cleanup_lregister0(); |
105 | 2730 return ret_type; |
89 | 2731 } |
2732 | |
2733 void | |
313 | 2734 code_alloca(int e1,int reg) |
2735 { | |
2736 char *crn,*grn; | |
2737 int g; | |
672 | 2738 |
2739 if (!is_const(e1)) { | |
2740 g_expr(list3(BAND,list3(ADD,e1,list2(CONST,15)),list2(CONST,~15))); | |
2741 use_int(reg); | |
2742 } else { | |
2743 use_int(reg); | |
2744 code_const(round16(cadr(e1)),reg); | |
2745 } | |
313 | 2746 use_int(reg); |
2747 g = get_register(); | |
2748 crn = register_name(reg); | |
2749 grn = register_name(g); | |
2750 // printf("\trlwinm r0,%s,0,0,27\n",crn); | |
672 | 2751 #ifdef R1SAVE |
660 | 2752 printf("\tlwz %s,0(%s)\n",grn,register_name(1)); |
313 | 2753 printf("\tneg %s,%s\n",crn,crn); |
660 | 2754 printf("\tstwux %s,%s,%s\n",grn,register_name(1),crn); |
672 | 2755 #else |
2756 printf("\tlwz %s,0(%s)\n",grn,register_name(1)); | |
2757 printf("\tneg %s,%s\n",crn,crn); | |
2758 printf("\tstwux %s,%s,%s\n",grn,register_name(1),crn); | |
2759 #endif | |
313 | 2760 // printf("\tstw %s,0(r1)\n",grn); |
2761 if (!max_func_arg_label) max_func_arg_label = fwdlabel(); | |
660 | 2762 #ifdef __APPLE__ |
313 | 2763 printf("\taddis r1,r1,ha16(L_%d)\n",max_func_arg_label); |
2764 printf("\taddi %s,r1,lo16(L_%d)\n",crn,max_func_arg_label); | |
660 | 2765 #else |
2766 printf("\taddis 1,1,.LC%d@ha\n",max_func_arg_label); | |
2767 printf("\taddi %s,1,.LC%d@l\n",crn,max_func_arg_label); | |
2768 #endif | |
313 | 2769 free_register(g); |
2770 } | |
2771 | |
2772 void | |
89 | 2773 code_frame_pointer(int e3) { |
221 | 2774 use_int(e3); |
128 | 2775 #if R1SAVE |
660 | 2776 printf("\tmr %s,%s\n",register_name(1),register_name(e3)); |
128 | 2777 #else |
667 | 2778 printf("\tmr %s,%s\n",register_name(REG_fp),register_name(e3)); |
128 | 2779 #endif |
89 | 2780 } |
2781 | |
577 | 2782 int |
2783 code_frame_pointer_register() | |
2784 { | |
2785 return list2(REGISTER,REG_fp); | |
2786 } | |
89 | 2787 |
2788 void | |
2789 code_fix_frame_pointer(int disp_offset) { | |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
2790 #if 0 |
128 | 2791 printf("\tla r30,"); |
578
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
2792 printf("lo16(%d)(r30)\n",FUNC_LVAR(0)-CODE_LVAR(0)); |
dbde3b869a0f
try to remove code_fix_frame_pointer(); PowerPC fixed.
kono
parents:
577
diff
changeset
|
2793 #endif |
89 | 2794 } |
2795 | |
2796 void | |
2797 code_jmp(char *s) { | |
128 | 2798 max_reg_var = REG_VAR_BASE-REG_VAR_MIN; |
2799 max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; | |
660 | 2800 #ifdef __APPLE__ |
89 | 2801 printf("\tb L_%s$stub\n",s); |
660 | 2802 #else |
2803 printf("\tb %s\n",s); | |
2804 #endif | |
283 | 2805 control=0; |
89 | 2806 } |
2807 | |
2808 | |
2809 void | |
2810 code_indirect_jmp(int e2) { | |
128 | 2811 max_reg_var = REG_VAR_BASE-REG_VAR_MIN; |
2812 max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; | |
221 | 2813 use_int(e2); |
89 | 2814 printf("\tmtctr %s\n",register_name(e2)); |
2815 printf("\tbctr\n"); | |
283 | 2816 control=0; |
89 | 2817 } |
2818 | |
660 | 2819 static void |
2820 code_add_op(char *op, char *crn, int offset, char *rrn) | |
2821 { | |
2822 #ifdef __APPLE__ | |
2823 if (LARGE_OFFSET(offset)) { | |
2824 printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset); | |
2825 } | |
662 | 2826 printf("\t%s %s,lo16(%d)(%s)\n",op,crn,offset,rrn); |
660 | 2827 #else |
2828 if (LARGE_OFFSET(offset)) { | |
2829 printf("\taddis %s,%s,%d@ha\n",crn,crn,offset); | |
2830 } | |
662 | 2831 printf("\t%s %s,%d@l(%s)\n",op,crn,offset,rrn); |
660 | 2832 #endif |
2833 } | |
2834 | |
355 | 2835 void |
2836 code_rindirect(int e1, int reg,int offset, int sign,int sz) | |
196 | 2837 { |
221 | 2838 char *crn,*rrn; |
196 | 2839 g_expr(e1); |
221 | 2840 if (!is_int_reg(creg)) error(-1); |
196 | 2841 crn=register_name(creg); |
221 | 2842 use_int(reg); |
2843 rrn=register_name(reg); | |
660 | 2844 code_add_op(cload(sz),rrn,offset,crn); |
355 | 2845 cext(sign,sz,reg); |
89 | 2846 } |
2847 | |
196 | 2848 #if FLOAT_CODE |
2849 int | |
221 | 2850 code_drindirect(int e1, int reg,int offset, int d) |
196 | 2851 { |
2852 char *crn; | |
2853 g_expr(e1); | |
221 | 2854 if (!is_int_reg(creg)) error(-1); |
196 | 2855 crn=register_name(creg); |
221 | 2856 use_float(d,reg); |
660 | 2857 code_add_op(fload(d),fregister_name(reg),offset,crn); |
375 | 2858 |
206 | 2859 return d?DOUBLE:FLOAT; |
196 | 2860 } |
2861 #endif | |
2862 | |
440 | 2863 #if LONGLONG_CODE |
660 | 2864 |
2865 | |
269 | 2866 static void |
2867 lload(int creg,int reg,int offset) | |
2868 { | |
2869 char *crn = register_name(creg); | |
660 | 2870 #ifdef __APPLE__ |
375 | 2871 if (LARGE_OFFSET(offset)) { |
2872 printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset); | |
2873 } | |
411 | 2874 #if ENDIAN_L==0 |
2875 if (creg!=regv_l(reg)) { | |
2876 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset,crn); | |
2877 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset+SIZE_OF_INT,crn); | |
2878 } else { | |
2879 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset+SIZE_OF_INT,crn); | |
2880 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset,crn); | |
2881 } | |
2882 #else | |
269 | 2883 if (creg!=regv_h(reg)) { |
375 | 2884 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset,crn); |
2885 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); | |
269 | 2886 } else { |
375 | 2887 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); |
2888 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset,crn); | |
269 | 2889 } |
411 | 2890 #endif |
660 | 2891 #else |
2892 if (LARGE_OFFSET(offset)) { | |
2893 printf("\taddis %s,%s,%d@ha\n",crn,crn,offset); | |
2894 } | |
2895 #if ENDIAN_L==0 | |
2896 if (creg!=regv_l(reg)) { | |
2897 printf("\tlwz %s,%d@l(%s)\n",lregister_name_low(reg),offset,crn); | |
2898 printf("\tlwz %s,%d@l(%s)\n",lregister_name_high(reg),offset+SIZE_OF_INT,crn); | |
2899 } else { | |
2900 printf("\tlwz %s,%d@l(%s)\n",lregister_name_high(reg),offset+SIZE_OF_INT,crn); | |
2901 printf("\tlwz %s,%d@l(%s)\n",lregister_name_low(reg),offset,crn); | |
2902 } | |
2903 #else | |
2904 if (creg!=regv_h(reg)) { | |
2905 printf("\tlwz %s,%d@l(%s)\n",lregister_name_high(reg),offset,crn); | |
2906 printf("\tlwz %s,%d@l(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); | |
2907 } else { | |
2908 printf("\tlwz %s,%d@l(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); | |
2909 printf("\tlwz %s,%d@l(%s)\n",lregister_name_high(reg),offset,crn); | |
2910 } | |
2911 #endif | |
2912 | |
2913 #endif | |
269 | 2914 } |
2915 | |
196 | 2916 int |
221 | 2917 code_lrindirect(int e1, int reg, int offset, int us) |
196 | 2918 { |
2919 char *crn; | |
222 | 2920 int creg0; |
2921 | |
196 | 2922 g_expr(e1); |
221 | 2923 if (!is_int_reg(creg)) error(-1); |
222 | 2924 crn=register_name(creg0=creg); |
221 | 2925 use_longlong(reg); |
269 | 2926 lload(creg0,reg,offset); |
206 | 2927 return us?ULONGLONG:LONGLONG; |
196 | 2928 } |
2929 #endif | |
2930 | |
89 | 2931 void |
103 | 2932 code_assign_gvar(int e2,int creg,int byte) { |
221 | 2933 use_int(creg); |
367 | 2934 code_ldf(cstore(byte),register_name(creg),cadr(e2), |
711 | 2935 get_ptr_cache(ncaddr(e2))); |
89 | 2936 } |
2937 | |
2938 void | |
103 | 2939 code_assign_lvar(int e2,int creg,int byte) { |
90 | 2940 char *crn; |
221 | 2941 use_int(creg); |
90 | 2942 crn=register_name(creg); |
119 | 2943 lvar_intro(e2); |
660 | 2944 printf("\t%s %s,",cstore(byte),crn); |
165 | 2945 lvar(e2); |
89 | 2946 } |
2947 | |
2948 void | |
111 | 2949 code_assign_register(int e2,int byte,int creg) { |
221 | 2950 use_int(creg); |
104 | 2951 if (e2!=creg) |
2952 printf("\tmr %s,%s\n",register_name(e2),register_name(creg)); | |
89 | 2953 } |
2954 | |
2955 void | |
118 | 2956 code_assign(int e2,int byte,int creg) { |
233 | 2957 char *drn; |
221 | 2958 char *crn; |
233 | 2959 use_int(e2); |
2960 drn=register_name(e2); | |
221 | 2961 use_int(creg); |
2962 crn=register_name(creg); | |
95 | 2963 |
367 | 2964 printf("\t%s %s,0(%s)\n",cstore(byte),crn,drn); |
89 | 2965 } |
2966 | |
2967 | |
2968 void | |
221 | 2969 code_register_assop(int e2,int reg, int op,int byte) { |
2970 // reg <= reg(e2) op=reg | |
2971 use_int(reg); | |
2972 tosop(op,e2,reg); | |
89 | 2973 } |
2974 | |
2975 void | |
221 | 2976 code_assop(int op,int creg, int byte,int sign) { |
590 | 2977 int xreg; |
2978 // (*pop()) op = creg | |
2979 // creg should be ecx | |
2980 | |
2981 use_int(creg); | |
2982 xreg = emit_pop(0); /* pop e3 value */ | |
2983 emit_push(); | |
2984 ld_indexx(byte,0,creg,ireg,sign); | |
2985 tosop(op,ireg,xreg); | |
2986 emit_pop_free(xreg); | |
2987 xreg = emit_pop(0); /* pop e3 value */ | |
2988 printf("\t%s %s,0(%s)\n",cstore(byte), | |
2989 register_name(ireg),register_name(xreg)); | |
2990 emit_pop_free(xreg); | |
594 | 2991 } |
2992 | |
2993 int | |
2994 tosop_operand_safe_p(int op) | |
2995 { | |
2996 return 1; | |
89 | 2997 } |
2998 | |
2999 void | |
221 | 3000 tosop(int op,int creg,int oreg) |
89 | 3001 { |
221 | 3002 int dx = -1; |
252 | 3003 int ox = -1; |
95 | 3004 char *orn,*crn,*drn; |
221 | 3005 // creg = creg op oreg |
3006 | |
3007 use_int(creg); | |
103 | 3008 if(oreg==-1) { |
3009 error(-1); | |
3010 } else if (oreg<= -REG_LVAR_OFFSET) { | |
252 | 3011 ox = get_register(); if (ox<0) error(-1); |
3012 code_rlvar(oreg+REG_LVAR_OFFSET,ox); | |
590 | 3013 free_lvar(oreg+REG_LVAR_OFFSET); |
252 | 3014 oreg = ox; |
103 | 3015 } |
3016 | |
89 | 3017 switch(op) { |
3018 case LSHIFT: | |
3019 case ULSHIFT: | |
221 | 3020 shift("slw",creg,oreg); |
252 | 3021 if(ox!=-1) free_register(ox); |
89 | 3022 return; |
3023 case RSHIFT: | |
221 | 3024 shift("sraw",creg,oreg); |
252 | 3025 if(ox!=-1) free_register(ox); |
89 | 3026 return; |
3027 case URSHIFT: | |
221 | 3028 shift("srw",creg,oreg); |
252 | 3029 if(ox!=-1) free_register(ox); |
89 | 3030 return; |
3031 } | |
93 | 3032 orn = register_name(oreg); |
89 | 3033 crn = register_name(creg); |
3034 switch(op) { | |
3035 case ADD: | |
114 | 3036 printf("\tadd %s,%s,%s\n",crn,crn,orn); |
89 | 3037 break; |
3038 case SUB: | |
114 | 3039 printf("\tsub %s,%s,%s\n",crn,crn,orn); |
89 | 3040 break; |
112 | 3041 case CMP: |
291 | 3042 inc_cmpflag(); |
662 | 3043 printf("\tcmpw %s,%s,%s\n",crname(cmpflag),crn,orn); |
280 | 3044 break; |
3045 case UCMP: | |
291 | 3046 inc_cmpflag(); |
662 | 3047 printf("\tcmplw %s,%s,%s\n",crname(cmpflag),crn,orn); |
112 | 3048 break; |
89 | 3049 case BAND: |
114 | 3050 printf("\tand %s,%s,%s\n",crn,crn,orn); |
89 | 3051 break; |
3052 case EOR: | |
114 | 3053 printf("\txor %s,%s,%s\n",crn,crn,orn); |
89 | 3054 break; |
3055 case BOR: | |
114 | 3056 printf("\tor %s,%s,%s\n",crn,crn,orn); |
89 | 3057 break; |
3058 case MUL: | |
116 | 3059 printf("\tmullw %s,%s,%s\n",crn,crn,orn); |
3060 break; | |
89 | 3061 case UMUL: |
114 | 3062 printf("\tmullw %s,%s,%s\n",crn,crn,orn); |
89 | 3063 break; |
3064 case DIV: | |
114 | 3065 printf("\tdivw %s,%s,%s\n",crn,crn,orn); |
90 | 3066 break; |
89 | 3067 case UDIV: |
114 | 3068 printf("\tdivwu %s,%s,%s\n",crn,crn,orn); |
89 | 3069 break; |
3070 case MOD: | |
90 | 3071 dx=get_register(); |
95 | 3072 drn = register_name(dx); |
116 | 3073 printf("\tdivw %s,%s,%s\n",drn,crn,orn); |
3074 printf("\tmullw %s,%s,%s\n",drn,drn,orn); | |
3075 printf("\tsubf %s,%s,%s\n",crn,drn,crn); | |
90 | 3076 break; |
89 | 3077 case UMOD: |
90 | 3078 dx=get_register(); |
95 | 3079 drn = register_name(dx); |
114 | 3080 printf("\tdivwu %s,%s,%s\n",drn,crn,orn); |
116 | 3081 printf("\tmullw %s,%s,%s\n",drn,drn,orn); |
3082 printf("\tsubf %s,%s,%s\n",crn,drn,crn); | |
89 | 3083 break; |
112 | 3084 default: |
3085 error(-1); | |
89 | 3086 } |
221 | 3087 if(dx!=-1) free_register(dx); |
252 | 3088 if(ox!=-1) free_register(ox); |
89 | 3089 } |
3090 | |
189 | 3091 int |
3092 code_const_op_p(int op,int v) | |
3093 { | |
240 | 3094 if (car(v)!=CONST) return 0; |
366 | 3095 if (op==DIV||op==UDIV) return ilog(v); |
3096 if (op==BAND||op==MOD||op==UMOD) return 0; | |
240 | 3097 v = cadr(v); |
214 | 3098 return (-32766<v&&v<32767); |
189 | 3099 } |
3100 | |
211 | 3101 void |
221 | 3102 oprtc(int op,int creg, int v) |
189 | 3103 { |
221 | 3104 char *crn; |
366 | 3105 int l; |
221 | 3106 use_int(creg); |
3107 crn = register_name(creg); | |
240 | 3108 v = cadr(v); |
221 | 3109 |
189 | 3110 switch(op) { |
3111 case LSHIFT: | |
3112 case ULSHIFT: | |
3113 printf("\tslwi %s,%s,%d\n",crn,crn,v); | |
3114 return; | |
366 | 3115 case DIV: |
3116 v = ilog(v); | |
189 | 3117 case RSHIFT: |
3118 printf("\tsrawi %s,%s,%d\n",crn,crn,v); | |
3119 return; | |
366 | 3120 case UDIV: |
3121 v = ilog(v); | |
189 | 3122 case URSHIFT: |
3123 printf("\tsrwi %s,%s,%d\n",crn,crn,v); | |
3124 return; | |
3125 case ADD: | |
660 | 3126 #ifdef __APPLE__ |
189 | 3127 printf("\taddi %s,%s,lo16(%d)\n",crn,crn,v); |
660 | 3128 #else |
3129 printf("\taddi %s,%s,%d@l\n",crn,crn,v); | |
3130 #endif | |
189 | 3131 break; |
3132 case SUB: | |
660 | 3133 #ifdef __APPLE__ |
221 | 3134 printf("\taddi %s,%s,lo16(-%d)\n",crn,crn,v); |
660 | 3135 #else |
3136 printf("\taddi %s,%s,-%d@l\n",crn,crn,v); | |
3137 #endif | |
189 | 3138 break; |
3139 case CMP: | |
291 | 3140 inc_cmpflag(); |
660 | 3141 #ifdef __APPLE__ |
662 | 3142 printf("\tcmpwi %s,%s,lo16(%d)\n",crname(cmpflag),crn,v); |
660 | 3143 #else |
662 | 3144 printf("\tcmpwi %s,%s,%d@l\n",crname(cmpflag),crn,v); |
660 | 3145 #endif |
189 | 3146 break; |
354 | 3147 case UCMP: |
3148 inc_cmpflag(); | |
660 | 3149 #ifdef __APPLE__ |
662 | 3150 printf("\tcmplwi %s,%s,lo16(%d)\n",crname(cmpflag),crn,v); |
660 | 3151 #else |
662 | 3152 printf("\tcmplwi %s,%s,%d@l\n",crname(cmpflag),crn,v); |
660 | 3153 #endif |
354 | 3154 break; |
189 | 3155 case EOR: |
660 | 3156 #ifdef __APPLE__ |
189 | 3157 printf("\txori %s,%s,lo16(%d)\n",crn,crn,v); |
660 | 3158 #else |
3159 printf("\txori %s,%s,%d@l\n",crn,crn,v); | |
3160 #endif | |
189 | 3161 break; |
3162 case BOR: | |
660 | 3163 #ifdef __APPLE__ |
189 | 3164 printf("\tori %s,%s,lo16(%d)\n",crn,crn,v); |
660 | 3165 #else |
3166 printf("\tori %s,%s,%d@l\n",crn,crn,v); | |
3167 #endif | |
189 | 3168 break; |
3169 case MUL: | |
3170 case UMUL: | |
366 | 3171 if ((l=ilog(v))) { |
3172 printf("\tslwi %s,%s,%d\n",crn,crn,l); | |
3173 } else | |
660 | 3174 #ifdef __APPLE__ |
366 | 3175 printf("\tmulli %s,%s,lo16(%d)\n",crn,crn,v); |
660 | 3176 #else |
3177 printf("\tmulli %s,%s,%d@l\n",crn,crn,v); | |
3178 #endif | |
189 | 3179 break; |
3180 default: | |
3181 error(-1); | |
3182 } | |
3183 } | |
89 | 3184 |
3185 void | |
221 | 3186 shift(char *op, int creg, int reg) |
89 | 3187 { |
221 | 3188 char *crn; |
93 | 3189 char *rrn = register_name(reg); |
221 | 3190 use_int(creg); |
3191 crn = register_name(creg); | |
186 | 3192 printf("\t%s %s,%s,%s\n",op,crn,crn,rrn); |
89 | 3193 } |
3194 | |
3195 void | |
221 | 3196 ld_indexx(int byte, int n, int xreg,int creg, int sign) |
89 | 3197 { |
221 | 3198 char *crn; |
3199 use_int(creg); | |
3200 crn = register_name(creg); | |
246 | 3201 printf("\t%s %s,%d(%s)\n",cload(byte),register_name(creg),n, |
90 | 3202 register_name(xreg)); |
246 | 3203 cext(sign,byte,creg); |
89 | 3204 } |
3205 | |
95 | 3206 int |
3207 code_csvalue() | |
3208 { | |
458 | 3209 return glist2(REGISTER,creg); |
95 | 3210 } |
3211 | |
89 | 3212 void |
287 | 3213 code_cmpdimm(int e, int csreg,int label,int cond) |
89 | 3214 { |
415 | 3215 int reg,regsv; |
89 | 3216 /* used in dosiwtch() */ |
291 | 3217 inc_cmpflag(); |
3218 if (-32767<e&&e<32767) { | |
662 | 3219 printf("\tcmpwi %s,%s,%d\n",crname(cmpflag),register_name(csreg),e); |
291 | 3220 jcond(label,cond); |
3221 } else { | |
415 | 3222 regsv = regs[csreg]; regs[csreg]=USING_REG; |
366 | 3223 reg = get_register(); |
415 | 3224 regs[csreg]= regsv; |
405 | 3225 code_const(e,reg); |
662 | 3226 printf("\tcmpw %s,%s,%s\n",crname(cmpflag),register_name(csreg),register_name(reg)); |
366 | 3227 jcond(label,cond); |
3228 free_register(reg); | |
291 | 3229 } |
89 | 3230 } |
3231 | |
3232 void | |
3233 code_opening(char *filename) | |
3234 { | |
3235 printf("\t.file \"%s\"\n",filename); | |
108 | 3236 /* printf("\t.version\t\"01.01\"\n"); */ |
89 | 3237 /* printf("gcc2_compiled.:\n"); */ |
605 | 3238 // printf(".text\n"); |
89 | 3239 } |
3240 | |
288 | 3241 #define CRBITSIZ 4 |
3242 | |
3243 static int | |
3244 rexpr_bool(int e1,int reg) | |
3245 { | |
3246 int t,flag=-1,eq=-1,neg=-1; | |
3247 char *rn; | |
3248 switch(car(e1)) { | |
3249 case GT: t=INT; flag = 2; break; | |
3250 case UGT: t=0; flag = 2; break; | |
3251 case GE: t=INT; flag = 2; eq=3; break; | |
3252 case UGE: t=0; flag = 2; eq=3; break; | |
3253 case LT: t=INT; flag = 1; break; | |
3254 case ULT: t=0; flag = 1; break; | |
3255 case LE: t=INT; flag = 1; eq=3; break; | |
3256 case ULE: t=0; flag = 1; eq=3; break; | |
3257 case EQ: t=INT; flag = 3; break; | |
289 | 3258 case NEQ: t=INT; flag = 3; neg=3; break; |
288 | 3259 default: return 0; |
3260 } | |
3261 g_expr(list3((t==INT?CMP:UCMP),cadr(e1),caddr(e1))); | |
3262 use_int(reg); | |
3263 rn = register_name(reg); | |
289 | 3264 t = CRBITSIZ*cmpflag; |
288 | 3265 if (eq>0) { |
289 | 3266 printf("\tcror %d,%d,%d\n",t+flag-1,t+eq-1,t+flag-1); |
3267 } | |
3268 if (neg>0) { | |
3269 neg = t+neg-1, | |
3270 printf("\tcrnor %d,%d,%d\n",neg,neg,neg); | |
288 | 3271 } |
3272 printf("\tmfcr %s\n",rn); | |
289 | 3273 printf("\trlwinm %s,%s,%d,1\n",rn,rn,t+flag); |
288 | 3274 return 1; |
3275 } | |
3276 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
3277 int |
280 | 3278 rexpr(int e1, int l1, int cond,int t) |
89 | 3279 { |
569 | 3280 char *s=0; |
433 | 3281 switch(car(e1)+BNOT*(!cond)) { |
3282 case GT: s=code_gt(1); break; | |
3283 case UGT: s=code_ugt(1); break; | |
3284 case GE: s=code_ge(1); break; | |
3285 case UGE: s=code_uge(1); break; | |
3286 case LT: s=code_ge(!1); break; | |
3287 case ULT: s=code_uge(!1);break; | |
3288 case LE: s=code_gt(!1); break; | |
3289 case ULE: s=code_ugt(!1);break; | |
3290 case EQ: s=code_eq(1); break; | |
3291 case NEQ: s=code_eq(!1); break; | |
3292 case GT+BNOT: s=code_gt(0); break; | |
3293 case UGT+BNOT: s=code_ugt(0); break; | |
3294 case GE+BNOT: s=code_ge(0); break; | |
3295 case UGE+BNOT: s=code_uge(0); break; | |
3296 case LT+BNOT: s=code_ge(!0); break; | |
3297 case ULT+BNOT: s=code_uge(!0);break; | |
3298 case LE+BNOT: s=code_gt(!0); break; | |
3299 case ULE+BNOT: s=code_ugt(!0);break; | |
3300 case EQ+BNOT: s=code_eq(0); break; | |
3301 case NEQ+BNOT: s=code_eq(!0); break; | |
280 | 3302 default: error(-1); |
3303 } | |
3304 g_expr(list3((t==INT?CMP:UCMP),cadr(e1),caddr(e1))); | |
662 | 3305 printf("\tb%s %s,%s%d\n",s,crname(cmpflag),lpfx,l1); |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
3306 return l1; |
89 | 3307 } |
3308 | |
287 | 3309 static void |
89 | 3310 jcond(int l, char cond) |
3311 { | |
297 | 3312 if (cond==LT) { |
662 | 3313 printf("\tb%s %s,%s%d\n",code_ge(0),crname(cmpflag),lpfx,l); |
297 | 3314 } else if (cond==1||cond==0) { |
662 | 3315 printf("\tb%s %s,%s%d\n",cond?"ne":"eq",crname(cmpflag),lpfx,l); |
297 | 3316 } else error(-1); |
89 | 3317 } |
3318 | |
3319 void | |
3320 jmp(int l) | |
3321 { | |
662 | 3322 printf("\tb\t%s%d\n",lpfx,l); |
89 | 3323 } |
3324 | |
327 | 3325 extern void |
456 | 3326 code_comment(char *s) |
89 | 3327 { |
307 | 3328 printf("## %s",s); |
89 | 3329 } |
3330 | |
3331 void | |
3332 code_enter(char *name) | |
3333 { | |
660 | 3334 #ifdef __APPLE__ |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3335 if (output_mode!=TEXT_EMIT_MODE) |
516 | 3336 text_mode(0); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3337 else |
108 | 3338 printf("\t.align 2\n"); |
89 | 3339 if (stmode!=STATIC) |
102 | 3340 printf(".globl _%s\n",name); |
126 | 3341 #ifdef DOT_SIZE |
89 | 3342 printf("\t.type\t%s,@function\n",name); |
126 | 3343 #endif |
101 | 3344 printf("_%s:\n",name); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3345 code_disp_label=fwdlabel(); |
417 | 3346 #if 0 |
128 | 3347 printf("\tla r1,lo16(L_%d)(r30)\n",code_disp_label); |
417 | 3348 #else |
3349 printf("\tla r1,lo16(L_%d)(r30)\n",code_disp_label); | |
3350 printf("\taddis r1,r1,ha16(L_%d)\n",code_disp_label); | |
3351 #endif | |
126 | 3352 printf("\tbcl 20,31,L_%d\n",code_base = fwdlabel()); |
3353 fwddef(code_base); | |
3354 printf("\tmflr r31\n"); | |
119 | 3355 max_func_args = 0; |
489 | 3356 clear_ptr_cache(); |
660 | 3357 #else |
3358 if (output_mode!=TEXT_EMIT_MODE) | |
3359 text_mode(0); | |
3360 else | |
3361 printf("\t.align 2\n"); | |
3362 if (stmode!=STATIC) | |
3363 printf(".globl %s\n",name); | |
3364 #ifdef DOT_SIZE | |
3365 printf("\t.type\t%s,@function\n",name); | |
3366 #endif | |
3367 printf("%s:\n",name); | |
3368 code_disp_label=fwdlabel(); | |
3369 #if 0 | |
3370 printf("\tla r1,lo16(L_%d)(r30)\n",code_disp_label); | |
3371 #else | |
672 | 3372 printf("\tla 1,%s%d@l(31)\n",lpfx,code_disp_label); |
3373 printf("\taddis 1,1,%s%d@ha\n",lpfx,code_disp_label); | |
660 | 3374 #endif |
3375 max_func_args = 0; | |
3376 clear_ptr_cache(); | |
3377 #endif | |
89 | 3378 } |
3379 | |
3380 | |
3381 void | |
3382 code_enter1(int args) | |
3383 { | |
222 | 3384 // set_lreg(LREG_LREGISTER,0); |
207 | 3385 set_ireg(CREG_REGISTER,0); |
106 | 3386 set_freg(FREG_FREGISTER,0); |
89 | 3387 } |
3388 | |
3389 void | |
3390 code_leave(char *name) | |
3391 { | |
128 | 3392 int r1_offsetv; |
245 | 3393 disp&= -SIZE_OF_INT; |
603 | 3394 r1_offsetv = -disp+max_func_args*SIZE_OF_INT -code_disp_offset0 +8+32+48; |
660 | 3395 #ifdef __APPLE__ |
128 | 3396 printf(".set L_%d,%d\n",code_disp_label,-r1_offsetv); |
417 | 3397 if (max_func_arg_label) { |
3398 printf(".set L_%d,%d\n",max_func_arg_label,max_func_args*SIZE_OF_INT+24); | |
3399 max_func_arg_label = 0; | |
3400 } | |
660 | 3401 #else |
3402 printf(".set .LC%d,%d\n",code_disp_label,-r1_offsetv); | |
3403 if (max_func_arg_label) { | |
3404 printf(".set .LC%d,%d\n",max_func_arg_label,max_func_args*SIZE_OF_INT+24); | |
3405 max_func_arg_label = 0; | |
3406 } | |
3407 #endif | |
89 | 3408 local_table(); |
208 | 3409 // free_all_register(); |
89 | 3410 } |
3411 | |
3412 void | |
3413 enter(char *name) | |
3414 { | |
660 | 3415 #ifdef __APPLE__ |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3416 if (output_mode!=TEXT_EMIT_MODE) |
516 | 3417 text_mode(0); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3418 else |
108 | 3419 printf("\t.align 2\n"); |
89 | 3420 if (stmode!=STATIC) |
662 | 3421 printf(".globl %s%s\n",npfx,name); |
108 | 3422 /* |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3423 printf("\t.type\t%s,@function\n",name); |
108 | 3424 */ |
662 | 3425 printf("%s%s:\n",npfx,name); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3426 code_setup=fwdlabel(); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3427 printf("\tmflr r0\n"); |
102 | 3428 printf("\tbl L_%d\n",code_setup); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3429 code_base=fwdlabel(); |
111 | 3430 fwddef(code_base); |
116 | 3431 r1_offset_label = fwdlabel(); |
3432 lvar_offset_label = fwdlabel(); | |
375 | 3433 #if 0 |
3434 printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label); | |
116 | 3435 printf("\tstwu r1,lo16(-L_%d)(r1)\n",r1_offset_label); |
375 | 3436 // printf("\tmr r30,r1\n"); |
3437 #else | |
3438 printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label); | |
3439 printf("\tlis r31,ha16(-L_%d)\n",r1_offset_label); | |
3440 printf("\taddi r31,r31,lo16(-L_%d)\n",r1_offset_label); | |
3441 printf("\tstwux r1,r1,r31\n"); | |
3442 #endif | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3443 printf("\tmflr r31\n"); |
660 | 3444 #else |
3445 if (output_mode!=TEXT_EMIT_MODE) | |
3446 text_mode(0); | |
3447 else | |
3448 printf("\t.align 2\n"); | |
3449 if (stmode!=STATIC) | |
662 | 3450 printf(".globl %s%s\n",npfx,name); |
660 | 3451 /* |
3452 printf("\t.type\t%s,@function\n",name); | |
3453 */ | |
3454 printf("%s:\n",name); | |
3455 code_setup=fwdlabel(); | |
672 | 3456 arg_offset_label = fwdlabel(); |
660 | 3457 printf("\tmflr 0\n"); |
672 | 3458 printf("\tstwu %d,-%s%d@l(%d)\n",1,lpfx,arg_offset_label,1); |
660 | 3459 printf("\tbl .LC%d\n",code_setup); |
3460 r1_offset_label = fwdlabel(); | |
3461 lvar_offset_label = fwdlabel(); | |
667 | 3462 |
672 | 3463 printf("\tmr %d,1\n",REG_fp); |
3464 printf("\taddi %d,1,-%s%d@l\n",REG_fp,lpfx,lvar_offset_label); | |
667 | 3465 printf("\tlis %d,-%s%d@ha\n",30,lpfx,r1_offset_label); |
672 | 3466 printf("\taddi %d,%d,-%s%d@l\n",30,30,lpfx,r1_offset_label); |
667 | 3467 printf("\tstwux 1,1,%d\n",30); |
660 | 3468 #endif |
116 | 3469 max_func_args = 0; |
489 | 3470 clear_ptr_cache(); |
89 | 3471 } |
3472 | |
3473 void | |
3474 enter1() | |
3475 { | |
516 | 3476 text_mode(0); |
208 | 3477 // set_lreg(LREG_LREGISTER,0); |
207 | 3478 set_ireg(CREG_REGISTER,0); |
106 | 3479 set_freg(FREG_FREGISTER,0); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3480 } |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3481 |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3482 int |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3483 reg_save_offset() |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3484 { |
108 | 3485 return -( |
245 | 3486 (REAL_MAX_REGISTER-(REG_VAR_BASE-max_reg_var))*SIZE_OF_INT+ |
3487 (REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*SIZE_OF_DOUBLE | |
108 | 3488 ); |
89 | 3489 } |
3490 | |
3491 void | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3492 code_label_call(int l) |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3493 { |
660 | 3494 #ifdef __APPLE__ |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3495 printf("\tbl\tL_%d\n",l); |
660 | 3496 #else |
3497 printf("\tbl\t.LC%d\n",l); | |
3498 #endif | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3499 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3500 |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3501 void |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3502 code_ret() |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3503 { |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3504 printf("\tblr\n"); |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3505 } |
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3506 |
663 | 3507 #ifndef __APPLE__ |
3508 static int saveFP_used=0; | |
3509 static char *saveFP_lib[] = { | |
3510 ".saveFP: stfd 14,-144(1)", | |
3511 " stfd 15,-136(1)", | |
3512 " stfd 16,-128(1)", | |
3513 " stfd 17,-120(1)", | |
3514 " stfd 18,-112(1)", | |
3515 " stfd 19,-104(1)", | |
3516 " stfd 20,-96(1)", | |
3517 " stfd 21,-88(1)", | |
3518 " stfd 22,-80(1)", | |
3519 " stfd 23,-72(1)", | |
3520 " stfd 24,-64(1)", | |
3521 " stfd 25,-56(1)", | |
3522 " stfd 26,-48(1)", | |
3523 " stfd 27,-40(1)", | |
3524 " stfd 28,-32(1)", | |
3525 " stfd 29,-24(1)", | |
672 | 3526 " stfd 31,-16(1)", |
3527 " stfd 30,-8(1)", | |
676 | 3528 " stw 0,4(1)", |
663 | 3529 " blr", |
672 | 3530 ".restFP: ", |
3531 " lfd 14,-144(1)", | |
663 | 3532 " lfd 15,-136(1)", |
3533 " lfd 16,-128(1)", | |
3534 " lfd 17,-120(1)", | |
3535 " lfd 18,-112(1)", | |
3536 " lfd 19,-104(1)", | |
3537 " lfd 20,-96(1)", | |
3538 " lfd 21,-88(1)", | |
3539 " lfd 22,-80(1)", | |
3540 " lfd 23,-72(1)", | |
3541 " lfd 24,-64(1)", | |
3542 " lfd 25,-56(1)", | |
3543 " lfd 26,-48(1)", | |
3544 " lfd 27,-40(1)", | |
3545 " lfd 28,-32(1)", | |
3546 " lfd 29,-24(1)", | |
672 | 3547 " lwz 0,4(1)", |
3548 " lfd 31,-16(1)", | |
3549 " lwz 1,0(1)", | |
663 | 3550 " mtlr 0", |
672 | 3551 " blr", |
663 | 3552 0 |
3553 }; | |
3554 #endif | |
3555 | |
726 | 3556 static void |
3557 make_return_continuation() | |
3558 { | |
3559 #if R1SAVE | |
3560 retcont1 = fwdlabel(); | |
3561 #endif | |
3562 fwddef(retcont); | |
3563 if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) { | |
3564 printf("\tfmr %s,%s\n",fregister_name(1),fregister_name(31)); | |
3565 printf("\tmr %s,%s\n",register_name(30),register_name(28)); | |
3566 } else if (cadr(fnptr->ty)>0&&( | |
3567 car(cadr(fnptr->ty))==STRUCT || | |
3568 car(cadr(fnptr->ty))==UNION)) { | |
3569 int sz = size(cadr(fnptr->ty)); | |
3570 #ifdef __APPLE__ | |
3571 printf("\tli r7,%d\n",sz); | |
3572 printf("\tsubl r6,r7,r30\n"); | |
3573 printf("\tlwz r3,lo16(%d)(r30)\n",(my_func_args-1)*SIZE_OF_INT); | |
3574 // emit_copy(6,3,sz,0,1,1); | |
3575 #else | |
3576 printf("\tli 7,%d\n",sz); | |
3577 printf("\tsubl 6,7,%d\n",REG_fp); | |
3578 printf("\tlwz 3,%d@l(%d)\n",(my_func_args-1)*SIZE_OF_INT,REG_fp); | |
3579 // emit_copy(6,3,sz,0,1,1); | |
3580 #endif | |
3581 printf("\tmr %s,%s\n",register_name(30),register_name(28)); | |
3582 } else if (cadr(fnptr->ty)!=VOID) { | |
3583 printf("\tmr %s,%s\n",register_name(3),register_name(29)); | |
3584 printf("\tmr %s,%s\n",register_name(30),register_name(28)); | |
3585 } | |
3586 #if R1SAVE | |
3587 jmp(retcont1); | |
3588 #else | |
3589 #endif | |
3590 } | |
3591 | |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3592 void |
89 | 3593 leave(int control, char *name) |
3594 { | |
577 | 3595 #if R1SAVE |
726 | 3596 int retcont1=0; |
577 | 3597 #else |
3598 #endif | |
128 | 3599 |
3600 if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; | |
3601 reg_save = reg_save_offset(); | |
111 | 3602 |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3603 if (control) { |
108 | 3604 code_set_return_register(1); |
89 | 3605 } |
126 | 3606 if (retcont) { |
3607 if (control) jmp(retlabel); | |
726 | 3608 make_return_continuation(); |
126 | 3609 } |
89 | 3610 fwddef(retlabel); |
577 | 3611 #if R1SAVE |
662 | 3612 printf("\tlwz %s,0(%s)\n",register_name(1),register_name(1)); |
128 | 3613 if (retcont) { |
3614 fwddef(retcont1); | |
3615 } | |
577 | 3616 #else |
662 | 3617 #ifdef __APPLE__ |
577 | 3618 printf("\taddi r1,r30,lo16(L_%d)\n",lvar_offset_label); |
662 | 3619 #else |
672 | 3620 printf("\taddi 1,%d,%s%d@l\n",REG_fp,lpfx,lvar_offset_label); |
662 | 3621 #endif |
577 | 3622 #endif |
110 | 3623 if (max_freg_var>=0) { |
663 | 3624 #ifdef __APPLE__ |
662 | 3625 printf("\tlmw r%d,%d(%s)\n", |
3626 REG_VAR_BASE-max_reg_var,reg_save,register_name(1)); | |
111 | 3627 freg_save = 72-(REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*4; |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3628 printf("\tb restFP+%d ; restore f%d-f31\n", |
111 | 3629 freg_save, |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3630 FREG_VAR_BASE-max_freg_var); |
662 | 3631 #else |
663 | 3632 printf("\tlmw %d,%d(%s)\n", |
3633 REG_VAR_BASE-max_reg_var,reg_save,register_name(1)); | |
3634 freg_save = 72-(REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*4; | |
3635 printf("\tb .restFP+%d # restore f%d-f31\n", | |
662 | 3636 freg_save, |
3637 FREG_VAR_BASE-max_freg_var); | |
3638 #endif | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3639 } else { |
662 | 3640 #ifdef __APPLE__ |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3641 printf("\tlwz r0,8(r1)\n"); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3642 printf("\tmtlr r0\n"); |
110 | 3643 printf("\tlmw r%d,%d(r1)\n", |
116 | 3644 REG_VAR_BASE-max_reg_var,reg_save); |
662 | 3645 #else |
3646 printf("\tlmw %d,%d(1)\n", | |
3647 REG_VAR_BASE-max_reg_var,reg_save); | |
672 | 3648 printf("\tlwz %s,4(1)\n",register_name(0)); |
3649 printf("\tlwz 1,0(1)\n"); | |
3650 printf("\tmtlr %s\n",register_name(0)); | |
662 | 3651 #endif |
450
eaf9e2746c83
parallel assign for simple expr. (too complex solution)
kono
parents:
449
diff
changeset
|
3652 code_ret(); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3653 } |
89 | 3654 |
245 | 3655 disp &= -SIZE_OF_INT; |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3656 fwddef(code_setup); |
672 | 3657 #ifdef __APPLE__ |
662 | 3658 printf("\tstmw %s,%d(%s)\n", |
3659 register_name(REG_VAR_BASE-max_reg_var),reg_save,register_name(1)); | |
3660 printf("\tstw %s,8(%s)\n",register_name(0),register_name(1)); | |
672 | 3661 #else |
3662 printf("\tstmw %s,%d(%s)\n", | |
3663 register_name(REG_VAR_BASE-max_reg_var),reg_save,register_name(1)); | |
3664 printf("\tstw %s,4(%s)\n",register_name(0),register_name(1)); | |
3665 #endif | |
663 | 3666 if (max_freg_var>=0) { |
664 | 3667 #ifdef __APPLE__ |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3668 printf("\tb saveFP+%d ; save f%d-f31\n", |
111 | 3669 freg_save, |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3670 FREG_VAR_BASE-max_freg_var); |
662 | 3671 #else |
663 | 3672 saveFP_used = 1; |
3673 printf("\tb .saveFP+%d # save f%d-f31\n", | |
662 | 3674 freg_save, |
3675 FREG_VAR_BASE-max_freg_var); | |
3676 #endif | |
663 | 3677 } else { |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3678 printf("\tblr\n"); |
110 | 3679 } |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
3680 |
116 | 3681 code_offset_set(); |
89 | 3682 local_table(); |
3683 labelno++; | |
208 | 3684 // free_all_register(); |
89 | 3685 } |
3686 | |
3687 | |
705 | 3688 int |
107 | 3689 code_set_return_register(int mode) { |
111 | 3690 if (cadr(fnptr->ty)==DOUBLE||cadr(fnptr->ty)==FLOAT) { |
107 | 3691 set_freg(RET_FREGISTER,mode); |
705 | 3692 return freg; |
206 | 3693 } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) { |
3694 set_lreg(RET_LREGISTER,mode); | |
705 | 3695 return lreg; |
147 | 3696 } else if (cadr(fnptr->ty)==VOID) { |
705 | 3697 return 0; |
103 | 3698 } else { |
207 | 3699 set_ireg(RET_REGISTER,mode); |
705 | 3700 return ireg; |
103 | 3701 } |
89 | 3702 } |
3703 | |
187 | 3704 int |
3705 code_get_fixed_creg(int reg,int type) { | |
3706 return creg; | |
3707 } | |
3708 | |
89 | 3709 void |
187 | 3710 code_set_fixed_creg(int reg,int mode,int type) { |
108 | 3711 if (type==FLOAT||type==DOUBLE) { |
187 | 3712 set_freg(reg,mode); |
206 | 3713 } else if (type==LONGLONG||type==ULONGLONG) { |
195 | 3714 set_lreg(reg,mode); |
210 | 3715 // use_reg(reg); |
108 | 3716 } else { |
207 | 3717 set_ireg(reg,mode); |
108 | 3718 } |
107 | 3719 } |
3720 | |
3721 void | |
89 | 3722 gen_gdecl(char *n, int gpc) |
3723 { | |
102 | 3724 /* |
89 | 3725 if (stmode!=STATIC) |
99 | 3726 printf(".globl _%s\n",n); |
102 | 3727 */ |
89 | 3728 } |
3729 | |
340 | 3730 extern void |
3731 ascii(char *s) | |
3732 { | |
517 | 3733 cstring_mode(); |
662 | 3734 #ifdef __APPLE__ |
340 | 3735 printf("\t.ascii \""); |
662 | 3736 #else |
3737 printf("\t.string \""); | |
3738 #endif | |
340 | 3739 while(*s) { |
3740 if (*s=='\n') | |
3741 printf("%cn",92); | |
3742 else if (*s<' ') | |
3743 printf("%c%03o",92,*s); | |
3744 else if (*s=='\\') | |
3745 printf("\\\\"); | |
3746 else if (*s==34) | |
3747 printf("%c%c",92,34); | |
3748 else | |
3749 printf("%c",*s); | |
3750 s++; | |
3751 } | |
3752 printf("\\0%c\n\t.align 2\n",34); | |
3753 } | |
3754 | |
3755 extern int | |
3756 emit_string_label() { | |
3757 int lb; | |
3758 | |
3759 lb=fwdlabel(); | |
516 | 3760 cstring_mode(); |
662 | 3761 printf("%s%d:\n",lpfx,lb); |
340 | 3762 return lb; |
3763 } | |
3764 | |
518 | 3765 extern void |
3766 emit_string(char *s,int t) | |
3767 { | |
3768 t = type_value(t); | |
3769 if (car(t)==ARRAY && | |
3770 (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) { | |
3771 ascii(s); | |
3772 } else { | |
3773 int l = emit_string_label(); | |
3774 ascii(s); | |
3775 emit_label(l); | |
3776 } | |
3777 return; | |
3778 } | |
3779 | |
415 | 3780 void |
716 | 3781 code_align(int t) |
89 | 3782 { |
415 | 3783 int d; |
3784 switch(t) { | |
3785 case CHAR: case UCHAR: return; | |
3786 case SHORT: case USHORT: d = data_alignment & 1; break; | |
3787 default: d = data_alignment & 3; | |
3788 } | |
3789 if (d) { | |
3790 printf("\t.align 2\n"); | |
3791 data_alignment = 0; | |
89 | 3792 } |
3793 } | |
3794 | |
516 | 3795 void |
517 | 3796 emit_global(NMTBL *n,int a,int e) |
340 | 3797 { |
517 | 3798 int t = type_value(n->ty); |
3799 if (e>0 && car(e)==STRING && t>0 && car(t)==ARRAY && | |
3800 (type_value(cadr(t))==CHAR||type_value(cadr(t))==UCHAR)) { | |
3801 cstring_mode(); | |
3802 } else | |
3803 data_mode(n->nm); | |
542 | 3804 if (n && n->sc!=STATIC) |
662 | 3805 printf("\t.globl\t%s%s\n",npfx,n->nm); |
3806 printf("%s%s:\n",npfx,n->nm); | |
340 | 3807 } |
3808 | |
3809 extern void | |
3810 emit_space(int sp) | |
3811 { | |
3812 data_mode(0); | |
3813 printf("\t.space\t%d\n",sp); | |
3814 } | |
3815 | |
3816 extern void | |
3817 emit_char(int d) | |
89 | 3818 { |
340 | 3819 data_mode(0); |
3820 printf("\t.byte %d\n",d); | |
3821 } | |
3822 | |
3823 extern void | |
3824 emit_short(int d) | |
3825 { | |
3826 data_mode(0); | |
3827 printf("\t.short %d\n",d); | |
3828 } | |
3829 | |
3830 extern void | |
3831 emit_int(int d) | |
3832 { | |
3833 data_mode(0); | |
3834 printf("\t.long %d\n",d); | |
3835 } | |
3836 | |
3837 extern void | |
3838 emit_longlong(int e) | |
3839 { | |
206 | 3840 #if LONGLONG_CODE |
341 | 3841 long long d = lcadr(e); |
340 | 3842 data_mode(0); |
411 | 3843 #if ENDIAN_L==0 |
3844 printf("\t.long\t0x%x,0x%x\n",code_l1(d),code_l2(d)); | |
3845 #else | |
340 | 3846 printf("\t.long\t0x%x,0x%x\n",code_l2(d),code_l1(d)); |
195 | 3847 #endif |
411 | 3848 #endif |
340 | 3849 } |
3850 | |
3851 extern void | |
3852 emit_double(int e) | |
3853 { | |
195 | 3854 #if FLOAT_CODE |
341 | 3855 double d = dcadr(e); |
340 | 3856 data_mode(0); |
411 | 3857 #if ENDIAN_D==0 |
3858 printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d)); | |
3859 #else | |
340 | 3860 printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); |
339 | 3861 #endif |
411 | 3862 #endif |
340 | 3863 } |
3864 | |
3865 extern void | |
3866 emit_float(int e) | |
3867 { | |
3868 #if FLOAT_CODE | |
341 | 3869 float f = dcadr(e); |
340 | 3870 data_mode(0); |
3871 printf("\t.long\t0x%x\n",*(int *)&f); | |
3872 #endif | |
3873 } | |
3874 | |
3875 extern void | |
367 | 3876 emit_address(char *s,int offset) |
340 | 3877 { |
3878 data_mode(0); | |
367 | 3879 if (offset) |
662 | 3880 printf("\t.long %s%s+%d\n",npfx,s,offset); |
367 | 3881 else |
662 | 3882 printf("\t.long %s%s\n",npfx,s); |
340 | 3883 } |
3884 | |
3885 extern void | |
3886 emit_label(int labelno) | |
3887 { | |
3888 data_mode(0); | |
662 | 3889 printf("\t.long %s%d\n",lpfx,labelno); |
340 | 3890 } |
3891 | |
3892 extern void | |
89 | 3893 emit_data_closing(NMTBL *n) |
3894 { | |
126 | 3895 #ifdef DOT_SIZE |
89 | 3896 int lb; |
126 | 3897 #endif |
89 | 3898 if (mode==GDECL) { |
662 | 3899 #ifdef DOT_SIZE |
3900 #ifdef __APPLE__ | |
89 | 3901 data_mode(0); |
662 | 3902 lb=fwdlabel(); |
3903 printf("%s%d:\n",lpfx,lb); | |
3904 printf("\t.size\t%s,%s%d-%%ss\n",n->nm,lb,lpfx,npfx,n->nm); | |
3905 #else | |
3906 data_mode(0); | |
89 | 3907 lb=fwdlabel(); |
662 | 3908 printf(".LC%d:\n",lb); |
3909 printf("\t.size\t%s,%s%d-%s%s\n",n->nm,lb,lpfx,npfx,n->nm); | |
3910 #endif | |
126 | 3911 #endif |
89 | 3912 } |
3913 } | |
3914 | |
662 | 3915 #ifdef __APPLE__ |
89 | 3916 void |
3917 global_table(void) | |
3918 { | |
3919 NMTBL *n; | |
98 | 3920 int init; char *extrn; |
89 | 3921 init=0; |
350 | 3922 for(n = global_list;n!=&null_nptr;n = n->next) { |
109 | 3923 if ((n->sc == GVAR) && n->dsp != -1) { |
89 | 3924 /* n->dsp = -1 means initialized global */ |
3925 if (init==0) { | |
3926 data_mode(0); | |
3927 init=1; | |
3928 } | |
662 | 3929 printf(".comm %s%s,%d\n",npfx,n->nm,size(n->ty)); |
109 | 3930 } else if ((n->sc==STATIC) && n->dsp != -1) { |
3931 /* n->dsp = -1 means initialized global */ | |
544 | 3932 if (is_code(n)||is_function(n)) continue; |
109 | 3933 if (init==0) { |
3934 data_mode(0); | |
3935 init=1; | |
3936 } | |
662 | 3937 printf(".lcomm %s%s,%d\n",npfx,n->nm,size(n->ty)); |
97 | 3938 } |
3939 } | |
350 | 3940 for(n = global_list;n!=&null_nptr;n = n->next) { |
103 | 3941 if (is_code(n)||is_function(n)) { |
97 | 3942 extrn = n->nm; |
103 | 3943 if (n->sc==EXTRN1) { |
3944 data_mode(0); | |
3945 printf(".picsymbol_stub\n"); | |
97 | 3946 printf("L_%s$stub:\n",extrn); |
3947 printf("\t.indirect_symbol _%s\n",extrn); | |
3948 printf("\tmflr r0\n"); | |
3949 printf("\tbcl 20,31,L0$_%s\n",extrn); | |
3950 printf("L0$_%s:\n",extrn); | |
3951 printf("\tmflr r11\n"); | |
3952 printf("\taddis r11,r11,ha16(L_%s$lazy_ptr-L0$_%s)\n",extrn,extrn); | |
3953 printf("\tmtlr r0\n"); | |
3954 printf("\tlwz r12,lo16(L_%s$lazy_ptr-L0$_%s)(r11)\n",extrn,extrn); | |
3955 printf("\tmtctr r12\n"); | |
3956 printf("\taddi r11,r11,lo16(L_%s$lazy_ptr-L0$_%s)\n",extrn,extrn); | |
3957 printf("\tbctr\n"); | |
3958 printf(".data\n"); | |
3959 printf(".lazy_symbol_pointer\n"); | |
3960 printf("L_%s$lazy_ptr:\n",extrn); | |
3961 printf("\t.indirect_symbol _%s\n",extrn); | |
3962 printf("\t.long dyld_stub_binding_helper\n"); | |
544 | 3963 } else if (n->sc==STATIC) { |
516 | 3964 text_mode(0); |
103 | 3965 printf("\t.set L_%s$stub,_%s\n",extrn,extrn); |
109 | 3966 data_mode(0); |
111 | 3967 printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",extrn,extrn); |
108 | 3968 } |
97 | 3969 } |
3970 } | |
109 | 3971 init=0; |
350 | 3972 for(n = global_list;n!=&null_nptr;n = n->next) { |
109 | 3973 if (n->sc == GVAR) { |
3974 if (init==0) { | |
119 | 3975 printf(".data\n"); |
109 | 3976 init=1; |
3977 } | |
116 | 3978 printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",n->nm,n->nm); |
109 | 3979 } |
3980 } | |
97 | 3981 init = 0; |
350 | 3982 for(n = global_list;n!=&null_nptr;n = n->next) { |
453 | 3983 if ((is_code(n)||is_function(n))&& |
3984 !has_attr(n,FNAME)) // not used as value | |
3985 continue; | |
109 | 3986 if (n->sc==EXTRN1) { |
97 | 3987 if(init==0) { |
119 | 3988 printf(".data\n"); |
97 | 3989 printf(".non_lazy_symbol_pointer\n"); |
3990 init=1; | |
3991 } | |
3992 printf("L_%s$non_lazy_ptr:\n",n->nm); | |
3993 printf("\t.indirect_symbol _%s\n",n->nm); | |
3994 printf("\t.long\t0\n"); | |
89 | 3995 } |
3996 } | |
3997 } | |
662 | 3998 #else |
3999 | |
4000 static void | |
4001 comm(NMTBL *n) | |
4002 { | |
4003 int align = 1; | |
4004 switch(n->ty) { | |
4005 case DOUBLE: | |
4006 case LONGLONG: | |
4007 case ULONGLONG: | |
4008 align = 8; break; | |
4009 case INT: | |
4010 case UNSIGNED: | |
4011 case FLOAT: | |
4012 align = 4; break; | |
4013 case SHORT: | |
4014 case USHORT: | |
4015 align = 2; break; | |
4016 } | |
4017 printf("\t.comm %s,%d,%d\n",n->nm,size(n->ty),align); | |
4018 } | |
4019 | |
4020 void | |
4021 global_table(void) | |
4022 { | |
4023 NMTBL *n; | |
4024 int init; | |
4025 init=0; | |
4026 for(n=global_list;n;n=n->next) { | |
4027 if ((n->sc == GVAR) && n->dsp != -1) { | |
4028 /* n->dsp = -1 means initialized global */ | |
4029 if (init==0) { | |
4030 data_mode(0); | |
4031 init=1; | |
4032 } | |
4033 comm(n); | |
4034 } else if ((n->sc==STATIC) && n->dsp != -1) { | |
4035 /* n->dsp = -1 means initialized global */ | |
4036 if (is_code(n)||is_function(n)) continue; | |
4037 if (init==0) { | |
4038 data_mode(0); | |
4039 init=1; | |
4040 } | |
4041 // printf(".local %s\n",n->nm); | |
4042 comm(n); | |
4043 } | |
4044 } | |
4045 } | |
4046 #endif | |
4047 | |
4048 #ifdef __APPLE__ | |
89 | 4049 void |
4050 local_table(void) | |
4051 { | |
4052 NMTBL *n; | |
4053 int init; | |
4054 init=0; | |
4055 /* static local variables */ | |
350 | 4056 for(n = local_static_list;n!=&null_nptr;n = n->next) { |
553 | 4057 if (n->sc == STATIC) { |
89 | 4058 if (init==0) { |
4059 data_mode(0); | |
4060 init=1; | |
4061 } | |
156 | 4062 if (n->dsp != -1) /* initialized static */ |
4063 printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); | |
4064 printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",n->nm,n->nm); | |
89 | 4065 } |
4066 } | |
4067 } | |
662 | 4068 #else |
4069 void | |
4070 local_table(void) | |
4071 { | |
4072 NMTBL *n; | |
4073 int init; | |
4074 init=0; | |
4075 /* static local variables */ | |
4076 for(n = local_static_list;n!=&null_nptr;n = n->next) { | |
4077 if (n->sc == STATIC) { | |
4078 if (init==0) { | |
4079 data_mode(0); | |
4080 init=1; | |
4081 } | |
4082 if (n->dsp != -1) /* initialized static */ | |
4083 printf(".lcomm %s,%d\n",n->nm,size(n->ty)); | |
4084 } | |
4085 } | |
4086 } | |
4087 #endif | |
89 | 4088 |
4089 void | |
516 | 4090 cstring_mode(int align) |
4091 { | |
4092 if (output_mode!=RODATA_EMIT_MODE) { | |
662 | 4093 #ifdef __APPLE__ |
516 | 4094 printf(".cstring\n\t.align 2\n"); |
662 | 4095 #else |
4096 printf("\t.section\t.rodata\n\t.align 2\n"); | |
4097 #endif | |
516 | 4098 output_mode = RODATA_EMIT_MODE; |
4099 } | |
4100 } | |
4101 | |
4102 void | |
4103 text_mode(int align) | |
89 | 4104 { |
4105 if (output_mode!=TEXT_EMIT_MODE) { | |
4106 printf(".text\n"); | |
4107 printf("\t.align 2\n"); | |
4108 output_mode = TEXT_EMIT_MODE; | |
4109 } | |
4110 } | |
4111 | |
4112 void | |
4113 data_mode(char *name) | |
4114 { | |
4115 if (output_mode!=DATA_EMIT_MODE) { | |
4116 printf(".data\n"); | |
4117 output_mode = DATA_EMIT_MODE; | |
4118 } | |
108 | 4119 /* |
89 | 4120 if (name) |
4121 printf("\t.type\t%s,@object\n",name); | |
108 | 4122 */ |
89 | 4123 } |
4124 | |
195 | 4125 #if FLOAT_CODE |
4126 | |
89 | 4127 /* floating point */ |
4128 | |
96 | 4129 static int float_one_lib_used=0; |
4130 static char *float_one_lib[] = { | |
4131 ".data", | |
108 | 4132 /* ".literal8", */ |
96 | 4133 " .align 3", |
4134 "__float_one:", | |
4135 " .long 1065353216", | |
4136 ".text", | |
109 | 4137 /* ".set L__float_one$non_lazy_ptr,__float_one", */ |
96 | 4138 0 |
4139 }; | |
97 | 4140 static int float_zero_lib_used=0; |
4141 static char *float_zero_lib[] = { | |
4142 ".data", | |
108 | 4143 /* ".literal8", */ |
97 | 4144 " .align 3", |
4145 "__float_zero:", | |
4146 " .long 0", | |
4147 ".text", | |
109 | 4148 /* ".set L__float_zero$non_lazy_ptr,__float_zero", */ |
97 | 4149 0 |
4150 }; | |
4151 | |
739
0c7a6ae119ba
i64 continue... compiler compiled.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
726
diff
changeset
|
4152 char * fstore(int d) |
89 | 4153 { |
90 | 4154 return (d?"stfd":"stfs"); |
89 | 4155 } |
4156 | |
4157 char * | |
4158 fload(int d) | |
4159 { | |
90 | 4160 return d?"lfd":"lfs"; |
89 | 4161 } |
4162 | |
95 | 4163 void |
287 | 4164 code_cmp_dregister(int e2,int d,int label,int cond) |
95 | 4165 { |
99 | 4166 char *frn,*rrn,*grn; |
4167 int greg,r; | |
662 | 4168 grn = fregister_name(greg = get_dregister(d)); |
221 | 4169 use_float(d,e2); |
132 | 4170 frn = register_name(e2); |
99 | 4171 float_zero_lib_used=1; |
109 | 4172 r = get_ptr_cache(&float_zero); |
99 | 4173 rrn = register_name(r); |
108 | 4174 printf("\tlfs %s,0(%s)\n",grn,rrn); |
291 | 4175 inc_cmpflag(); |
662 | 4176 printf("\tfcmpu %s,%s,%s\n",crname(cmpflag),grn,frn); |
147 | 4177 free_register(greg); |
287 | 4178 jcond(label,cond); |
99 | 4179 return; |
95 | 4180 } |
4181 | |
4182 void | |
138 | 4183 code_dregister(int e2,int freg,int d) |
95 | 4184 { |
221 | 4185 use_float(d,freg); |
147 | 4186 if (freg!=e2) { |
4187 if (is_int_reg(e2)) error(-1); | |
108 | 4188 printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2)); |
147 | 4189 } |
95 | 4190 } |
4191 | |
211 | 4192 void |
4193 code_dassign_gvar(int e2,int freg,int d) | |
89 | 4194 { |
221 | 4195 use_float(d,freg); |
367 | 4196 code_ldf(fstore(d),fregister_name(freg),cadr(e2), |
711 | 4197 get_ptr_cache(ncaddr(e2))); |
89 | 4198 } |
4199 | |
211 | 4200 void |
4201 code_dassign_lvar(int e2,int freg,int d) | |
89 | 4202 { |
221 | 4203 use_float(d,freg); |
119 | 4204 lvar_intro(e2); |
4205 printf("\t%s %s,",fstore(d),fregister_name(freg)); | |
4206 lvar(e2); | |
89 | 4207 } |
4208 | |
211 | 4209 void |
4210 code_dassign(int e2,int freg,int d) | |
89 | 4211 { |
221 | 4212 use_float(d,freg); |
108 | 4213 printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2)); |
89 | 4214 } |
4215 | |
111 | 4216 void |
138 | 4217 code_dassign_dregister(int e2,int d,int freg) { |
221 | 4218 use_float(d,freg); |
147 | 4219 if (e2!=freg) { |
111 | 4220 printf("\tfmr %s,%s\n",fregister_name(e2),fregister_name(freg)); |
147 | 4221 } |
111 | 4222 } |
4223 | |
89 | 4224 static double d0 = 1.0; |
4225 | |
4226 int | |
4227 code_d1(double d) | |
4228 { | |
4229 int *i = (int *)&d0; int *j = (int *)&d; | |
99 | 4230 return (i[1] == 0x3ff00000)?j[0]:j[1]; |
89 | 4231 } |
4232 | |
4233 int | |
4234 code_d2(double d) | |
4235 { | |
4236 int *i = (int *)&d0; int *j = (int *)&d; | |
99 | 4237 return (i[1] == 0x3ff00000)?j[1]:j[0]; |
89 | 4238 } |
4239 | |
133 | 4240 int |
4241 code_f(double d) | |
4242 { | |
4243 float f = d; | |
4244 int *j = (int *)&f; | |
4245 return *j; | |
4246 } | |
4247 | |
779 | 4248 static void emit_dconst0(ValuePtr value, int lb, void *arg) |
4249 { | |
4250 long d = (long) arg; | |
4251 printf(" \t.data\n\t.align 3\n"); | |
4252 printf("%s%d:\n",lpfx,lb); | |
4253 if (d) { | |
4254 #if ENDIAN_D==0 | |
4255 printf("\t.long\t0x%x,0x%x\n",code_d1(value->d),code_d2(value->d)); | |
4256 #else | |
4257 printf("\t.long\t0x%x,0x%x\n",code_d2(value->d),code_d1(value->d)); | |
4258 #endif | |
4259 } else { | |
780
c5315f472912
ia32/powerpc regression test
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
779
diff
changeset
|
4260 printf("\t.long\t0x%x\n",code_f(value->f)); |
779 | 4261 } |
4262 if (output_mode==TEXT_EMIT_MODE) { | |
4263 printf(".text\n"); | |
4264 } else { | |
4265 text_mode(0); | |
4266 } | |
4267 } | |
4268 | |
4269 /* load double / float const | |
4270 we should keep what constant we have create | |
4271 */ | |
4272 | |
211 | 4273 void |
138 | 4274 code_dconst(int e2,int freg,int d) |
89 | 4275 { |
780
c5315f472912
ia32/powerpc regression test
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
779
diff
changeset
|
4276 int sz; |
779 | 4277 Value value; |
4278 value.d = dcadr(e2); | |
90 | 4279 int r; |
97 | 4280 char *rrn,*frn; |
221 | 4281 use_float(d,freg); |
97 | 4282 frn = fregister_name(freg); |
779 | 4283 if (value.d==0.0) { |
97 | 4284 float_zero_lib_used=1; |
109 | 4285 r = get_ptr_cache(&float_zero); |
98 | 4286 rrn = register_name(r); |
108 | 4287 printf("\tlfs %s,0(%s)\n",frn,rrn); |
97 | 4288 return; |
89 | 4289 } |
779 | 4290 if (value.d==1.0) { |
97 | 4291 float_one_lib_used=1; |
109 | 4292 r = get_ptr_cache(&float_one); |
98 | 4293 rrn = register_name(r); |
108 | 4294 printf("\tlfs %s,0(%s)\n",frn,rrn); |
97 | 4295 return; |
89 | 4296 } |
779 | 4297 if (d) { |
4298 sz = sizeof(double); | |
4299 } else { | |
4300 sz = sizeof(float); | |
4301 value.f = (float) value.d; | |
4302 } | |
4303 | |
4304 long d_mode = d; | |
4305 int lb = get_data_label(&value,sz,emit_dconst0, (void*) d_mode); | |
4306 | |
97 | 4307 rrn = register_name((r=get_register())); |
780
c5315f472912
ia32/powerpc regression test
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
779
diff
changeset
|
4308 // use_reg(r); // to clear ptr cache |
662 | 4309 code_label_value(lb,r); |
138 | 4310 if (d) { |
133 | 4311 printf("\tlfd %s,0(%s)\n",frn,rrn); |
4312 } else { | |
4313 printf("\tlfs %s,0(%s)\n",frn,rrn); | |
4314 } | |
90 | 4315 free_register(r); |
89 | 4316 } |
4317 | |
616 | 4318 void |
4319 code_builtin_fabsf(int e) | |
4320 { | |
4321 char *frn; | |
4322 g_expr0(e); | |
4323 use_float(0,freg); | |
4324 frn = fregister_name(freg); | |
4325 printf("\tfabs %s,%s\n",frn,frn); | |
4326 } | |
4327 | |
4328 void | |
4329 code_builtin_fabs(int e) | |
4330 { | |
4331 char *frn; | |
4332 g_expr0(e); | |
4333 use_float(1,freg); | |
4334 frn = fregister_name(freg); | |
4335 printf("\tfabs %s,%s\n",frn,frn); | |
4336 } | |
4337 | |
4338 static void | |
4339 code_inf(int d) | |
4340 { | |
4341 int lb; | |
4342 int r; | |
4343 char *rrn,*frn; | |
4344 int freg = USE_CREG; | |
4345 | |
4346 use_float(d,freg); | |
4347 frn = fregister_name(freg); | |
4348 rrn = register_name((r=get_register())); | |
4349 use_reg(r); // to clear ptr cache | |
4350 printf(" \t.data\n\t.align 3\n"); | |
4351 lb=fwdlabel(); | |
4352 printf("L_%d:\n",lb); | |
4353 if (d) { | |
4354 #if ENDIAN_D==0 | |
4355 printf("\t.long\t0x%x,0x%x\n",0,0x7ff00000); | |
4356 #else | |
4357 printf("\t.long\t0x%x,0x%x\n",0x7ff00000,0); | |
4358 #endif | |
4359 } else { | |
4360 printf("\t.long\t0x%x\n",0x7f800000); | |
4361 } | |
4362 if (output_mode==TEXT_EMIT_MODE) { | |
4363 printf(".text\n"); | |
4364 } else { | |
4365 text_mode(0); | |
4366 } | |
662 | 4367 code_label_value(lb,r); |
616 | 4368 if (d) { |
4369 printf("\tlfd %s,0(%s)\n",frn,rrn); | |
4370 } else { | |
4371 printf("\tlfs %s,0(%s)\n",frn,rrn); | |
4372 } | |
4373 free_register(r); | |
4374 } | |
4375 | |
4376 void | |
4377 code_builtin_inff() | |
4378 { | |
4379 code_inf(0); | |
4380 } | |
4381 | |
4382 void | |
4383 code_builtin_inf() | |
4384 { | |
4385 code_inf(1); | |
4386 } | |
4387 | |
4388 | |
133 | 4389 |
211 | 4390 void |
4391 code_dneg(int freg,int d) | |
89 | 4392 { |
221 | 4393 char *frn; |
4394 use_float(d,freg); | |
4395 frn = fregister_name(freg); | |
95 | 4396 printf("\tfneg %s,%s\n",frn,frn); |
89 | 4397 } |
4398 | |
211 | 4399 void |
221 | 4400 code_d2i() |
89 | 4401 { |
147 | 4402 char *frn; |
4403 char *crn; | |
245 | 4404 int e2 = new_lvar(SIZE_OF_DOUBLE); |
147 | 4405 |
221 | 4406 use_double0(); |
4407 frn = fregister_name(freg); | |
4408 use_int0(); | |
147 | 4409 crn = register_name(creg); |
4410 | |
119 | 4411 free_lvar(e2); |
93 | 4412 printf("\tfctiwz %s,%s\n",frn,frn); |
119 | 4413 lvar_intro(e2); |
4414 printf("\tstfd %s,",frn); lvar(e2); | |
245 | 4415 lvar_intro(e2+SIZE_OF_DOUBLE-SIZE_OF_INT); |
4416 printf("\tlwz %s,",crn); lvar(e2+SIZE_OF_DOUBLE-SIZE_OF_INT); | |
89 | 4417 } |
4418 | |
91 | 4419 static int i2d_lib_used=0; |
662 | 4420 #ifdef __APPLE__ |
91 | 4421 static char *i2d_lib[] = { |
4422 ".data", | |
108 | 4423 /* ".literal8", */ |
91 | 4424 " .align 3", |
4425 "__i2dLC0:", | |
4426 " .long 1127219200", | |
4427 " .long -2147483648", | |
4428 ".text", | |
4429 " .align 2", | |
111 | 4430 "i2d_:", |
91 | 4431 " mflr r0", |
4432 " bcl 20,31,__i2dL1$pb", | |
4433 "__i2dL1$pb:", | |
4434 " mflr r10", | |
4435 " mtlr r0", | |
4436 " xoris r3,r3,0x8000", | |
375 | 4437 " stw r3,-28(r1)", |
91 | 4438 " lis r0,0x4330", |
375 | 4439 " stw r0,-32(r1)", |
4440 " lfd f0,-32(r1)", | |
91 | 4441 " addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)", |
4442 " lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)", | |
4443 " fsub f1,f0,f1", | |
4444 " blr", | |
4445 0 | |
4446 }; | |
662 | 4447 #else |
4448 static char *i2d_lib[] = { | |
4449 ".data", | |
4450 /* ".literal8", */ | |
4451 " .align 3", | |
663 | 4452 "__i2dLC0:", |
662 | 4453 " .long 1127219200", |
4454 " .long -2147483648", | |
4455 ".text", | |
4456 " .align 2", | |
4457 "i2d_:", | |
4458 " xoris 3,3,0x8000", | |
4459 " stw 3,-28(1)", | |
4460 " lis 0,0x4330", | |
4461 " stw 0,-32(1)", | |
4462 " lfd 0,-32(1)", | |
673 | 4463 " lis 9,__i2dLC0@ha", |
4464 " lfd 1,__i2dLC0@l(9)", | |
662 | 4465 " fsub 1,0,1", |
4466 " blr", | |
4467 0 | |
4468 }; | |
4469 #endif | |
91 | 4470 |
211 | 4471 void |
221 | 4472 code_i2d() |
89 | 4473 { |
95 | 4474 i2d_lib_used = 1; |
113 | 4475 clear_ptr_cache(); |
4476 code_save_stacks(); | |
207 | 4477 set_ireg(RET_REGISTER,1); |
91 | 4478 printf("\tbl i2d_\n"); |
104 | 4479 set_freg(RET_FREGISTER,0); |
89 | 4480 } |
4481 | |
91 | 4482 static int d2u_lib_used=0; |
662 | 4483 #ifdef __APPLE__ |
91 | 4484 static char *d2u_lib[] = { |
108 | 4485 /* ".literal8", */ |
91 | 4486 " .align 3", |
4487 "__d2uLC0:", | |
4488 " .long 1105199104", | |
4489 " .long 0", | |
4490 ".text", | |
4491 " .align 2", | |
111 | 4492 "d2u_:", |
91 | 4493 " mflr r0", |
4494 " bcl 20,31,__d2uL1$pb", | |
4495 "__d2uL1$pb:", | |
4496 " mflr r10", | |
4497 " mtlr r0", | |
4498 " addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)", | |
4499 " lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)", | |
4500 " fcmpu cr0,f1,f0", | |
4501 " cror 2,1,2", | |
4502 " beq- cr0,__d2uL2", | |
4503 " fctiwz f0,f1", | |
375 | 4504 " stfd f0,-32(r1)", |
4505 " lwz r3,-28(r1)", | |
91 | 4506 " blr", |
4507 "__d2uL2:", | |
4508 " addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)", | |
4509 " lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)", | |
4510 " fsub f0,f1,f0", | |
4511 " fctiwz f0,f0", | |
375 | 4512 " stfd f0,-24(r1)", |
4513 " lwz r3,-20(r1)", | |
91 | 4514 " xoris r3,r3,0x8000", |
4515 " blr", | |
4516 0 | |
4517 }; | |
662 | 4518 #else |
4519 static char *d2u_lib[] = { | |
4520 /* ".literal8", */ | |
4521 " .align 3", | |
4522 "__d2uLC0:", | |
4523 " .long 1105199104", | |
4524 " .long 0", | |
4525 ".text", | |
4526 " .align 2", | |
4527 "d2u_:", | |
673 | 4528 " lis 9,__d2uLC0@ha", |
4529 " lfd 0,__d2uLC0@l(9)", | |
663 | 4530 " fcmpu 0,1,0", |
662 | 4531 " cror 2,1,2", |
663 | 4532 " beq- 0,__d2uL2", |
4533 " fctiwz 0,1", | |
4534 " stfd 0,-32(1)", | |
4535 " lwz 3,-28(1)", | |
662 | 4536 " blr", |
4537 "__d2uL2:", | |
673 | 4538 " lis 9,__d2uLC0@ha", |
4539 " lfd 0,__d2uLC0@l(9)", | |
663 | 4540 " fsub 0,1,0", |
4541 " fctiwz 0,0", | |
4542 " stfd 0,-24(1)", | |
4543 " lwz 3,-20(1)", | |
4544 " xoris 3,3,0x8000", | |
662 | 4545 " blr", |
4546 0 | |
4547 }; | |
4548 #endif | |
91 | 4549 |
211 | 4550 void |
221 | 4551 code_d2u() |
89 | 4552 { |
113 | 4553 code_save_stacks(); |
4554 clear_ptr_cache(); | |
91 | 4555 d2u_lib_used=1; |
104 | 4556 set_freg(RET_FREGISTER,1); |
111 | 4557 printf("\tbl d2u_\n"); |
207 | 4558 set_ireg(RET_REGISTER,0); |
91 | 4559 } |
90 | 4560 |
91 | 4561 static int u2d_lib_used=0; |
662 | 4562 #ifdef __APPLE__ |
91 | 4563 static char *u2d_lib[] = { |
4564 ".data", | |
108 | 4565 /* ".literal8", */ |
91 | 4566 " .align 3", |
4567 "__u2dLC1:", | |
4568 " .long 1127219200", | |
4569 " .long 0", | |
4570 ".text", | |
4571 " .align 2", | |
111 | 4572 "u2d_:", |
91 | 4573 " mflr r0", |
4574 " bcl 20,31,__u2dL2$pb", | |
4575 "__u2dL2$pb:", | |
4576 " mflr r10", | |
4577 " mtlr r0", | |
375 | 4578 " stw r3,-28(r1)", |
91 | 4579 " lis r0,0x4330", |
375 | 4580 " stw r0,-32(r1)", |
4581 " lfd f0,-32(r1)", | |
91 | 4582 " addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)", |
4583 " lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)", | |
4584 " fsub f1,f0,f1", | |
4585 " blr", | |
4586 0 | |
4587 }; | |
662 | 4588 #else |
4589 static char *u2d_lib[] = { | |
4590 ".data", | |
4591 /* ".literal8", */ | |
4592 " .align 3", | |
4593 "__u2dLC1:", | |
4594 " .long 1127219200", | |
4595 " .long 0", | |
4596 ".text", | |
4597 " .align 2", | |
673 | 4598 ".u2d_:", |
4599 " stw 3,-28(1)", | |
4600 " lis 0,0x4330", | |
4601 " stw 0,-32(1)", | |
4602 " lfd 0,-32(1)", | |
4603 " lis 9,__u2dLC1@ha", | |
4604 " lfd 1,__u2dLC1@l(9)", | |
4605 " fsub 1,0,1", | |
662 | 4606 " blr", |
4607 0 | |
4608 }; | |
4609 #endif | |
89 | 4610 |
211 | 4611 void |
221 | 4612 code_u2d() |
89 | 4613 { |
113 | 4614 code_save_stacks(); |
4615 clear_ptr_cache(); | |
147 | 4616 u2d_lib_used = 1; |
207 | 4617 set_ireg(RET_REGISTER,1); |
673 | 4618 #ifdef __APPLE__ |
111 | 4619 printf("\tbl u2d_\n"); |
673 | 4620 #else |
4621 printf("\tbl .u2d_\n"); | |
4622 #endif | |
228 | 4623 set_freg(RET_FREGISTER,0); |
89 | 4624 } |
4625 | |
211 | 4626 void |
221 | 4627 code_d2f() { } |
211 | 4628 void |
221 | 4629 code_f2d() { } |
211 | 4630 void |
221 | 4631 code_f2i() { code_d2i(); } |
211 | 4632 void |
221 | 4633 code_f2u() { code_d2u(); } |
211 | 4634 void |
221 | 4635 code_i2f() { code_i2d(); } |
211 | 4636 void |
221 | 4637 code_u2f() { code_u2d(); } |
211 | 4638 |
4639 void | |
4640 code_drgvar(int e2,int d,int freg) | |
89 | 4641 { |
221 | 4642 use_float(d,freg); |
367 | 4643 code_ldf(fload(d),fregister_name(freg),cadr(e2), |
711 | 4644 get_ptr_cache(ncaddr(e2))); |
89 | 4645 } |
4646 | |
4647 | |
211 | 4648 void |
4649 code_drlvar(int e2,int d,int freg) | |
89 | 4650 { |
221 | 4651 use_float(d,freg); |
119 | 4652 lvar_intro(e2); |
4653 printf("\t%s %s,",fload(d),fregister_name(freg)); lvar(e2); | |
89 | 4654 } |
4655 | |
211 | 4656 void |
287 | 4657 code_cmp_drgvar(int e2,int reg,int d,int label,int cond) |
89 | 4658 { |
221 | 4659 char *frn; |
138 | 4660 int g=get_dregister(d); |
97 | 4661 char *grn=fregister_name(g); |
221 | 4662 |
4663 use_float(d,reg); | |
4664 frn=fregister_name(reg); | |
4665 | |
367 | 4666 code_ldf(fload(1),grn,cadr(e2), |
711 | 4667 get_ptr_cache(ncaddr(e2))); |
291 | 4668 inc_cmpflag(); |
662 | 4669 printf("\tfcmpu %s,%s,%s\n",crname(cmpflag),frn,grn); |
147 | 4670 free_register(g); |
287 | 4671 jcond(label,cond); |
89 | 4672 } |
4673 | |
211 | 4674 void |
287 | 4675 code_cmp_drlvar(int e2,int reg,int d,int label,int cond) |
89 | 4676 { |
221 | 4677 char *frn; |
138 | 4678 int g=get_dregister(d); |
97 | 4679 char *grn=fregister_name(g); |
108 | 4680 |
221 | 4681 use_float(d,reg); |
4682 frn=fregister_name(reg); | |
4683 | |
119 | 4684 lvar_intro(e2); |
4685 printf("\t%s %s,",fload(1),grn); lvar(e2); | |
291 | 4686 inc_cmpflag(); |
662 | 4687 printf("\tfcmpu %s,%s,%s\n",crname(cmpflag),frn,grn); |
147 | 4688 free_register(g); |
287 | 4689 jcond(label,cond); |
89 | 4690 } |
4691 | |
211 | 4692 void |
273 | 4693 dtosop(int op,int reg,int oreg) |
89 | 4694 { |
127 | 4695 char *opn=""; |
221 | 4696 char *frn; |
273 | 4697 char *grn; |
4698 int ox = -1; | |
221 | 4699 |
4700 use_float(1,reg); | |
273 | 4701 if(oreg==-1) { |
4702 error(-1); | |
4703 } else if (oreg<= -REG_LVAR_OFFSET) { | |
4704 ox = get_dregister(1); if (ox<0) error(-1); | |
4705 use_reg(ox); | |
4706 code_drlvar(oreg+REG_LVAR_OFFSET,1,ox); | |
4707 oreg = ox; | |
4708 } | |
4709 grn=fregister_name(oreg); | |
221 | 4710 frn=fregister_name(reg); |
89 | 4711 switch(op) { |
133 | 4712 case FADD: |
91 | 4713 case DADD: opn="fadd"; break; |
133 | 4714 case FSUB: |
101 | 4715 case DSUB: opn="fsub"; break; |
133 | 4716 case FDIV: |
101 | 4717 case DDIV: opn="fdiv"; break; |
133 | 4718 case FMUL: |
101 | 4719 case DMUL: opn="fmul"; break; |
133 | 4720 case FCMP: |
91 | 4721 case DCMP: |
291 | 4722 inc_cmpflag(); |
662 | 4723 printf("\tfcmpu %s,%s,%s\n",crname(cmpflag),frn,grn); |
273 | 4724 if (ox!=-1) free_register(ox); |
101 | 4725 return; |
133 | 4726 case FCMPGE: |
91 | 4727 case DCMPGE: |
291 | 4728 inc_cmpflag(); |
662 | 4729 printf("\tfcmpu %s,%s,%s\n",crname(cmpflag),frn,grn); |
273 | 4730 if (ox!=-1) free_register(ox); |
101 | 4731 return; |
133 | 4732 default: |
4733 error(-1); return; | |
89 | 4734 } |
91 | 4735 printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); |
273 | 4736 if (ox!=-1) free_register(ox); |
89 | 4737 } |
4738 | |
4739 void | |
221 | 4740 code_dassop(int op,int reg,int d) { |
91 | 4741 /* we have lvalue in creg, applied floating value is in freg */ |
221 | 4742 // (*creg) op = pop() |
138 | 4743 int xreg=emit_dpop(d); |
221 | 4744 char *crn; |
209 | 4745 char *frn; |
221 | 4746 |
4747 crn=register_name(ireg); | |
4748 use_float(d,reg); | |
4749 frn =fregister_name(reg); | |
209 | 4750 |
108 | 4751 printf("\t%s %s,0(%s)\n",fload(d),frn,crn); |
221 | 4752 dtosop(op,reg,xreg); |
108 | 4753 printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); |
138 | 4754 emit_dpop_free(xreg,d); |
89 | 4755 } |
4756 | |
219 | 4757 void |
4758 code_register_dassop(int reg,int op,int d) { | |
221 | 4759 // reg op= dpop() |
219 | 4760 int xreg=emit_dpop(d); |
221 | 4761 dtosop(op,reg,xreg); |
4762 emit_dpop_free(xreg,d); | |
219 | 4763 } |
91 | 4764 |
273 | 4765 static int |
4766 code_dload_1(int d) | |
4767 { | |
4768 int r,g; | |
4769 char *drn,*grn; | |
4770 // load 1 | |
4771 float_one_lib_used=1; | |
4772 r = get_ptr_cache(&float_one); | |
4773 drn=register_name(r); | |
4774 grn=fregister_name(g=get_dregister(d)); | |
4775 printf("\tlfs %s,0(%s)\n",grn,drn); | |
4776 return g; | |
4777 } | |
4778 | |
89 | 4779 void |
107 | 4780 code_dpreinc(int e1,int e2,int d,int reg) { |
273 | 4781 char *frn,*crn,*grn; |
91 | 4782 int g; |
4783 | |
144 | 4784 if (car(e2)==DREGISTER||car(e2)==FREGISTER) { |
221 | 4785 crn=register_name(cadr(e2)); |
273 | 4786 grn = fregister_name(g = code_dload_1(d)); |
4787 if (reg==USE_CREG) { | |
4788 reg=get_dregister(d); if (!reg) error(-1); | |
4789 set_freg(reg,0); | |
4790 } | |
4791 frn=fregister_name(reg); | |
4792 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn); | |
4793 if (use && reg!=cadr(e2)) | |
4794 printf("\tfmr %s,%s\n",frn,crn); | |
221 | 4795 } else { |
4796 g_expr(e2); | |
4797 if (!is_int_reg(creg)) error(-1); | |
4798 crn=register_name(ireg); | |
273 | 4799 if (reg==USE_CREG) { |
4800 reg=get_dregister(d); if (!reg) error(-1); | |
4801 set_freg(reg,0); | |
4802 } | |
4803 frn=fregister_name(reg); | |
4804 grn = fregister_name(g = code_dload_1(d)); | |
221 | 4805 printf("\t%s %s,0(%s)\n",fload(d),frn,crn); |
4806 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",frn,frn,grn); | |
4807 printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); | |
4808 } | |
147 | 4809 free_register(g); |
89 | 4810 } |
4811 | |
4812 void | |
107 | 4813 code_dpostinc(int e1,int e2,int d,int reg) { |
273 | 4814 char *frn,*crn,*grn; |
91 | 4815 int g; |
4816 | |
144 | 4817 if (car(e2)==DREGISTER||car(e2)==FREGISTER) { |
221 | 4818 crn=register_name(cadr(e2)); |
273 | 4819 grn = fregister_name(g = code_dload_1(d)); |
4820 if (reg==USE_CREG) { | |
4821 reg=get_dregister(d); if (!reg) error(-1); | |
4822 set_freg(reg,0); | |
4823 } | |
4824 frn=fregister_name(reg); | |
4825 if (use && reg!=cadr(e2)) | |
4826 printf("\tfmr %s,%s\n",frn,crn); | |
4827 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn); | |
221 | 4828 } else { |
4829 g_expr(e2); | |
4830 if (!is_int_reg(creg)) error(-1); | |
273 | 4831 crn=register_name(ireg); |
4832 if (reg==USE_CREG) { | |
4833 reg=get_dregister(d); if (!reg) error(-1); | |
4834 set_freg(reg,0); | |
4835 } | |
4836 frn=fregister_name(reg); | |
4837 grn = fregister_name(g = code_dload_1(d)); | |
221 | 4838 printf("\t%s %s,0(%s)\n",fload(d),frn,crn); |
4839 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",grn,frn,grn); | |
4840 printf("\t%s %s,0(%s)\n",fstore(d),grn,crn); | |
4841 } | |
147 | 4842 free_register(g); |
89 | 4843 } |
4844 | |
288 | 4845 static int |
4846 drexpr_bool(int e1,int reg) | |
4847 { | |
289 | 4848 int flag=-1,eq=-1,neg=-1,t; |
288 | 4849 char *rn; |
4850 switch(car(e1)) { | |
4851 case DOP+GT: case FOP+GT: flag = 2; break; | |
4852 case DOP+GE: case FOP+GE: flag = 2; eq=3; break; | |
4853 case DOP+LT: case FOP+LT: flag = 1; break; | |
4854 case DOP+LE: case FOP+LE: flag = 1; eq=3; break; | |
4855 case DOP+EQ: case FOP+EQ: flag = 3; break; | |
289 | 4856 case DOP+NEQ: case FOP+NEQ: flag = 3; neg=3; break; |
288 | 4857 default: return 0; |
4858 } | |
4859 g_expr(list3(DCMP,cadr(e1),caddr(e1))); | |
4860 use_int(reg); | |
4861 rn = register_name(reg); | |
289 | 4862 t = CRBITSIZ*cmpflag; |
288 | 4863 if (eq>0) { |
289 | 4864 printf("\tcror %d,%d,%d\n",t+flag-1,t+eq-1,t+flag-1); |
4865 } | |
4866 if (neg>0) { | |
4867 neg = t+neg-1, | |
4868 printf("\tcrnor %d,%d,%d\n",neg,neg,neg); | |
288 | 4869 } |
4870 printf("\tmfcr %s\n",rn); | |
289 | 4871 printf("\trlwinm %s,%s,%d,1\n",rn,rn,t+flag); |
288 | 4872 return 1; |
4873 } | |
4874 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4875 int |
229 | 4876 drexpr(int e1, int e2,int l1, int op,int cond) |
4877 { | |
231 | 4878 if (!cond) { |
229 | 4879 switch(op) { |
4880 case FOP+GT: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4881 return drexpr(e2,e1,l1,FOP+GE,1); |
229 | 4882 case FOP+GE: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4883 return drexpr(e2,e1,l1,FOP+GT,1); |
229 | 4884 case FOP+EQ: |
4885 op=FOP+NEQ; break; | |
4886 case FOP+NEQ: | |
4887 op=FOP+EQ; break; | |
4888 case DOP+GT: | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4889 return drexpr(e2,e1,l1,DOP+GE,1); |
229 | 4890 case DOP+GE: |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4891 return drexpr(e2,e1,l1,DOP+GT,1); |
229 | 4892 case DOP+EQ: |
4893 op=DOP+NEQ; break; | |
4894 case DOP+NEQ: | |
4895 op=DOP+EQ; break; | |
4896 } | |
4897 } | |
234 | 4898 g_expr(list3(DCMP, e1,e2)); |
89 | 4899 switch(op) { |
288 | 4900 case DOP+GT: case FOP+GT: |
662 | 4901 printf("\tbgt\t%s,%s%d\n",crname(cmpflag),lpfx,l1); |
288 | 4902 break; |
4903 case DOP+GE: case FOP+GE: | |
662 | 4904 printf("\tbge\t%s,%s%d\n",crname(cmpflag),lpfx,l1); |
229 | 4905 break; |
288 | 4906 case DOP+EQ: case FOP+EQ: |
662 | 4907 printf("\tbeq\t%s,%s%d\n",crname(cmpflag),lpfx,l1); |
89 | 4908 break; |
288 | 4909 case DOP+NEQ: case FOP+NEQ: |
662 | 4910 printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,l1); |
89 | 4911 break; |
4912 } | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4913 return l1; |
89 | 4914 } |
4915 | |
138 | 4916 int emit_dpop(int d) |
89 | 4917 { |
114 | 4918 int xreg,reg; |
97 | 4919 xreg=pop_fregister(); |
4920 if (xreg<= -REG_LVAR_OFFSET) { | |
138 | 4921 reg = get_dregister(d); |
119 | 4922 code_drlvar(REG_LVAR_OFFSET+xreg,1,reg); |
117 | 4923 free_lvar(REG_LVAR_OFFSET+xreg); |
205 | 4924 xreg=reg; |
96 | 4925 } |
4926 return xreg; | |
89 | 4927 } |
4928 | |
211 | 4929 void |
4930 emit_dpop_free(int e1,int d) | |
89 | 4931 { |
590 | 4932 if (e1>=0 && e1!=creg && regs[e1]!=REG_VAR) |
4933 free_register(e1); | |
89 | 4934 } |
4935 | |
211 | 4936 void |
4937 emit_dpush(int d) | |
89 | 4938 { |
97 | 4939 int new_reg; |
221 | 4940 if (!is_float_reg(creg)) error(-1); |
102 | 4941 if (freg_sp>MAX_MAX) error(-1); |
724 | 4942 new_reg = get_dregister(1); /* 絶対に取れる */ |
4943 freg_stack[freg_sp++] = freg; /* push するかわりにレジスタを使う */ | |
147 | 4944 creg = freg = new_reg; |
89 | 4945 } |
4946 | |
195 | 4947 #endif |
4948 | |
4949 #if LONGLONG_CODE | |
4950 | |
4951 | |
4952 /* 64bit int part */ | |
219 | 4953 static void |
530 | 4954 lmove(int to,int from) // to <= from |
219 | 4955 { |
227 | 4956 int tmp; |
4957 if (regv_h(to)==regv_l(from)&&(regv_l(to)==regv_h(from))) { | |
4958 tmp = get_register(); | |
228 | 4959 printf("\tmr %s,%s\n",register_name(tmp),lregister_name_low(from)); |
227 | 4960 printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); |
4961 printf("\tmr %s,%s\n",lregister_name_low(to),register_name(tmp)); | |
4962 free_register(tmp); | |
4963 } else if (regv_h(to)==regv_l(from)) { | |
226 | 4964 printf("\tmr %s,%s\n",lregister_name_low(to),lregister_name_low(from)); |
4965 printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); | |
4966 } else { | |
4967 printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); | |
4968 printf("\tmr %s,%s\n",lregister_name_low(to),lregister_name_low(from)); | |
4969 } | |
219 | 4970 } |
195 | 4971 |
211 | 4972 static void |
280 | 4973 pcond(char *s,int cmpflag,int l1) |
4974 { | |
662 | 4975 printf("\tb%s %s,%s%d\n",s,crname(cmpflag),lpfx,l1); |
280 | 4976 } |
4977 | |
4978 static int | |
4979 lcmp(int op,int cond) | |
210 | 4980 { |
280 | 4981 if (op==LOP+UGT||op==LOP+UGE) { |
4982 return UCMP; | |
4983 } else if (op==LOP+LE||op==LOP+GE) { | |
4984 return CMP; | |
4985 } else { | |
4986 return CMP; | |
4987 } | |
210 | 4988 } |
4989 | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
4990 int |
229 | 4991 lrexpr(int e1, int e2,int l1, int op,int cond) |
195 | 4992 { |
221 | 4993 int reg; |
210 | 4994 int e3; |
280 | 4995 int l2; |
4996 int op1,cr0,cr1; | |
4997 | |
210 | 4998 g_expr(e1); |
4999 emit_lpush(); | |
5000 g_expr(e2); | |
5001 e3 = emit_lpop(); | |
221 | 5002 if (!is_longlong_reg(creg)) error(-1); |
5003 reg = lreg; | |
280 | 5004 op1 = lcmp(op,cond); |
5005 tosop(op1,regv_h(e3),regv_h(reg)); | |
5006 cr0 = cmpflag; | |
291 | 5007 tosop(op1,regv_l(e3),regv_l(reg)); |
280 | 5008 cr1 = cmpflag; |
5009 | |
5010 l2 = fwdlabel(); | |
5011 // cond==0 jump on false condtion ( if(x) => rexpr(.. cond=0 ...) ) | |
433 | 5012 switch(op+(!cond)*BNOT) { |
210 | 5013 case LOP+GT: |
5014 case LOP+GE: | |
433 | 5015 pcond(code_gt(1),cr0,1?l1:l2); |
5016 pcond(code_eq(0),cr0,1?l2:l1); | |
280 | 5017 break; |
5018 case LOP+UGT: | |
5019 case LOP+UGE: | |
433 | 5020 pcond(code_ugt(1),cr0,1?l1:l2); |
5021 pcond(code_eq(0), cr0,1?l2:l1); | |
280 | 5022 break; |
210 | 5023 case LOP+EQ: |
433 | 5024 pcond(code_eq(0),cr0,(1?l2:l1)); |
280 | 5025 pcond(code_eq(cond),cr1,l1); |
5026 break; | |
210 | 5027 case LOP+NEQ: |
433 | 5028 pcond(code_eq(0),cr0,(1?l1:l2)); |
5029 pcond(code_eq(!1),cr1,l1); | |
5030 break; | |
5031 case LOP+GT+BNOT: | |
5032 case LOP+GE+BNOT: | |
5033 pcond(code_gt(1),cr0,0?l1:l2); | |
5034 pcond(code_eq(0),cr0,0?l2:l1); | |
5035 break; | |
5036 case LOP+UGT+BNOT: | |
5037 case LOP+UGE+BNOT: | |
5038 pcond(code_ugt(1),cr0,0?l1:l2); | |
5039 pcond(code_eq(0), cr0,0?l2:l1); | |
5040 break; | |
5041 case LOP+EQ+BNOT: | |
5042 pcond(code_eq(0),cr0,(0?l2:l1)); | |
5043 pcond(code_eq(0),cr1,l1); | |
5044 break; | |
5045 case LOP+NEQ+BNOT: | |
5046 pcond(code_eq(0),cr0,(0?l1:l2)); | |
5047 pcond(code_eq(!0),cr1,l1); | |
280 | 5048 break; |
210 | 5049 default: |
5050 error(-1); | |
5051 } | |
433 | 5052 switch(op+BNOT*(!cond)) { |
5053 case LOP+GT: pcond(code_gt(1), cr1,l1); break; | |
5054 case LOP+GE: pcond(code_ge(1), cr1,l1); break; | |
5055 case LOP+UGT: pcond(code_ugt(1), cr1,l1); break; | |
5056 case LOP+UGE: pcond(code_uge(1), cr1,l1); break; | |
5057 case LOP+GT+BNOT: pcond(code_gt(0), cr1,l1); break; | |
5058 case LOP+GE+BNOT: pcond(code_ge(0), cr1,l1); break; | |
5059 case LOP+UGT+BNOT: pcond(code_ugt(0), cr1,l1); break; | |
5060 case LOP+UGE+BNOT: pcond(code_uge(0), cr1,l1); break; | |
280 | 5061 } |
5062 fwddef(l2); | |
5063 emit_lpop_free(e3); | |
438
626d705471d5
Unexecuted code in conditional. Lazy jmp code generation.
kono
parents:
436
diff
changeset
|
5064 return l1; |
280 | 5065 } |
195 | 5066 |
211 | 5067 int |
5068 emit_lpop() | |
195 | 5069 { |
210 | 5070 int xreg,reg; |
237 | 5071 xreg=lreg_stack[--lreg_sp]; |
210 | 5072 if (xreg<= -REG_LVAR_OFFSET) { |
5073 reg = get_lregister(); | |
5074 code_lrlvar(REG_LVAR_OFFSET+xreg,reg); | |
5075 free_lvar(REG_LVAR_OFFSET+xreg); | |
5076 xreg = reg; | |
5077 } | |
5078 return xreg; | |
195 | 5079 } |
5080 | |
211 | 5081 void |
5082 code_lregister(int e2,int reg) | |
195 | 5083 { |
221 | 5084 use_longlong(reg); |
5085 if (reg!=e2) { | |
5086 lmove(reg,e2); | |
211 | 5087 } |
195 | 5088 } |
5089 | |
211 | 5090 void |
287 | 5091 code_cmp_lregister(int reg,int label,int cond) |
195 | 5092 { |
221 | 5093 use_longlong(reg); |
211 | 5094 printf("\tor %s,%s,%s\n", |
5095 lregister_name_low(reg), | |
5096 lregister_name_low(reg), | |
5097 lregister_name_high(reg)); | |
291 | 5098 inc_cmpflag(); |
662 | 5099 printf("\tcmpwi %s,%s,0\n",crname(cmpflag),lregister_name_low(reg)); |
287 | 5100 jcond(label,cond); |
195 | 5101 } |
5102 | |
211 | 5103 void |
287 | 5104 code_cmp_lrgvar(int e1,int creg,int label,int cond) |
195 | 5105 { |
221 | 5106 use_longlong(creg); |
211 | 5107 code_lrgvar(e1,creg); |
287 | 5108 code_cmp_lregister(creg,label,cond); |
211 | 5109 } |
5110 | |
5111 void | |
287 | 5112 code_cmp_lrlvar(int e1,int creg,int label,int cond) |
211 | 5113 { |
221 | 5114 use_longlong(creg); |
211 | 5115 code_lrlvar(e1,creg); |
287 | 5116 code_cmp_lregister(creg,label,cond); |
195 | 5117 } |
5118 | |
211 | 5119 void |
5120 code_lassign(int e2,int creg) | |
195 | 5121 { |
211 | 5122 char *drn = register_name(e2); |
221 | 5123 char *crn_h; |
5124 char *crn_l; | |
5125 | |
5126 use_longlong(creg); | |
5127 crn_h = lregister_name_high(creg); | |
5128 crn_l = lregister_name_low(creg); | |
411 | 5129 #if ENDIAN_L==0 |
5130 printf("\tstw %s,0(%s)\n",crn_l,drn); | |
5131 printf("\tstw %s,%d(%s)\n",crn_h,SIZE_OF_INT,drn); | |
5132 #else | |
271 | 5133 printf("\tstw %s,0(%s)\n",crn_h,drn); |
5134 printf("\tstw %s,%d(%s)\n",crn_l,SIZE_OF_INT,drn); | |
411 | 5135 #endif |
195 | 5136 } |
5137 | |
211 | 5138 void |
5139 code_lassign_gvar(int e2,int creg) | |
195 | 5140 { |
211 | 5141 int r; |
367 | 5142 use_longlong(creg); |
711 | 5143 r = get_ptr_cache(ncaddr(e2)); |
411 | 5144 #if ENDIAN_L==0 |
5145 code_ldf(cstore(0),lregister_name_low(creg),cadr(e2),r); | |
5146 code_ldf(cstore(0),lregister_name_high(creg),cadr(e2)+SIZE_OF_INT,r); | |
5147 #else | |
367 | 5148 code_ldf(cstore(0),lregister_name_high(creg),cadr(e2),r); |
5149 code_ldf(cstore(0),lregister_name_low(creg),cadr(e2)+SIZE_OF_INT,r); | |
411 | 5150 #endif |
195 | 5151 } |
5152 | |
211 | 5153 void |
5154 code_lassign_lvar(int e2,int creg) | |
195 | 5155 { |
221 | 5156 char *crn_h; |
5157 char *crn_l; | |
5158 | |
5159 use_longlong(creg); | |
5160 crn_h = lregister_name_high(creg); | |
5161 crn_l = lregister_name_low(creg); | |
211 | 5162 lvar_intro(e2); |
411 | 5163 #if ENDIAN_L==0 |
5164 printf("\tstw %s,",crn_l);lvar(e2); | |
5165 printf("\tstw %s,",crn_h);lvar(e2+SIZE_OF_INT); | |
5166 #else | |
211 | 5167 printf("\tstw %s,",crn_h);lvar(e2); |
245 | 5168 printf("\tstw %s,",crn_l);lvar(e2+SIZE_OF_INT); |
411 | 5169 #endif |
195 | 5170 } |
5171 | |
211 | 5172 void |
5173 code_lassign_lregister(int e2,int reg) | |
195 | 5174 { |
221 | 5175 use_longlong(reg); |
219 | 5176 if (e2!=reg) { |
5177 lmove(e2,reg); | |
211 | 5178 } |
195 | 5179 } |
5180 | |
207 | 5181 static long long ll0 = 1LL; |
206 | 5182 |
5183 static int | |
5184 code_l1(long long d) | |
5185 { | |
207 | 5186 int *i = (int *)&ll0; int *j = (int *)&d; |
206 | 5187 return (i[1] == 1)?j[1]:j[0]; |
5188 } | |
5189 | |
5190 static int | |
5191 code_l2(long long d) | |
5192 { | |
207 | 5193 int *i = (int *)&ll0; int *j = (int *)&d; |
206 | 5194 return (i[1] == 1)?j[0]:j[1]; |
5195 } | |
5196 | |
211 | 5197 void |
5198 code_lconst(int e1,int creg) | |
5199 { | |
221 | 5200 use_longlong(creg); |
411 | 5201 #if ENDIAN_L==0 |
5202 code_const(code_l1(lcadr(e1)),regv_h(creg)); | |
5203 code_const(code_l2(lcadr(e1)),regv_l(creg)); | |
5204 #else | |
211 | 5205 code_const(code_l1(lcadr(e1)),regv_l(creg)); |
5206 code_const(code_l2(lcadr(e1)),regv_h(creg)); | |
411 | 5207 #endif |
211 | 5208 } |
5209 | |
5210 void | |
5211 code_lneg(int creg) | |
195 | 5212 { |
221 | 5213 use_longlong(creg); |
211 | 5214 printf("\tsubfic %s,%s,0\n", |
5215 lregister_name_low(creg),lregister_name_low(creg)); | |
221 | 5216 printf("\tsubfze %s,%s\n", |
211 | 5217 lregister_name_high(creg),lregister_name_high(creg)); |
195 | 5218 } |
5219 | |
211 | 5220 void |
221 | 5221 code_lrgvar(int e1,int creg) |
211 | 5222 { |
5223 int r; | |
221 | 5224 char *crn_h; |
5225 char *crn_l; | |
5226 use_longlong(creg); | |
5227 crn_h = lregister_name_high(creg); | |
5228 crn_l = lregister_name_low(creg); | |
711 | 5229 r = get_ptr_cache(ncaddr(e1)); |
411 | 5230 #if ENDIAN_L==0 |
5231 code_ldf(cload(0),crn_l,cadr(e1),r); | |
5232 code_ldf(cload(0),crn_h,cadr(e1)+SIZE_OF_INT,r); | |
5233 #else | |
367 | 5234 code_ldf(cload(0),crn_h,cadr(e1),r); |
5235 code_ldf(cload(0),crn_l,cadr(e1)+SIZE_OF_INT,r); | |
411 | 5236 #endif |
211 | 5237 } |
5238 | |
5239 void | |
5240 code_lrlvar(int e1,int creg) | |
195 | 5241 { |
221 | 5242 char *crn_h; |
5243 char *crn_l; | |
5244 use_longlong(creg); | |
5245 crn_h = lregister_name_high(creg); | |
5246 crn_l = lregister_name_low(creg); | |
211 | 5247 lvar_intro(e1); |
411 | 5248 #if ENDIAN_L==0 |
5249 printf("\tlwz %s,",crn_l); lvar(e1); | |
5250 printf("\tlwz %s,",crn_h); lvar(e1+SIZE_OF_INT); | |
5251 #else | |
211 | 5252 printf("\tlwz %s,",crn_h); lvar(e1); |
245 | 5253 printf("\tlwz %s,",crn_l); lvar(e1+SIZE_OF_INT); |
411 | 5254 #endif |
195 | 5255 } |
5256 | |
221 | 5257 #if 0 |
216 | 5258 static int lumod_lib_used=0; |
217 | 5259 static char *lumod_lib[] = { |
216 | 5260 }; |
5261 | |
5262 static int lmod_lib_used=0; | |
217 | 5263 static char *lmod_lib[] = { |
216 | 5264 }; |
5265 | |
5266 static int ludiv_lib_used=0; | |
217 | 5267 static char *ludiv_lib[] = { |
216 | 5268 }; |
5269 | |
5270 static int ldiv_lib_used=0; | |
217 | 5271 static char *ldiv_lib[] = { |
216 | 5272 }; |
221 | 5273 #endif |
216 | 5274 |
5275 static int lsrd_lib_used=0; | |
217 | 5276 static char *lsrd_lib[] = { |
662 | 5277 #ifdef __APPLE__ |
5278 ".text", | |
5279 " .align 2", | |
672 | 5280 ".lsrd__:", |
662 | 5281 " mr. r5,r5", |
5282 " beqlr", | |
5283 " subfic r2,r5,32", | |
5284 " stw r3,-32(r1)", | |
5285 " stw r4,-28(r1)", | |
5286 " cmpwi cr7,r2,0", | |
5287 " bgt+ cr7,L__lsrd1", | |
5288 " neg r0,r2", | |
5289 " lwz r2,-32(r1)", | |
5290 " li r9,0", | |
5291 " srw r2,r2,r0", | |
5292 " stw r9,-48(r1)", | |
5293 " b L__lsrd2", | |
5294 "L__lsrd1: lwz r0,-32(r1)", | |
5295 " slw r9,r0,r2", | |
5296 " lwz r2,-28(r1)", | |
5297 " srw r0,r0,r5", | |
5298 " srw r2,r2,r5", | |
5299 " stw r0,-48(r1)", | |
5300 " or r2,r2,r9", | |
5301 "L__lsrd2: stw r2,-44(r1)", | |
5302 " lwz r3,-48(r1)", | |
5303 " lwz r4,-44(r1)", | |
5304 " blr", | |
5305 #else | |
217 | 5306 ".text", |
5307 " .align 2", | |
672 | 5308 ".lsrd__:", |
5309 " mr. 5,5", | |
5310 " beqlr", | |
673 | 5311 " subfic 8,5,32", |
672 | 5312 " stw 3,-32(1)", |
5313 " stw 4,-28(1)", | |
673 | 5314 " cmpwi 7,8,0", |
672 | 5315 " bgt+ 7,.L__lsrd1", |
5316 " neg 0,2", | |
673 | 5317 " lwz 8,-32(1)", |
672 | 5318 " li 9,0", |
673 | 5319 " srw 8,8,0", |
672 | 5320 " stw 9,-48(1)", |
5321 " b .L__lsrd2", | |
5322 ".L__lsrd1: lwz 0,-32(1)", | |
673 | 5323 " slw 9,0,8", |
5324 " lwz 8,-28(1)", | |
672 | 5325 " srw 0,0,5", |
673 | 5326 " srw 8,8,5", |
672 | 5327 " stw 0,-48(1)", |
673 | 5328 " or 8,8,9", |
5329 ".L__lsrd2: stw 8,-44(1)", | |
672 | 5330 " lwz 3,-48(1)", |
5331 " lwz 4,-44(1)", | |
217 | 5332 " blr", |
662 | 5333 #endif |
219 | 5334 0 |
217 | 5335 }; |
5336 | |
5337 static int asld_lib_used=0; | |
5338 static char *asld_lib[] = { | |
662 | 5339 #ifdef __APPLE__ |
5340 ".text", | |
5341 " .align 2", | |
672 | 5342 ".asld__:", |
662 | 5343 " mr. r5,r5", |
5344 " beqlr", | |
5345 " subfic r2,r5,32", | |
5346 " stw r3,-32(r1)", | |
5347 " stw r4,-28(r1)", | |
5348 " cmpwi cr7,r2,0", | |
5349 " bgt+ cr7,L__asld1", | |
5350 " neg r0,r2", | |
5351 " lwz r2,-28(r1)", | |
5352 " li r9,0", | |
5353 " slw r2,r2,r0", | |
5354 " stw r9,-44(r1)", | |
5355 " b L__asld2", | |
5356 "L__asld1: lwz r0,-28(r1)", | |
5357 " srw r9,r0,r2", | |
5358 " lwz r2,-32(r1)", | |
5359 " slw r0,r0,r5", | |
5360 " slw r2,r2,r5", | |
5361 " stw r0,-44(r1)", | |
5362 " or r2,r2,r9", | |
5363 "L__asld2: stw r2,-48(r1)", | |
5364 " lwz r3,-48(r1)", | |
5365 " lwz r4,-44(r1)", | |
5366 " blr", | |
5367 #else | |
217 | 5368 ".text", |
5369 " .align 2", | |
672 | 5370 ".asld__:", |
5371 " mr. 5,5", | |
5372 " beqlr", | |
673 | 5373 " subfic 8,5,32", |
672 | 5374 " stw 3,-32(1)", |
5375 " stw 4,-28(1)", | |
673 | 5376 " cmpwi 7,8,0", |
672 | 5377 " bgt+ 7,.L__asld1", |
673 | 5378 " neg 0,8", |
5379 " lwz 8,-28(1)", | |
672 | 5380 " li 9,0", |
673 | 5381 " slw 8,8,0", |
672 | 5382 " stw 9,-44(1)", |
5383 " b .L__asld2", | |
5384 ".L__asld1: lwz 0,-28(1)", | |
673 | 5385 " srw 9,0,8", |
5386 " lwz 8,-32(1)", | |
672 | 5387 " slw 0,0,5", |
673 | 5388 " slw 8,8,5", |
672 | 5389 " stw 0,-44(1)", |
673 | 5390 " or 8,8,9", |
5391 ".L__asld2: stw 8,-48(1)", | |
672 | 5392 " lwz 3,-48(1)", |
5393 " lwz 4,-44(1)", | |
217 | 5394 " blr", |
662 | 5395 #endif |
219 | 5396 0 |
216 | 5397 }; |
5398 | |
5399 static int asrd_lib_used=0; | |
217 | 5400 static char *asrd_lib[] = { |
662 | 5401 #ifdef __APPLE__ |
217 | 5402 ".text", |
5403 " .align 2", | |
672 | 5404 ".asrd__:", |
217 | 5405 " mr. r5,r5", |
5406 " beqlr", | |
5407 " subfic r2,r5,32", | |
5408 " stw r3,-32(r1)", | |
5409 " stw r4,-28(r1)", | |
5410 " cmpwi cr7,r2,0", | |
5411 " bgt+ cr7,L__asrd1", | |
5412 " lwz r0,-32(r1)", | |
5413 " neg r2,r2", | |
5414 " sraw r2,r0,r2", | |
5415 " srawi r0,r0,31", | |
5416 " b L__asrd2", | |
5417 "L__asrd1: lwz r0,-32(r1)", | |
5418 " slw r9,r0,r2", | |
5419 " lwz r2,-28(r1)", | |
5420 " sraw r0,r0,r5", | |
5421 " srw r2,r2,r5", | |
5422 " or r2,r2,r9", | |
5423 "L__asrd2: stw r0,-48(r1)", | |
5424 " stw r2,-44(r1)", | |
5425 " lwz r3,-48(r1)", | |
5426 " lwz r4,-44(r1)", | |
5427 " blr", | |
662 | 5428 #else |
5429 ".text", | |
5430 " .align 2", | |
672 | 5431 ".asrd__:", |
5432 " mr. 5,5", | |
5433 " beqlr", | |
673 | 5434 " subfic 8,5,32", |
672 | 5435 " stw 3,-32(1)", |
5436 " stw 4,-28(1)", | |
673 | 5437 " cmpwi 7,8,0", |
672 | 5438 " bgt+ 7,.L__asrd1", |
5439 " lwz 0,-32(1)", | |
673 | 5440 " neg 8,8", |
5441 " sraw 8,0,8", | |
672 | 5442 " srawi 0,0,31", |
5443 " b .L__asrd2", | |
5444 ".L__asrd1: lwz 0,-32(1)", | |
673 | 5445 " slw 9,0,8", |
5446 " lwz 8,-28(1)", | |
672 | 5447 " sraw 0,0,5", |
673 | 5448 " srw 8,8,5", |
5449 " or 8,8,9", | |
672 | 5450 ".L__asrd2: stw 0,-48(1)", |
673 | 5451 " stw 8,-44(1)", |
672 | 5452 " lwz 3,-48(1)", |
5453 " lwz 4,-44(1)", | |
5454 " blr", | |
662 | 5455 #endif |
219 | 5456 0 |
216 | 5457 }; |
5458 | |
662 | 5459 #endif |
5460 | |
217 | 5461 static void |
5462 extern_conv(char *conv) | |
5463 { | |
5464 code_save_stacks(); | |
5465 clear_ptr_cache(); | |
5466 extern_define(conv,0,FUNCTION,1); | |
662 | 5467 #ifdef __APPLE__ |
217 | 5468 printf("\tbl L_%s$stub\n",conv); |
662 | 5469 #else |
5470 printf("\tbl %s\n",conv); | |
5471 #endif | |
217 | 5472 } |
5473 | |
216 | 5474 #if FLOAT_CODE |
218 | 5475 #if 0 |
217 | 5476 static int d2ll_lib_used=0; |
5477 static char *d2ll_lib[] = { | |
216 | 5478 }; |
5479 | |
5480 static int d2ull_lib_used=0; | |
217 | 5481 static char *d2ull_lib[] = { |
216 | 5482 }; |
5483 | |
5484 static int f2ll_lib_used=0; | |
217 | 5485 static char *f2ll_lib[] = { |
216 | 5486 }; |
5487 | |
5488 static int f2ull_lib_used=0; | |
217 | 5489 static char *f2ull_lib[] = { |
216 | 5490 }; |
5491 | |
5492 static int ll2d_lib_used=0; | |
217 | 5493 static char *ll2d_lib[] = { |
216 | 5494 }; |
5495 | |
5496 static int ll2f_lib_used=0; | |
217 | 5497 static char *ll2f_lib[] = { |
216 | 5498 }; |
218 | 5499 #endif |
216 | 5500 |
5501 #endif | |
5502 | |
5503 static void | |
255 | 5504 code_asld_lib(int reg,int oreg) |
211 | 5505 { |
5506 code_save_stacks(); | |
5507 clear_ptr_cache(); | |
5508 asld_lib_used = 1; | |
255 | 5509 set_lreg_operand(reg,1); |
5510 set_lreg(RET_LREGISTER,0); | |
228 | 5511 if (regv_l(oreg)!=5) { |
662 | 5512 printf("\tmr %s,%s\n", |
5513 register_name(5), | |
5514 lregister_name_low(oreg)); | |
228 | 5515 } |
672 | 5516 printf("\tbl .asld__\n"); |
195 | 5517 } |
5518 | |
216 | 5519 static void |
255 | 5520 code_asrd_lib(int reg,int oreg) // ___ashrdi3$stub |
216 | 5521 { |
5522 code_save_stacks(); | |
5523 clear_ptr_cache(); | |
5524 asrd_lib_used = 1; | |
255 | 5525 set_lreg_operand(reg,1); |
5526 set_lreg(RET_LREGISTER,0); | |
228 | 5527 if (regv_l(oreg)!=5) { |
662 | 5528 printf("\tmr %s,%s\n", |
5529 register_name(5), | |
5530 lregister_name_low(oreg)); | |
228 | 5531 } |
672 | 5532 printf("\tbl .asrd__\n"); |
216 | 5533 } |
5534 | |
5535 static void | |
255 | 5536 code_lsrd_lib(int reg,int oreg) // ___lshrdi3$stub |
216 | 5537 { |
5538 code_save_stacks(); | |
5539 clear_ptr_cache(); | |
5540 lsrd_lib_used = 1; | |
255 | 5541 set_lreg_operand(reg,1); |
5542 set_lreg(RET_LREGISTER,0); | |
231 | 5543 if (regv_l(oreg)!=5) { |
662 | 5544 printf("\tmr %s,%s\n", |
5545 register_name(5), | |
5546 lregister_name_low(oreg)); | |
231 | 5547 } |
672 | 5548 printf("\tbl .lsrd__\n"); |
216 | 5549 } |
5550 | |
5551 static void | |
255 | 5552 code_ldiv_lib(int reg,int oreg) // ___divdi3$stub |
216 | 5553 { |
223 | 5554 code_save_stacks(); |
5555 clear_ptr_cache(); | |
255 | 5556 set_lreg_operand(reg,1); |
5557 set_lreg(RET_LREGISTER,0); | |
5558 set_lreg_operand1(oreg,1); | |
217 | 5559 extern_conv("__divdi3"); |
216 | 5560 } |
5561 | |
5562 static void | |
255 | 5563 code_ludiv_lib(int reg,int oreg) // ___udivdi3$stub |
216 | 5564 { |
223 | 5565 code_save_stacks(); |
5566 clear_ptr_cache(); | |
255 | 5567 set_lreg_operand(reg,1); |
5568 set_lreg(RET_LREGISTER,0); | |
5569 set_lreg_operand1(oreg,1); | |
217 | 5570 extern_conv("__udivdi3"); |
216 | 5571 } |
5572 | |
5573 static void | |
255 | 5574 code_lmod_lib(int reg,int oreg) // ___moddi3$stub |
216 | 5575 { |
223 | 5576 code_save_stacks(); |
5577 clear_ptr_cache(); | |
255 | 5578 set_lreg_operand(reg,1); |
5579 set_lreg(RET_LREGISTER,0); | |
5580 set_lreg_operand1(oreg,1); | |
217 | 5581 extern_conv("__moddi3"); |
216 | 5582 } |
5583 | |
5584 static void | |
255 | 5585 code_lumod_lib(int reg,int oreg) // ___umoddi3$stub |
216 | 5586 { |
223 | 5587 code_save_stacks(); |
5588 clear_ptr_cache(); | |
255 | 5589 set_lreg(RET_LREGISTER,0); |
5590 set_lreg_operand(reg,1); | |
5591 set_lreg_operand1(oreg,1); | |
217 | 5592 extern_conv("__umoddi3"); |
216 | 5593 } |
5594 | |
530 | 5595 #define check_lreg(reg) if (reg!=lreg) { lmove(reg,lreg); /* reg<=lreg */ } |
5596 | |
5597 // reg = reg op oreg | |
221 | 5598 |
211 | 5599 void |
221 | 5600 ltosop(int op,int reg,int oreg) |
195 | 5601 { |
221 | 5602 int dx = -1; |
252 | 5603 int ox = -1; |
531 | 5604 int creg_mode = (reg==USE_CREG); |
211 | 5605 char *orn_h,*crn_h,*drn_h; |
5606 char *orn_l,*crn_l,*drn_l; | |
221 | 5607 // creg = creg op oreg |
5608 | |
5609 use_longlong(reg); | |
211 | 5610 if(oreg==-1) { |
5611 error(-1); | |
5612 } else if (oreg<= -REG_LVAR_OFFSET) { | |
252 | 5613 ox = get_lregister(); if (ox<0) error(-1); |
5614 use_reg(ox); | |
273 | 5615 code_lrlvar(oreg+REG_LVAR_OFFSET,ox); |
252 | 5616 oreg = ox; |
211 | 5617 } |
5618 | |
5619 switch(op) { | |
5620 case LLSHIFT: | |
5621 case LULSHIFT: | |
255 | 5622 code_asld_lib(reg,oreg); // ___ashldi3$stub |
221 | 5623 check_lreg(reg); |
252 | 5624 if(ox!=-1) free_register(ox); |
211 | 5625 return; |
5626 case LRSHIFT: | |
255 | 5627 code_asrd_lib(reg,oreg); // ___ashrdi3$stub |
221 | 5628 check_lreg(reg); |
252 | 5629 if(ox!=-1) free_register(ox); |
211 | 5630 return; |
5631 case LURSHIFT: | |
255 | 5632 code_lsrd_lib(reg,oreg); // ___lshrdi3$stub |
221 | 5633 check_lreg(reg); |
252 | 5634 if(ox!=-1) free_register(ox); |
211 | 5635 return; |
5636 } | |
5637 orn_h = lregister_name_high(oreg); | |
5638 orn_l = lregister_name_low(oreg); | |
221 | 5639 crn_h = lregister_name_high(reg); |
5640 crn_l = lregister_name_low(reg); | |
211 | 5641 switch(op) { |
219 | 5642 case LADD: |
211 | 5643 printf("\taddc %s,%s,%s\n",crn_l,crn_l,orn_l); |
5644 printf("\tadde %s,%s,%s\n",crn_h,crn_h,orn_h); | |
5645 break; | |
219 | 5646 case LSUB: |
228 | 5647 printf("\tsubfc %s,%s,%s\n",crn_l,orn_l,crn_l); |
5648 printf("\tsubfe %s,%s,%s\n",crn_h,orn_h,crn_h); | |
211 | 5649 break; |
5650 case LCMP: | |
5651 error(-1); | |
5652 break; | |
219 | 5653 case LBAND: |
211 | 5654 printf("\tand %s,%s,%s\n",crn_l,crn_l,orn_l); |
5655 printf("\tand %s,%s,%s\n",crn_h,crn_h,orn_h); | |
5656 break; | |
219 | 5657 case LEOR: |
211 | 5658 printf("\txor %s,%s,%s\n",crn_l,crn_l,orn_l); |
5659 printf("\txor %s,%s,%s\n",crn_h,crn_h,orn_h); | |
5660 break; | |
219 | 5661 case LBOR: |
211 | 5662 printf("\tor %s,%s,%s\n",crn_l,crn_l,orn_l); |
5663 printf("\tor %s,%s,%s\n",crn_h,crn_h,orn_h); | |
5664 break; | |
219 | 5665 case LMUL: |
5666 case LUMUL: | |
273 | 5667 // code_save_stacks(); |
5668 // clear_ptr_cache(); | |
530 | 5669 dx=get_lregister(); if (dx<0) error(-1); |
223 | 5670 use_reg(dx); |
211 | 5671 drn_l = lregister_name_low(dx); |
5672 drn_h = lregister_name_high(dx); | |
5673 /* | |
5674 drn_l = l32( crn_l * orn_l); | |
5675 drn_h = h32( crn_l * orn_l); | |
593 | 5676 crn_h = l32( crn_h * orn_l); |
5677 drn_h = drn_h + crn_h; | |
211 | 5678 crn_l = l32( crn_l * orn_h); |
5679 crn_h = drn_h + crn_l; | |
5680 crn_l = drn_l; | |
5681 */ | |
5682 printf("\tmulhwu %s,%s,%s\n",drn_h,crn_l,orn_l); | |
228 | 5683 printf("\tmullw %s,%s,%s\n", drn_l,crn_l,orn_l); |
593 | 5684 printf("\tmullw %s,%s,%s\n", crn_h,crn_h,orn_l); |
5685 printf("\tadd %s,%s,%s\n", drn_h,drn_h,crn_h); | |
228 | 5686 printf("\tmullw %s,%s,%s\n", crn_l,orn_h,crn_l); |
5687 printf("\tadd %s,%s,%s\n", crn_h,drn_h,crn_l); | |
5688 printf("\tmr %s,%s\n", crn_l,drn_l); | |
211 | 5689 break; |
219 | 5690 case LDIV: |
255 | 5691 code_ldiv_lib(reg,oreg); // ___divdi3$stub |
531 | 5692 if (!creg_mode) check_lreg(reg); |
211 | 5693 break; |
219 | 5694 case LUDIV: |
255 | 5695 code_ludiv_lib(reg,oreg); // ___udivdi3$stub |
531 | 5696 if (!creg_mode) check_lreg(reg); |
211 | 5697 break; |
219 | 5698 case LMOD: |
255 | 5699 code_lmod_lib(reg,oreg); // ___moddi3$stub |
531 | 5700 if (!creg_mode) check_lreg(reg); |
211 | 5701 break; |
219 | 5702 case LUMOD: |
255 | 5703 code_lumod_lib(reg,oreg); // ___umoddi3$stub |
531 | 5704 if (!creg_mode) check_lreg(reg); |
211 | 5705 break; |
5706 default: | |
5707 error(-1); | |
5708 } | |
530 | 5709 if(ox!=-1) free_register(ox); |
221 | 5710 if(dx!=-1) free_register(dx); |
195 | 5711 } |
5712 | |
216 | 5713 int |
5714 code_lconst_op_p(int op,int e) | |
214 | 5715 { |
215 | 5716 int v; |
5717 if (car(e)==LCONST) { | |
222 | 5718 if (!(-32766<lcadr(e)&&lcadr(e)<32767)) return 0; |
287 | 5719 v = lcadr(e); |
215 | 5720 } else if (car(e)==CONST) { |
222 | 5721 if (!(-32766<cadr(e)&&cadr(e)<32767)) return 0; |
287 | 5722 v = cadr(e); |
222 | 5723 } else return 0; |
215 | 5724 |
214 | 5725 switch(op) { |
436 | 5726 case LMUL: case LUMUL: case LUDIV: |
5727 // case LDIV: | |
5728 return ilog(v); | |
231 | 5729 case LLSHIFT: |
5730 case LULSHIFT: | |
5731 case LRSHIFT: | |
5732 case LURSHIFT: | |
435 | 5733 return (0<=v&&v<=64); |
219 | 5734 case LADD: |
5735 case LSUB: | |
215 | 5736 return 1; |
219 | 5737 case LBOR: |
215 | 5738 return (v>0); |
214 | 5739 default: |
5740 return 0; | |
5741 } | |
5742 } | |
5743 | |
216 | 5744 void |
221 | 5745 loprtc(int op,int creg,int e) |
213 | 5746 { |
221 | 5747 char *crn_h; |
5748 char *crn_l; | |
215 | 5749 char *grn; |
569 | 5750 int v=0; |
215 | 5751 int greg; |
5752 | |
221 | 5753 use_longlong(creg); |
5754 crn_h = lregister_name_high(creg); | |
5755 crn_l = lregister_name_low(creg); | |
5756 | |
222 | 5757 if (car(e)==LCONST) v = lcadr(e); |
5758 else if (car(e)==CONST) v = cadr(e); | |
213 | 5759 |
5760 switch(op) { | |
436 | 5761 case LMUL: case LUMUL: |
5762 v=ilog(v); | |
219 | 5763 case LLSHIFT: |
5764 case LULSHIFT: | |
435 | 5765 if (v==0) return; |
5766 if (v==32) { | |
5767 code_register(regv_l(creg),regv_h(creg)); | |
5768 code_const(0,regv_l(creg)); | |
5769 return; | |
5770 } else if (v>31) { | |
5771 printf("\tslwi %s,%s,%d\n",crn_h,crn_l,v-32); | |
5772 code_const(0,regv_l(creg)); | |
5773 return; | |
5774 } | |
215 | 5775 greg = get_register(); |
435 | 5776 grn = register_name(greg); |
223 | 5777 use_reg(greg); |
231 | 5778 printf("\tsrwi %s,%s,%d\n",grn,crn_l,32-v); |
5779 printf("\tslwi %s,%s,%d\n",crn_h,crn_h,v); | |
5780 printf("\tor %s,%s,%s\n",crn_h,grn,crn_h); | |
215 | 5781 printf("\tslwi %s,%s,%d\n",crn_l,crn_l,v); |
5782 free_register(greg); | |
213 | 5783 return; |
436 | 5784 case LDIV: |
5785 v=ilog(v); | |
219 | 5786 case LRSHIFT: |
435 | 5787 if (v==0) return; |
5788 if (v==32) { | |
5789 code_register(regv_h(creg),regv_l(creg)); | |
5790 printf("\tsrawi %s,%s,31\n",crn_h,crn_l); | |
5791 return; | |
5792 } else if (v>31) { | |
5793 printf("\tsrawi %s,%s,%d\n",crn_l,crn_h,v-32); | |
5794 printf("\tsrawi %s,%s,31\n",crn_h,crn_l); | |
5795 return; | |
5796 } | |
215 | 5797 greg = get_register(); |
223 | 5798 use_reg(greg); |
215 | 5799 grn = register_name(greg); |
5800 printf("\tsrwi %s,%s,%d\n",grn,crn_l,v); | |
231 | 5801 printf("\tinsrwi %s,%s,%d,0\n",grn,crn_h,v); |
215 | 5802 printf("\tsrawi %s,%s,%d\n",crn_h,crn_h,v); |
5803 printf("\tmr %s,%s\n",crn_l,grn); | |
5804 free_register(greg); | |
213 | 5805 return; |
436 | 5806 case LUDIV: |
5807 v=ilog(v); | |
219 | 5808 case LURSHIFT: |
435 | 5809 if (v==0) return; |
5810 if (v==32) { | |
5811 code_register(regv_h(creg),regv_l(creg)); | |
5812 code_const(0,regv_h(creg)); | |
5813 return; | |
5814 } else if (v>31) { | |
5815 printf("\tsrwi %s,%s,%d\n",crn_l,crn_h,v-32); | |
5816 code_const(0,regv_h(creg)); | |
5817 return; | |
5818 } | |
215 | 5819 greg = get_register(); |
223 | 5820 use_reg(greg); |
215 | 5821 grn = register_name(greg); |
231 | 5822 printf("\tslwi %s,%s,%d\n",grn,crn_h,32-v); |
215 | 5823 printf("\tsrwi %s,%s,%d\n",crn_l,crn_l,v); |
231 | 5824 printf("\tor %s,%s,%s\n",crn_l,grn,crn_l); |
5825 printf("\tsrwi %s,%s,%d\n",crn_h,crn_h,v); | |
215 | 5826 free_register(greg); |
5827 return; | |
231 | 5828 case LSUB: |
5829 v = -v; | |
219 | 5830 case LADD: |
231 | 5831 printf("\taddic %s,%s,%d\n",crn_l,crn_l,v); |
5832 if (v<0) | |
5833 printf("\taddme %s,%s\n",crn_h,crn_h); | |
5834 else | |
5835 printf("\taddze %s,%s\n",crn_h,crn_h); | |
213 | 5836 break; |
219 | 5837 case LBOR: |
662 | 5838 #ifdef __APPLE__ |
215 | 5839 printf("\tori %s,%s,lo16(%d)\n",crn_l,crn_l,v); |
662 | 5840 #else |
5841 printf("\tori %s,%s,%d@l\n",crn_l,crn_l,v); | |
5842 #endif | |
213 | 5843 break; |
5844 default: | |
5845 error(-1); | |
5846 } | |
5847 } | |
5848 | |
5849 | |
211 | 5850 void |
5851 emit_lpop_free(int xreg) | |
195 | 5852 { |
590 | 5853 if (xreg>=0 && xreg!=creg && regs[xreg]!=REG_VAR) |
211 | 5854 free_register(xreg); |
195 | 5855 } |
5856 | |
211 | 5857 void |
5858 emit_lpush() | |
5859 { | |
5860 int new_reg; | |
212 | 5861 if (!is_longlong_reg(creg)) error(-1); |
211 | 5862 if (lreg_sp>MAX_MAX) error(-1); |
724 | 5863 new_reg = get_lregister(); /* 絶対に取れる(?) */ |
5864 lreg_stack[lreg_sp++] = creg; /* push するかわりにレジスタを使う */ | |
211 | 5865 lreg = creg = new_reg; |
5866 } | |
5867 | |
5868 void | |
239 | 5869 code_i2ll(int reg) |
195 | 5870 { |
215 | 5871 char *crn,*crn_h,*crn_l; |
239 | 5872 int reg0; |
5873 crn = register_name(reg0 = ireg); | |
5874 use_longlong(reg); | |
221 | 5875 crn_h = lregister_name_high(lreg); |
5876 crn_l = lregister_name_low(lreg); | |
239 | 5877 if (reg0!=regv_l(lreg)) |
215 | 5878 printf("\tmr %s,%s\n",crn_l,crn); |
5879 printf("\tsrawi %s,%s,31\n",crn_h,crn_l); | |
195 | 5880 } |
5881 | |
211 | 5882 void |
239 | 5883 code_i2ull(int reg) |
195 | 5884 { |
239 | 5885 code_i2ll(reg); |
195 | 5886 } |
5887 | |
211 | 5888 void |
239 | 5889 code_u2ll(int reg) |
195 | 5890 { |
215 | 5891 char *crn,*crn_h,*crn_l; |
239 | 5892 int reg0; |
5893 crn = register_name(reg0 = ireg); | |
5894 use_longlong(reg); | |
221 | 5895 crn_h = lregister_name_high(lreg); |
5896 crn_l = lregister_name_low(lreg); | |
239 | 5897 if (reg0!=regv_l(lreg)) |
215 | 5898 printf("\tmr %s,%s\n",crn_l,crn); |
5899 printf("\tli %s,0\n",crn_h); | |
195 | 5900 } |
5901 | |
211 | 5902 void |
5903 code_u2ull(int creg) | |
195 | 5904 { |
215 | 5905 code_u2ll(creg); |
195 | 5906 } |
5907 | |
211 | 5908 void |
239 | 5909 code_ll2i(int reg) |
195 | 5910 { |
219 | 5911 char *crn_l; |
239 | 5912 int reg0; |
5913 crn_l = lregister_name_low(reg0=lreg); | |
5914 use_int(reg); | |
5915 if (ireg!=regv_l(reg0)) | |
221 | 5916 printf("\tmr %s,%s\n",register_name(ireg),crn_l); |
195 | 5917 } |
5918 | |
211 | 5919 void |
5920 code_ll2u(int creg) | |
195 | 5921 { |
215 | 5922 code_ll2i(creg); |
195 | 5923 } |
5924 | |
211 | 5925 void |
5926 code_ull2i(int creg) | |
195 | 5927 { |
215 | 5928 code_ll2i(creg); |
195 | 5929 } |
5930 | |
211 | 5931 void |
5932 code_ull2u(int creg) | |
195 | 5933 { |
215 | 5934 code_ll2i(creg); |
195 | 5935 } |
5936 | |
5937 #if FLOAT_CODE | |
216 | 5938 |
211 | 5939 void |
239 | 5940 code_d2ll(int reg) |
195 | 5941 { |
215 | 5942 // fixdfdi$stub |
218 | 5943 set_freg(RET_FREGISTER,1); |
221 | 5944 extern_conv("__fixdfdi"); |
216 | 5945 set_lreg(RET_LREGISTER,0); |
239 | 5946 if (reg!=USE_CREG&®!=RET_LREGISTER) |
5947 use_longlong(reg); | |
195 | 5948 } |
5949 | |
211 | 5950 void |
239 | 5951 code_d2ull(int reg) |
195 | 5952 { |
218 | 5953 set_freg(RET_FREGISTER,1); |
221 | 5954 extern_conv("__fixunsdfdi"); |
216 | 5955 set_lreg(RET_LREGISTER,0); |
239 | 5956 if (reg!=USE_CREG&®!=RET_LREGISTER) |
5957 use_longlong(reg); | |
195 | 5958 } |
5959 | |
211 | 5960 void |
239 | 5961 code_f2ll(int reg) |
195 | 5962 { |
218 | 5963 set_freg(RET_FREGISTER,1); |
221 | 5964 extern_conv("__fixdfdi"); |
216 | 5965 set_lreg(RET_LREGISTER,0); |
239 | 5966 if (reg!=USE_CREG&®!=RET_LREGISTER) |
5967 use_longlong(reg); | |
195 | 5968 } |
5969 | |
211 | 5970 void |
239 | 5971 code_f2ull(int reg) |
195 | 5972 { |
218 | 5973 set_freg(RET_FREGISTER,1); |
221 | 5974 extern_conv("__fixsfdi"); |
216 | 5975 set_lreg(RET_LREGISTER,0); |
239 | 5976 if (reg!=USE_CREG&®!=RET_LREGISTER) |
5977 use_longlong(reg); | |
195 | 5978 } |
5979 | |
211 | 5980 void |
239 | 5981 code_ll2d(int reg) |
195 | 5982 { |
216 | 5983 set_lreg(RET_LREGISTER,1); |
221 | 5984 extern_conv("__floatdidf"); |
218 | 5985 set_freg(RET_FREGISTER,0); |
239 | 5986 if (reg!=USE_CREG&®!=RET_FREGISTER) |
5987 use_float(1,reg); | |
195 | 5988 } |
5989 | |
217 | 5990 |
211 | 5991 void |
239 | 5992 code_ll2f(int reg) |
195 | 5993 { |
216 | 5994 set_lreg(RET_LREGISTER,1); |
221 | 5995 extern_conv("__floatdisf"); |
218 | 5996 set_freg(RET_FREGISTER,0); |
239 | 5997 if (reg!=USE_CREG&®!=RET_FREGISTER) |
5998 use_float(0,reg); | |
195 | 5999 } |
6000 | |
211 | 6001 void |
6002 code_ull2d(int creg) | |
195 | 6003 { |
215 | 6004 code_ll2d(creg); |
195 | 6005 } |
6006 | |
211 | 6007 void |
6008 code_ull2f(int creg) | |
195 | 6009 { |
215 | 6010 code_ll2f(creg); |
195 | 6011 } |
6012 | |
6013 | |
273 | 6014 static void |
6015 ladd(int creg,int reg,int dir) // creg=reg+dir | |
221 | 6016 { |
273 | 6017 printf("\taddic %s,%s,%d\n", |
6018 lregister_name_low(creg),lregister_name_low(reg), dir); | |
6019 printf("\tadd%s %s,%s\n", dir>0?"ze":"me", | |
6020 lregister_name_high(creg),lregister_name_high(reg)); | |
221 | 6021 } |
195 | 6022 |
211 | 6023 void |
6024 code_lpreinc(int e1,int e2,int reg) | |
195 | 6025 { |
222 | 6026 int dreg,xreg; |
211 | 6027 int dir=caddr(e1); |
6028 if (car(e2)==LREGISTER) { | |
221 | 6029 use_longlong(reg); |
273 | 6030 ladd(cadr(e2),cadr(e2),dir); |
6031 if (reg!=cadr(e2)) { | |
6032 lmove(reg,cadr(e2)); | |
211 | 6033 } |
6034 return; | |
6035 } | |
6036 g_expr(e2); | |
221 | 6037 if(!is_int_reg(creg)) error(-1); |
222 | 6038 emit_push(); |
221 | 6039 if (reg==USE_CREG) { |
6040 dreg=get_lregister(); if (!dreg) error(-1); | |
6041 set_lreg(dreg,0); // free old lreg==creg | |
6042 } else { | |
269 | 6043 dreg = reg; |
221 | 6044 } |
222 | 6045 xreg = emit_pop(0); |
269 | 6046 lload(xreg,dreg,0); |
273 | 6047 ladd(dreg,dreg,dir); |
269 | 6048 code_lassign(xreg,dreg); |
222 | 6049 emit_pop_free(xreg); |
195 | 6050 } |
6051 | |
211 | 6052 void |
6053 code_lpostinc(int e1,int e2,int reg) | |
195 | 6054 { |
222 | 6055 int dreg,nreg,xreg; |
211 | 6056 int dir=caddr(e1); |
6057 if (car(e2)==LREGISTER) { | |
221 | 6058 use_longlong(reg); |
587 | 6059 if (use && reg!=cadr(e2)) |
273 | 6060 lmove(reg,cadr(e2)); |
6061 ladd(cadr(e2),cadr(e2),dir); | |
211 | 6062 return; |
6063 } | |
6064 g_expr(e2); | |
221 | 6065 if(!is_int_reg(creg)) error(-1); |
222 | 6066 emit_push(); |
221 | 6067 nreg=get_lregister(); if (!nreg) error(-1); |
6068 if (reg==USE_CREG) { | |
6069 dreg=get_lregister(); if (!dreg) error(-1); | |
6070 set_lreg(dreg,0); // free old lreg==creg | |
6071 } else { | |
269 | 6072 dreg = reg; |
221 | 6073 } |
222 | 6074 xreg = emit_pop(0); |
269 | 6075 lload(xreg,dreg,0); |
273 | 6076 ladd(nreg,dreg,dir); |
269 | 6077 code_lassign(xreg,nreg); |
222 | 6078 emit_pop_free(xreg); |
211 | 6079 free_register(nreg); |
195 | 6080 } |
6081 | |
211 | 6082 void |
221 | 6083 code_lassop(int op,int reg) |
195 | 6084 { |
211 | 6085 int xreg; |
6086 int edx,edx0=-1; | |
221 | 6087 |
6088 // (*creg) op = pop() | |
211 | 6089 xreg = emit_lpop(0); /* pop e3 value */ |
6090 if (!is_int_reg(creg)) error(-1); | |
221 | 6091 edx = ireg; |
223 | 6092 emit_push(); |
221 | 6093 use_longlong(reg); |
6094 if (regv_l(lreg)==edx || regv_h(lreg)==edx) { | |
285 | 6095 // this can't happen |
211 | 6096 edx0 = get_register(); if(!edx0) error(-1); |
468 | 6097 printf("## lassop\n\tmr %s,%s\n",register_name(edx0),register_name(edx)); |
211 | 6098 edx = edx0; |
6099 } | |
269 | 6100 lload(edx0=edx,reg,0); |
221 | 6101 ltosop(op,reg,xreg); |
269 | 6102 use_reg(reg); |
223 | 6103 edx = emit_pop(0); |
269 | 6104 code_lassign(edx,reg); |
6105 if (edx0!=-1) | |
6106 free_register(edx0); | |
6107 emit_pop_free(edx); | |
211 | 6108 emit_lpop_free(xreg); |
195 | 6109 } |
6110 | |
219 | 6111 void |
6112 code_register_lassop(int reg,int op) { | |
221 | 6113 // reg op = pop() |
219 | 6114 int xreg=emit_lpop(); |
221 | 6115 ltosop(op,reg,xreg); |
6116 emit_lpop_free(xreg); | |
219 | 6117 } |
6118 | |
195 | 6119 |
6120 #endif | |
6121 | |
95 | 6122 void |
6123 code_save_stacks() | |
6124 { | |
103 | 6125 int i,reg; |
101 | 6126 for(i=0;i<reg_sp;i++) { |
103 | 6127 if ((reg=reg_stack[i])>=0) { |
101 | 6128 code_assign_lvar( |
245 | 6129 (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0); |
101 | 6130 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; |
368 | 6131 free_register(reg); |
101 | 6132 } |
6133 } | |
195 | 6134 #if FLOAT_CODE |
101 | 6135 for(i=0;i<freg_sp;i++) { |
103 | 6136 if ((reg=freg_stack[i])>=0) { |
101 | 6137 code_dassign_lvar( |
245 | 6138 (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); |
101 | 6139 freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; |
368 | 6140 free_register(reg); |
101 | 6141 } |
6142 } | |
195 | 6143 #endif |
212 | 6144 #if LONGLONG_CODE |
6145 for(i=0;i<lreg_sp;i++) { | |
6146 if ((reg=lreg_stack[i])>=0) { | |
223 | 6147 code_lassign_lvar( |
245 | 6148 (lreg_stack[i]=new_lvar(SIZE_OF_LONGLONG)),reg); |
212 | 6149 lreg_stack[i]= lreg_stack[i]-REG_LVAR_OFFSET; |
368 | 6150 free_register(reg); |
212 | 6151 } |
6152 } | |
6153 #endif | |
96 | 6154 } |
6155 | |
739
0c7a6ae119ba
i64 continue... compiler compiled.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
726
diff
changeset
|
6156 static void |
96 | 6157 emit_lib(char *p[]) |
95 | 6158 { |
98 | 6159 while(*p) { |
6160 printf("%s\n",*p++); | |
96 | 6161 } |
6162 } | |
6163 | |
6164 void | |
6165 code_closing() | |
6166 { | |
195 | 6167 #if FLOAT_CODE |
96 | 6168 if (d2u_lib_used) emit_lib(d2u_lib); |
6169 if (u2d_lib_used) emit_lib(u2d_lib); | |
6170 if (float_one_lib_used) emit_lib(float_one_lib); | |
98 | 6171 if (float_zero_lib_used) emit_lib(float_zero_lib); |
96 | 6172 if (i2d_lib_used) emit_lib(i2d_lib); |
739
0c7a6ae119ba
i64 continue... compiler compiled.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
726
diff
changeset
|
6173 d2u_lib_used = u2d_lib_used= float_one_lib_used= float_zero_lib_used = i2d_lib_used = 0; |
195 | 6174 #endif |
213 | 6175 #if LONGLONG_CODE |
218 | 6176 if (asld_lib_used) emit_lib(asld_lib); |
221 | 6177 if (lsrd_lib_used) emit_lib(lsrd_lib); |
6178 if (asrd_lib_used) emit_lib(asrd_lib); | |
739
0c7a6ae119ba
i64 continue... compiler compiled.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
726
diff
changeset
|
6179 asld_lib_used = lsrd_lib_used = asrd_lib_used = 0; |
221 | 6180 #if 0 |
216 | 6181 if (lumod_lib_used) emit_lib(lumod_lib); |
6182 if (lmod_lib_used) emit_lib(lmod_lib); | |
6183 if (ludiv_lib_used) emit_lib(ludiv_lib); | |
6184 if (ldiv_lib_used) emit_lib(ldiv_lib); | |
221 | 6185 #endif |
213 | 6186 #if FLOAT_CODE |
218 | 6187 #if 0 |
216 | 6188 if (dl2ll_lib_used) emit_lib(dl2ll_lib); |
6189 if (d2ull_lib_used) emit_lib(d2ull_lib); | |
6190 if (f2ll_lib_used) emit_lib(f2ll_lib); | |
6191 if (f2ull_lib_used) emit_lib(f2ull_lib); | |
6192 if (ll2d_lib_used) emit_lib(ll2d_lib); | |
6193 if (ll2f_lib_used) emit_lib(ll2f_lib); | |
213 | 6194 #endif |
6195 #endif | |
218 | 6196 #endif |
662 | 6197 #ifndef __APPLE__ |
6198 if (saveFP_used) emit_lib(saveFP_lib); | |
6199 #endif | |
97 | 6200 global_table(); |
108 | 6201 /* printf("\t.ident \"Micro-C compiled\"\n"); */ |
95 | 6202 } |
6203 | |
300 | 6204 #if CASE_CODE |
6205 | |
6206 int | |
382 | 6207 code_table_jump_p(int delta) { return 1; } |
300 | 6208 |
6209 void | |
302 | 6210 code_table_jump(int l,int csvalue,int delta,int max,int min,int dlabel) |
300 | 6211 { |
302 | 6212 int t,s,u=-1; |
6213 char *crn = register_name(csvalue); // can be t,s,u | |
300 | 6214 char *trn = register_name(t=get_register()); |
6215 char *srn = register_name(s=get_register()); | |
302 | 6216 char *urn; |
300 | 6217 |
6218 inc_cmpflag(); | |
6219 if (min>32767||min<-32765) { | |
302 | 6220 if (t==csvalue) { |
6221 code_const(min,s); | |
6222 printf("\tsub\t%s,%s,%s\n",trn,crn,srn); | |
6223 } else { | |
6224 code_const(min,t); | |
6225 printf("\tsub\t%s,%s,%s\n",trn,crn,trn); | |
6226 } | |
300 | 6227 } else { |
667 | 6228 #ifdef __APPLE__ |
300 | 6229 printf("\taddi\t%s,%s,lo16(%d)\n",trn,crn,-min); |
667 | 6230 #else |
6231 printf("\taddi\t%s,%s,%d@l\n",trn,crn,-min); | |
6232 #endif | |
300 | 6233 } |
662 | 6234 printf("\tcmplwi %s,%s,%d\n",crname(cmpflag),trn,max-min); |
6235 printf("\tbgt-\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel); | |
300 | 6236 inc_cmpflag(); |
6237 switch(delta) { | |
6238 case 1: printf("\tslwi %s,%s,2\n",trn,trn); break; | |
302 | 6239 case 2: |
6240 printf("\tli %s,1\n",srn); | |
6241 printf("\tand %s,%s,%s\n",srn,srn,trn); | |
662 | 6242 printf("\tcmplwi %s,%s,0\n",crname(cmpflag),srn); |
667 | 6243 printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel); |
302 | 6244 printf("\tslwi %s,%s,1\n",trn,trn); |
6245 break; | |
6246 case 4: | |
6247 printf("\tli %s,3\n",srn); | |
6248 printf("\tand %s,%s,%s\n",srn,srn,trn); | |
662 | 6249 printf("\tcmplwi %s,%s,0\n",crname(cmpflag),srn); |
667 | 6250 printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel); |
302 | 6251 break; |
300 | 6252 default: |
302 | 6253 urn = register_name(u=get_register()); |
6254 printf("\tli %s,%d\n",srn,delta); | |
6255 printf("\tdivwu %s,%s,%s\n",urn,trn,srn); | |
6256 printf("\tmullw %s,%s,%s\n",srn,urn,srn); | |
6257 printf("\tsubf %s,%s,%s\n",srn,trn,srn); | |
662 | 6258 printf("\tcmplwi %s,%s,0\n",crname(cmpflag),srn); |
667 | 6259 printf("\tbne\t%s,%s%d\n",crname(cmpflag),lpfx,dlabel); |
302 | 6260 printf("\tslwi %s,%s,2\n",trn,urn); |
300 | 6261 } |
662 | 6262 #ifdef __APPLE__ |
300 | 6263 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n", |
6264 srn,l,code_base); | |
6265 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n", | |
6266 srn,l,code_base,srn); | |
6267 printf("\tadd %s,%s,%s\n",trn,srn,trn); | |
6268 printf("\tlwz r0,0(%s)\n",trn); | |
6269 printf("\tadd r0,r0,%s\n",srn); | |
6270 printf("\tmtctr r0\n"); | |
6271 printf("\tbctr\n"); | |
662 | 6272 #else |
672 | 6273 printf("\tlis %s,%s%d@ha\n",srn,lpfx,l); |
6274 printf("\tla %s,%s%d@l(%s)\n",srn,lpfx,l,srn); | |
662 | 6275 printf("\tadd %s,%s,%s\n",trn,srn,trn); |
6276 printf("\tlwz 0,0(%s)\n",trn); | |
6277 printf("\tadd 0,0,%s\n",srn); | |
6278 printf("\tmtctr 0\n"); | |
6279 printf("\tbctr\n"); | |
6280 #endif | |
300 | 6281 |
6282 free_register(s); | |
6283 free_register(t); | |
302 | 6284 if (u!=-1) free_register(u); |
300 | 6285 } |
6286 | |
6287 void | |
6288 code_table_open(int l) | |
6289 { | |
6290 printf("\t.p2align 2\n"); | |
6291 fwddef(l); | |
6292 } | |
6293 | |
6294 void | |
6295 code_table_value(int label,int table_top) | |
6296 { | |
662 | 6297 printf("\t.long %s%d-%s%d\n",lpfx,label,lpfx,table_top); |
300 | 6298 } |
6299 | |
6300 void | |
6301 code_table_close() | |
6302 { | |
6303 } | |
6304 | |
6305 #endif | |
6306 | |
316 | 6307 #if ASM_CODE |
6308 | |
318 | 6309 /* |
320 | 6310 print an operand |
318 | 6311 */ |
6312 | |
6313 static void | |
320 | 6314 emit_asm_operand(int rstr) |
318 | 6315 { |
6316 if (car(rstr)==REGISTER) { | |
6317 printf("%s",register_name(cadr(rstr))); | |
6318 } else if (car(rstr)==CONST) { | |
6319 printf("%d",cadr(rstr)); | |
319 | 6320 } else if (car(rstr)==FNAME) { |
711 | 6321 printf("%s",ncaddr(rstr)->nm); |
6322 } else if (car(rstr)==LABEL) { | |
6323 printf("%s%d:\n",lpfx,cadr(rstr)); | |
318 | 6324 } else { |
6325 error(-1); | |
6326 } | |
6327 } | |
6328 | |
320 | 6329 /* |
6330 prepare asm operands | |
6331 | |
6332 char *constraints sgtring | |
326 | 6333 int oeprand expr |
320 | 6334 int mode (ASM_INPUT,ASM_OUTPUT) |
6335 int replacement list | |
6336 int output operands count | |
6337 int output operands replacement list | |
6338 | |
6339 retrun replacement list | |
6340 list3( operands, next, clobber ) | |
6341 0 can be shared in input/output | |
6342 1 can't be used in input | |
6343 */ | |
6344 | |
327 | 6345 extern int |
6346 code_asm_operand(char *p,int e1,int mode,int repl,int n,int repl0) | |
318 | 6347 { |
6348 int r; | |
6349 int c; | |
6350 int val; | |
6351 int clobber = 0; | |
6352 | |
527 | 6353 printf("## constraint %s\n",p); |
6354 retry: | |
6355 switch((c=*p)) { | |
6356 case '?': | |
6357 case '!': | |
6358 case '+': | |
6359 case '%': | |
6360 case '#': | |
6361 case '*': | |
6362 case '=': | |
318 | 6363 // output register |
6364 p++; | |
527 | 6365 goto retry; |
6366 case '&': | |
318 | 6367 // earlyclobber |
6368 p++; | |
6369 clobber = 1; | |
527 | 6370 goto retry; |
6371 case 'b': // address base register (what?) | |
6372 case 'r': | |
318 | 6373 if (mode==ASM_INPUT) { |
6374 for(;repl0;repl0 = cadr(repl0)) { | |
6375 if (car(car(repl0))==REGISTER && caddr(repl0)==0) { | |
6376 r = cadr(car(repl0)); | |
6377 caddr(repl0) = ASM_USED; | |
6378 break; | |
6379 } | |
6380 } | |
6381 r = get_register(); | |
6382 } else { | |
6383 r = get_register(); | |
6384 } | |
6385 repl = list3(list2(REGISTER,r),repl,clobber); | |
527 | 6386 break; |
6387 case 'm': | |
319 | 6388 repl = list3(list2(0,0),repl,clobber); |
527 | 6389 break; |
6390 case 'i': | |
368 | 6391 if (car(e1)==GVAR) { |
711 | 6392 e1=list3n(FNAME,0,ncaddr(e1)); |
368 | 6393 } else if (car(e1)==FNAME) { |
711 | 6394 e1=list3n(FNAME,0,ncaddr(e1)); |
319 | 6395 } else if (car(e1)==STRING) { |
6396 val = emit_string_label(); | |
712 | 6397 ascii(ncaddr(e1)->nm); |
711 | 6398 e1=list2(LABEL,val); |
319 | 6399 } else if (car(e1)==CONST) { |
6400 } else error(-1); | |
318 | 6401 repl = list3(e1,repl,clobber); |
527 | 6402 break; |
6403 case '0': case '1': case '2': case '3': case '4': | |
6404 case '5': case '6': case '7': case '8': case '9': | |
318 | 6405 val = 0; |
6406 do { val = val*10 + c-'0'; } while (digit(c=*p++)); | |
6407 if (val>MAX_ASM_REG) error(-1); // too large register | |
6408 if (n-val<0) error(-1); | |
6409 repl = list3(car(nth(n-val-1,repl0)),repl,clobber); | |
527 | 6410 break; |
6411 default: | |
6412 printf("### unknown asm constraint %c\n",c); | |
6413 } | |
318 | 6414 return repl; |
6415 } | |
6416 | |
320 | 6417 void |
327 | 6418 code_free_asm_operand(int repl) |
318 | 6419 { |
6420 for(;repl;repl=cadr(repl)) { | |
6421 if (car(car(repl))==REGISTER) | |
6422 free_register(cadr(car(repl))); | |
6423 } | |
6424 } | |
6425 | |
320 | 6426 |
6427 extern void | |
327 | 6428 code_asm(char *asm_str,int repl) |
316 | 6429 { |
320 | 6430 int c,i,rstr,val; |
318 | 6431 char *p; |
320 | 6432 int reg[MAX_ASM_REG]; |
6433 | |
516 | 6434 text_mode(0); |
320 | 6435 c = *asm_str; |
6436 if (c!='\t'&&c!=' ') printf("\t"); | |
6437 for(i=0;repl && i<MAX_ASM_REG;i++) { | |
6438 reg[i] = car(repl); | |
6439 repl = cadr(repl); | |
6440 } | |
6441 p = asm_str; | |
6442 while((c = *p++)) { | |
6443 if (c=='%') { | |
6444 c = *p++; | |
6445 if (!c) { break; | |
6446 } else if (c=='%') { | |
6447 printf("%%"); continue; | |
6448 } else if (!digit(c)) { | |
6449 printf("%%%c",c); continue; | |
6450 } | |
6451 val = 0; | |
6452 do { val = val*10 + c-'0'; } while (digit(c=*p++)) ; | |
6453 p--; | |
6454 if (val>MAX_ASM_REG) error(-1); // too large register | |
6455 rstr = reg[val]; | |
6456 emit_asm_operand(rstr); | |
6457 } else { | |
6458 printf("%c",c); | |
318 | 6459 } |
6460 } | |
320 | 6461 printf("\n"); |
316 | 6462 } |
6463 | |
6464 #endif | |
6465 | |
6466 | |
329 | 6467 #if BIT_FIELD_CODE |
6468 | |
6469 /* bit field alignment calcuration */ | |
6470 | |
6471 static void | |
426 | 6472 set_bitsz(int type,int *pbitpos,int *pbitsize, |
6473 int *psign,int *pbitsz,int *palign,int *pl) | |
329 | 6474 { |
569 | 6475 int sign=0,bitsz=0; |
6476 int align=4,l=0; | |
426 | 6477 *pbitpos = cadr(caddr(type)); |
6478 *pbitsize = caddr(caddr(type)); | |
420 | 6479 switch(cadr(type)) { /* value type */ |
329 | 6480 case INT: sign=1; bitsz=32; align=4;break; |
6481 case UNSIGNED: bitsz=32; align=4;break; | |
335 | 6482 case CHAR: sign=1; bitsz= 8; align=1;break; |
6483 case UCHAR: bitsz= 8; align=1;break; | |
329 | 6484 case SHORT: sign=1; bitsz=16; align=2;break; |
6485 case USHORT: sign=1; bitsz=16; align=2;break; | |
676 | 6486 #ifdef __APPLE__ |
329 | 6487 case LONGLONG: sign=1; bitsz=64; align=4;l=1; break; |
6488 case ULONGLONG: bitsz=64; align=4;l=1; break; | |
676 | 6489 #else |
6490 case LONGLONG: sign=1; bitsz=64; align=8;l=1; break; | |
6491 case ULONGLONG: bitsz=64; align=8;l=1; break; | |
6492 #endif | |
329 | 6493 default: error(-1); |
6494 } | |
6495 *psign = sign; | |
6496 *pbitsz = bitsz; | |
6497 *palign = align; | |
6498 *pl = l; | |
6499 } | |
6500 | |
6501 /* | |
6502 bit field alignment calcuration | |
6503 this is architecture depenedent | |
6504 */ | |
6505 | |
6506 extern int | |
6507 code_bit_field_disp(int type,int *poffset,int *bfd,int *sz) | |
6508 { | |
331 | 6509 int sign,bitsz,align; |
329 | 6510 int i; |
6511 int bitpos = *bfd; | |
426 | 6512 int bitpos0; |
6513 int bitsize; | |
329 | 6514 int offset = *poffset; |
6515 int l; | |
426 | 6516 set_bitsz(type,&bitpos0,&bitsize,&sign,&bitsz,&align,&l); |
329 | 6517 |
569 | 6518 if (bitsize>bitsz) { error(BTERR); bitsize = bitsz; } |
329 | 6519 |
6520 /* bfd means previous bit field bit offset */ | |
6521 if (bitpos) { | |
6522 /* previous field is bit field and spaces may remain */ | |
6523 /* calc previsous offset */ | |
6524 | |
6525 i= offset-(bitpos+7)/8; | |
6526 | |
335 | 6527 for(l = bitpos;l>0;l -= 8,i++) { |
336 | 6528 if ((i & (align-1))==0 && l+bitsize <= bitsz) { |
335 | 6529 /* alignment is correct and space remains */ |
6530 *poffset=offset=i; | |
6531 i = l+bitsize; | |
423 | 6532 *bfd = (i==bitsz)?0:i; |
335 | 6533 *sz = (i+7)/8; |
527 | 6534 // printf("## bitpos=%d bitsize=%d bitsz=%d offset=%d\n",l,bitsize,bitsz,*poffset); |
335 | 6535 return l; |
6536 } | |
6537 } | |
329 | 6538 } |
6539 | |
6540 /* first bit-field */ | |
6541 | |
6542 if ((i=(offset & (align-1)))) { | |
335 | 6543 *poffset = (offset += (align-i)); |
329 | 6544 } |
6545 bitpos = 0; | |
426 | 6546 *bfd = (bitsize==bitsz)?0:bitsize; |
329 | 6547 *sz = (bitsize+7)/8; |
6548 | |
527 | 6549 // printf("## bitpos=%d bitsize=%d bitsz=%d offset=%d\n",bitpos,bitsize,bitsz,*poffset); |
329 | 6550 return bitpos; |
6551 } | |
6552 | |
6553 /* bit field value */ | |
6554 | |
6555 extern void | |
426 | 6556 code_bit_field(int type,int adr, int reg) |
329 | 6557 { |
331 | 6558 int sign,bitsz,l,align; |
426 | 6559 int bitsize,bitpos; |
6560 int i,size; | |
6561 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l); | |
6562 size = bitsz/8; | |
527 | 6563 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); |
329 | 6564 /* this implementation returns -1 for int i:1; */ |
6565 if (l==1) { | |
440 | 6566 #if LONGLONG_CODE |
431 | 6567 // use_int(adr); |
329 | 6568 use_longlong(reg); |
426 | 6569 lload(adr,reg,0); |
329 | 6570 /* shift left */ |
331 | 6571 if (bitpos) |
335 | 6572 loprtc(LLSHIFT,reg,list2(CONST,bitpos)); |
329 | 6573 /* shift right */ |
6574 if ((i=bitsz-bitsize)) | |
335 | 6575 loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i)); |
440 | 6576 #endif |
329 | 6577 } else { |
431 | 6578 // use_int(adr); |
329 | 6579 use_int(reg); |
662 | 6580 #ifdef __APPLE__ |
426 | 6581 printf("\t%s %s,lo16(%d)(%s)\n",cload(size), |
6582 register_name(reg),0,register_name(adr)); | |
662 | 6583 #else |
6584 printf("\t%s %s,%d@l(%s)\n",cload(size), | |
6585 register_name(reg),0,register_name(adr)); | |
6586 #endif | |
426 | 6587 cext(sign,size,reg); |
329 | 6588 /* shift left */ |
336 | 6589 if ((i=bitpos+(32-bitsz))) |
6590 oprtc(LSHIFT,reg,list2(CONST,i)); | |
329 | 6591 /* shift right */ |
336 | 6592 if ((i=bitsz-bitsize+(32-bitsz))) |
335 | 6593 oprtc(sign?RSHIFT:URSHIFT,reg,list2(CONST,i)); |
329 | 6594 } |
6595 } | |
6596 | |
6597 /* bit field replacement */ | |
6598 | |
330 | 6599 static void |
331 | 6600 make_mask_and_or(int mask,int tmp,char *trn,char *crn,char *lrn) |
330 | 6601 { |
527 | 6602 // printf("## mask 0x%08x ~0x%08x\n",mask,~mask); |
330 | 6603 code_const(~mask,tmp); |
6604 printf("\tor %s,%s,%s\n",trn,crn,trn); | |
6605 /* do conjunction */ | |
6606 printf("\tand %s,%s,%s\n",lrn,trn,lrn); | |
6607 /* make or-mask */ | |
6608 code_const(mask,tmp); | |
6609 printf("\tand %s,%s,%s\n",trn,crn,trn); | |
6610 /* do disjunction */ | |
336 | 6611 printf("\tor %s,%s,%s\n",crn,trn,lrn); |
330 | 6612 } |
6613 | |
329 | 6614 extern void |
431 | 6615 code_bit_replace(int adr,int value,int type) |
329 | 6616 { |
331 | 6617 int sign,bitsz,l,align; |
426 | 6618 int bitsize,bitpos; |
330 | 6619 int mask = 0; |
6620 int tmp = -1; | |
331 | 6621 int i; |
426 | 6622 int lvalue; |
330 | 6623 char *crn,*lrn,*trn; |
426 | 6624 int size; |
6625 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l); | |
6626 size = bitsz/8; | |
467 | 6627 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); |
329 | 6628 if (l) { |
440 | 6629 #if LONGLONG_CODE |
431 | 6630 // use_int(adr); |
426 | 6631 lvalue = get_lregister(); |
431 | 6632 lload(adr,lvalue,0); |
330 | 6633 use_longlong(value); |
6634 crn = lregister_name_low(value); | |
6635 lrn = lregister_name_low(lvalue); | |
329 | 6636 /* shift left */ |
330 | 6637 if ((i=bitsz-bitsize-bitpos)) |
335 | 6638 loprtc(LLSHIFT,value,list2(CONST,i)); |
330 | 6639 trn = register_name(tmp = get_register()); |
336 | 6640 if (bitpos+bitsize>=32) { |
330 | 6641 /* make and-mask lower */ |
336 | 6642 mask = make_mask(bitpos>=32?bitpos-32:0,bitpos+bitsize-32-1); |
330 | 6643 make_mask_and_or(mask,tmp,trn,crn,lrn); |
6644 } | |
6645 crn = lregister_name_high(value); | |
6646 lrn = lregister_name_high(lvalue); | |
6647 if (bitpos<32) { | |
6648 /* make and-mask upper */ | |
336 | 6649 mask = make_mask(bitpos,bitpos+bitsize>=32?31:bitpos+bitsize-1); |
330 | 6650 make_mask_and_or(mask,tmp,trn,crn,lrn); |
6651 } | |
431 | 6652 code_lassign(adr,value); |
426 | 6653 free_register(lvalue); |
431 | 6654 // free_register(adr); |
440 | 6655 #endif |
329 | 6656 } else { |
431 | 6657 // use_int(adr); |
330 | 6658 use_int(value); |
426 | 6659 lvalue = get_register(); |
662 | 6660 #ifdef __APPLE__ |
426 | 6661 printf("\t%s %s,lo16(%d)(%s)\n",cload(size), |
431 | 6662 register_name(lvalue),0,register_name(adr)); |
662 | 6663 #else |
6664 printf("\t%s %s,%d@l(%s)\n",cload(size), | |
6665 register_name(lvalue),0,register_name(adr)); | |
6666 #endif | |
426 | 6667 cext(sign,size,lvalue); |
330 | 6668 crn = register_name(value); |
6669 lrn = register_name(lvalue); | |
6670 /* shift left */ | |
6671 if ((i=bitsz-bitsize-bitpos)) | |
335 | 6672 oprtc(LSHIFT,value,list2(CONST,i)); |
330 | 6673 trn = register_name(tmp = get_register()); |
329 | 6674 /* make and-mask */ |
336 | 6675 mask = make_mask(bitpos+(32-bitsz),bitpos+bitsize-1+(32-bitsz)); |
330 | 6676 make_mask_and_or(mask,tmp,trn,crn,lrn); |
426 | 6677 free_register(lvalue); |
431 | 6678 code_assign(adr,size,value); |
329 | 6679 } |
330 | 6680 if (tmp!=-1) free_register(tmp); |
426 | 6681 if (use) { |
431 | 6682 code_bit_field(type,adr,USE_CREG); |
426 | 6683 } |
329 | 6684 } |
6685 | |
365 | 6686 static void |
6687 make_mask_and_or_const(int mask,char *crn,int c) | |
6688 { | |
6689 char *trn; | |
6690 int tmp = -1; | |
527 | 6691 // printf("## mask 0x%08x ~0x%08x\n",mask,~mask); |
365 | 6692 if ((~mask|c)!=-1) { |
6693 trn = register_name(tmp=get_register()); | |
6694 code_const((~mask|c),tmp); | |
6695 /* do conjunction */ | |
6696 printf("\tand %s,%s,%s\n",crn,trn,crn); | |
6697 } | |
6698 /* make or-mask */ | |
6699 c = mask&c; | |
6700 if (c!=0) { | |
6701 /* do disjunction */ | |
6702 if (!((mask&c)&0xffff0000)) { | |
662 | 6703 #ifdef __APPLE__ |
365 | 6704 printf("\tori %s,%s,lo16(%d)\n",crn,crn,c); |
662 | 6705 #else |
6706 printf("\tori %s,%s,%d@l\n",crn,crn,c); | |
6707 #endif | |
365 | 6708 } else { |
6709 trn = register_name(tmp=get_register()); | |
6710 code_const(c,tmp); | |
6711 printf("\tor %s,%s,%s\n",crn,trn,crn); | |
6712 } | |
6713 } | |
6714 if (tmp!=-1) free_register(tmp); | |
6715 } | |
6716 | |
6717 extern void | |
431 | 6718 code_bit_replace_const(int value,int adr,int type) |
365 | 6719 { |
6720 int sign,bitsz,l,align; | |
426 | 6721 int bitsize,bitpos,size; |
365 | 6722 int mask = 0; |
6723 int i; | |
6724 int c; | |
426 | 6725 int lvalue; |
365 | 6726 #if LONGLONG_CODE |
6727 long long lc; | |
6728 #endif | |
6729 char *crn; | |
426 | 6730 set_bitsz(type,&bitpos,&bitsize,&sign,&bitsz,&align,&l); |
6731 size = bitsz/8; | |
467 | 6732 // printf("## %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); |
365 | 6733 if (l) { |
6734 #if LONGLONG_CODE | |
431 | 6735 use_int(adr); |
426 | 6736 lvalue = get_lregister(); |
431 | 6737 lload(adr,lvalue,0); |
365 | 6738 crn = lregister_name_low(lvalue); |
6739 /* shift left */ | |
6740 lc = lcadr(value); | |
6741 if ((i=bitsz-bitsize-bitpos)) | |
6742 lc <<= i; | |
6743 if (bitpos+bitsize>=32) { | |
6744 /* make and-mask lower */ | |
6745 mask = make_mask(bitpos>=32?bitpos-32:0,bitpos+bitsize-32-1); | |
6746 make_mask_and_or_const(mask,crn,(int)lc); | |
6747 } | |
6748 crn = lregister_name_high(lvalue); | |
6749 if (bitpos<32) { | |
6750 /* make and-mask upper */ | |
6751 mask = make_mask(bitpos,bitpos+bitsize>=32?31:bitpos+bitsize-1); | |
6752 make_mask_and_or_const(mask,crn,(int)(lc>>32)); | |
6753 } | |
431 | 6754 code_lassign(adr,lvalue); |
426 | 6755 free_register(lvalue); |
365 | 6756 #endif |
6757 } else { | |
431 | 6758 use_int(adr); |
426 | 6759 lvalue = get_register(); |
662 | 6760 #ifdef __APPLE__ |
426 | 6761 printf("\t%s %s,lo16(%d)(%s)\n",cload(size), |
431 | 6762 register_name(lvalue),0,register_name(adr)); |
662 | 6763 #else |
6764 printf("\t%s %s,%d@l(%s)\n",cload(size), | |
6765 register_name(lvalue),0,register_name(adr)); | |
6766 #endif | |
426 | 6767 cext(sign,size,lvalue); |
365 | 6768 crn = register_name(lvalue); |
6769 /* shift left */ | |
6770 c = cadr(value); | |
6771 if ((i=bitsz-bitsize-bitpos)) | |
6772 c <<= i; | |
6773 /* make and-mask */ | |
6774 mask = make_mask(bitpos+(32-bitsz),bitpos+bitsize-1+(32-bitsz)); | |
6775 make_mask_and_or_const(mask,crn,c); | |
431 | 6776 code_assign(adr,size,lvalue); |
426 | 6777 free_register(lvalue); |
6778 } | |
6779 if (use) { | |
431 | 6780 code_bit_field(type,adr,USE_CREG); |
365 | 6781 } |
6782 } | |
6783 | |
329 | 6784 #endif |
6785 | |
715 | 6786 extern int |
782
003067098032
code argument offset in caller and callee
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
780
diff
changeset
|
6787 code_arg_alignment(int args,NMTBL *n, int type0,int sz, int is_code) |
003067098032
code argument offset in caller and callee
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
780
diff
changeset
|
6788 { |
003067098032
code argument offset in caller and callee
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
780
diff
changeset
|
6789 return code_arg_alignment0(args,n, type0,sz, is_code); |
715 | 6790 } |
6791 | |
6792 | |
6793 extern int | |
6794 code_lvar_alignment(int args,NMTBL *n, int type0,int sz) | |
6795 { | |
6796 return code_lvar_alignment0(args,n, type0,sz); | |
6797 } | |
6798 | |
6799 | |
89 | 6800 /* end */ |