Mercurial > hg > CbC > old > device
comparison mc-code-arm.c @ 372:81345636387d
arm continue...
author | kono |
---|---|
date | Sat, 10 Jul 2004 21:46:21 +0900 |
parents | 238c3704ee3d |
children | 9bc42f69f653 |
comparison
equal
deleted
inserted
replaced
371:238c3704ee3d | 372:81345636387d |
---|---|
9 #include "mc-codegen.h" | 9 #include "mc-codegen.h" |
10 | 10 |
11 #define Linux_Zaurus 1 | 11 #define Linux_Zaurus 1 |
12 #define GameBoyAdvance 2 | 12 #define GameBoyAdvance 2 |
13 | 13 |
14 int arc_mode = Linux_Zaurus; | 14 int arch_mode = Linux_Zaurus; |
15 | 15 |
16 char **l_include_path[]; | 16 char **l_include_path[]; |
17 | 17 |
18 char *l_include_path_zaurus[] = { | 18 char *l_include_path_zaurus[] = { |
19 "/Developer/Zaurus-X-gcc/opt/Embedix/tools/arm-linux/include", | 19 "/Developer/Zaurus-X-gcc/opt/Embedix/tools/arm-linux/include", |
43 | 43 |
44 static int creg; | 44 static int creg; |
45 | 45 |
46 static int output_mode = TEXT_EMIT_MODE; | 46 static int output_mode = TEXT_EMIT_MODE; |
47 | 47 |
48 static FILE *asi; | |
49 | |
50 static int cprestore_label; | 48 static int cprestore_label; |
51 static int fmask_label; | 49 static int fmask_label; |
52 static int fmask_offset_label; | 50 static int fmask_offset_label; |
53 static int mask_label; | 51 static int mask_label; |
54 static int mask_offset_label; | 52 static int mask_offset_label; |
129 #define FREGISTER_OPERAND (FREG_OFFSET +12) | 127 #define FREGISTER_OPERAND (FREG_OFFSET +12) |
130 | 128 |
131 #define RET_LREGISTER (LREG_OFFSET+REAL_MAX_LREGISTER) | 129 #define RET_LREGISTER (LREG_OFFSET+REAL_MAX_LREGISTER) |
132 #define LREGISTER_OPERAND (LREG_OFFSET +REAL_MAX_LREGISTER +1) | 130 #define LREGISTER_OPERAND (LREG_OFFSET +REAL_MAX_LREGISTER +1) |
133 #define LREGISTER_OPERAND_1 (LREG_OFFSET +REAL_MAX_LREGISTER +2) | 131 #define LREGISTER_OPERAND_1 (LREG_OFFSET +REAL_MAX_LREGISTER +2) |
134 #define RET_LREGISTER_L 2 /* low word */ | 132 #define RET_LREGISTER_L 0 /* low word */ |
135 #define RET_LREGISTER_H 3 /* high word */ | 133 #define RET_LREGISTER_H 1 /* high word */ |
136 #define LREGISTER_OPERAND_L 4 /* low word */ | 134 #define LREGISTER_OPERAND_L 0 /* low word */ |
137 #define LREGISTER_OPERAND_H 5 /* high word */ | 135 #define LREGISTER_OPERAND_H 1 /* high word */ |
138 #define LREGISTER_OPERAND_1_L 6 /* low word */ | 136 #define LREGISTER_OPERAND_1_L 2 /* low word */ |
139 #define LREGISTER_OPERAND_1_H 7 /* high word */ | 137 #define LREGISTER_OPERAND_1_H 3 /* high word */ |
140 | 138 |
141 #define RET_DREGISTER RET_LREGISTER | 139 #define RET_DREGISTER RET_LREGISTER |
142 #define DREGISTER_OPERAND LREGISTER_OPERAND | 140 #define DREGISTER_OPERAND LREGISTER_OPERAND |
143 #define DREGISTER_OPERAND_1 LREGISTER_OPERAND_1 | 141 #define DREGISTER_OPERAND_1 LREGISTER_OPERAND_1 |
144 #define RET_DREGISTER_L RET_LREGISTER_L | 142 #define RET_DREGISTER_L RET_LREGISTER_L |
179 char *lh(i) { return lregister_name_high(i); } | 177 char *lh(i) { return lregister_name_high(i); } |
180 | 178 |
181 #define is_int_reg(i) (0<i&&i<REAL_MAX_REGISTER) | 179 #define is_int_reg(i) (0<i&&i<REAL_MAX_REGISTER) |
182 #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) | 180 #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) |
183 #define is_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER+LREG_V) | 181 #define is_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER+LREG_V) |
184 #define is_double_reg(i) is_longlong_reg(i) | 182 #define is_double_reg(i) (arch_mode==GameBoyAdvance?is_longlong_reg(i):is_float_reg(i)) |
185 | 183 |
186 #define use_int(reg) if (reg==USE_CREG) reg=use_int0() | 184 #define use_int(reg) if (reg==USE_CREG) reg=use_int0() |
187 static | 185 static |
188 int use_int0() { | 186 int use_int0() { |
189 int i = creg; | 187 int i = creg; |
222 static void lmove(int to,int from); | 220 static void lmove(int to,int from); |
223 #endif | 221 #endif |
224 | 222 |
225 | 223 |
226 #if FLOAT_CODE | 224 #if FLOAT_CODE |
227 #define use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0() | 225 #define use_float(d,reg) if (reg==USE_CREG) arch_mode==GameBoyAdvance?(reg=d?use_double0():use_float0()):use_float0() |
228 static | 226 static |
229 int use_float0() { | 227 int use_float0() { |
230 int i = creg; | 228 int i = creg; |
231 if (!is_float_reg(i)) { | 229 if (!is_float_reg(i)) { |
232 if (lreg) { free_register(lreg); lreg = 0; } | 230 if (lreg) { free_register(lreg); lreg = 0; } |
295 | 293 |
296 Reorder is automatically done in assembler. | 294 Reorder is automatically done in assembler. |
297 delayed slot done within .set noreorder. | 295 delayed slot done within .set noreorder. |
298 | 296 |
299 r0 return value etc. | 297 r0 return value etc. |
300 $2,$3 return value. (dpcmp return value on $2) | 298 r0,r1 return value. (dpcmp return value on $2) |
301 $0 special register | 299 00 special register |
302 $4-$7 input register | 300 r0-r3 input register |
303 r18-r24 saved register variable (input register for code segment) | 301 r7-r9 saved register variable (input register for code segment) |
304 $25 jump register | 302 jump register |
305 $31 stack pointer | 303 sp stack pointer |
306 $fp frame pointer | 304 fp frame pointer |
307 | 305 |
308 $f0 return value etc. | 306 f0 return value etc. |
309 $f14,$f12 input register | 307 r0-r3 input register |
310 $f20-$f31 saved register variable | 308 f20-f31 saved register variable |
311 | 309 |
312 code segment stack frame | 310 code segment stack frame |
313 | 311 |
314 * gotoを呼び出した関数のr1 ! r1(goto前のr1) | 312 * gotoを呼び出した関数のr1 ! r1(goto前のr1) |
315 # * $fp <---r1_offset---------> $sp | 313 # * $fp <---r1_offset---------> $sp |
358 2*SIZE_OF_INT; | 356 2*SIZE_OF_INT; |
359 r1_offsetv = lvar_offsetv + arg_offset + SIZE_OF_INT*2 + | 357 r1_offsetv = lvar_offsetv + arg_offset + SIZE_OF_INT*2 + |
360 max_reg_var*SIZE_OF_INT+max_freg_var*SIZE_OF_FLOAT+2*SIZE_OF_INT ; | 358 max_reg_var*SIZE_OF_INT+max_freg_var*SIZE_OF_FLOAT+2*SIZE_OF_INT ; |
361 lvar_offsetv += round16(r1_offsetv)-r1_offsetv; | 359 lvar_offsetv += round16(r1_offsetv)-r1_offsetv; |
362 r1_offsetv = round16(r1_offsetv); | 360 r1_offsetv = round16(r1_offsetv); |
361 | |
362 printf(" @ args = %d, pretend = %d, frame = %d\n", | |
363 max_func_args,0,round16(-disp)); | |
364 printf(" @ frame_needed = 1, current_function_anonymous_args = 0\n"); | |
365 | |
363 | 366 |
364 #if 0 | 367 #if 0 |
365 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n", | 368 printf("# vars= %d, regs= %d/%d, args= %d, extra= %d\n", |
366 round16(-disp), | 369 round16(-disp), |
367 max_reg_var+2, | 370 max_reg_var+2, |
387 printf("# min caller arg var=\t%d\n", | 390 printf("# min caller arg var=\t%d\n", |
388 CALLER_ARG(round16(max_func_args*SIZE_OF_INT))); | 391 CALLER_ARG(round16(max_func_args*SIZE_OF_INT))); |
389 printf("# max caller arg var=\t%d\n",CALLER_ARG(0)); | 392 printf("# max caller arg var=\t%d\n",CALLER_ARG(0)); |
390 printf("#\n"); | 393 printf("#\n"); |
391 #endif | 394 #endif |
392 fprintf(asi,"$L_%d=0x%x\n",mask_label,code_mask()); | |
393 fprintf(asi,"$L_%d=%d\n",mask_offset_label,code_mask_offset()); | |
394 fprintf(asi,"$L_%d=0x%x\n",fmask_label,code_fmask()); | |
395 fprintf(asi,"$L_%d=%d\n",fmask_offset_label,code_fmask_offset()); | |
396 fprintf(asi,"$L_%d=%d\n",cprestore_label , | |
397 round16((max_func_args>2?max_func_args:2)*SIZE_OF_INT)); | |
398 fprintf(asi,"$L_%d=%d\n",r1_offset_label,r1_offsetv); | |
399 fprintf(asi,"$L_%d=%d\n",lvar_offset_label,lvar_offsetv); | |
400 | 395 |
401 return r1_offsetv; | 396 return r1_offsetv; |
402 } | 397 } |
403 | 398 |
404 static void | 399 static void |
405 lvar(int l) | 400 lvar(int l) |
406 { | 401 { |
407 if (fnptr->sc==CODE) { | 402 if (fnptr->sc==CODE) { |
408 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | 403 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
409 printf("%d($sp)\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); | 404 printf("[sp, #%d]\n",CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); |
410 } else | 405 } else |
411 printf("%d($fp)\n",CODE_LVAR(l)); | 406 printf("[fp, #%d]\n",CODE_LVAR(l)); |
412 } else if (l<0) { /* local variable */ | 407 } else if (l<0) { /* local variable */ |
413 printf("%d+$L_%d($fp)\n",FUNC_LVAR(l),lvar_offset_label); | 408 printf("[fp, #%d+.L%d]\n",FUNC_LVAR(l),lvar_offset_label); |
414 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | 409 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
415 printf("%d($sp)\n",CALLER_ARG(l-ARG_LVAR_OFFSET)); | 410 printf("[sp, #%d]\n",CALLER_ARG(l-ARG_LVAR_OFFSET)); |
416 } else { /* callee's arguments */ | 411 } else { /* callee's arguments */ |
417 printf("%d+$L_%d($fp)\n",CALLEE_ARG(l),r1_offset_label); | 412 printf("[fp, #%d+.L%d]\n",CALLEE_ARG(l),r1_offset_label); |
418 } | 413 } |
419 } | 414 } |
420 | 415 |
421 static void | 416 static void |
422 lvar_address(int l,int creg) | 417 lvar_address(int l,int creg) |
423 { | 418 { |
424 if (fnptr->sc==CODE) { | 419 if (fnptr->sc==CODE) { |
425 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | 420 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
426 printf("\taddu\t%s,$sp,%d\n", | 421 printf("\tadd\t%s, sp, #%d\n", |
427 register_name(creg),CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); | 422 register_name(creg),CODE_CALLER_ARG(l-ARG_LVAR_OFFSET)); |
428 } else | 423 } else |
429 printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR(l)); | 424 printf("\tadd\t%s, fp,#%d\n",register_name(creg),CODE_LVAR(l)); |
430 } else if (l<0) { /* local variable */ | 425 } else if (l<0) { /* local variable */ |
431 printf("\taddu\t%s,$fp,%d+$L_%d\n",register_name(creg), | 426 printf("\tsub\t%s, fp, #%d+$L_%d\n",register_name(creg), |
432 FUNC_LVAR(l),lvar_offset_label); | 427 FUNC_LVAR(l),lvar_offset_label); |
433 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | 428 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
434 printf("\taddu\t%s,$sp,%d\n", | 429 printf("\tadd\t%s, $sp, #%d\n", |
435 register_name(creg),CALLER_ARG(l-ARG_LVAR_OFFSET)); | 430 register_name(creg),CALLER_ARG(l-ARG_LVAR_OFFSET)); |
436 } else { /* callee's arguments */ | 431 } else { /* callee's arguments */ |
437 printf("\taddu\t%s,$fp,%d+$L_%d\n", | 432 printf("\tsub\t%s, fp, #%d+$L_%d\n", |
438 register_name(creg),CALLEE_ARG(l),r1_offset_label); | 433 register_name(creg),CALLEE_ARG(l),r1_offset_label); |
439 } | 434 } |
440 } | 435 } |
441 | 436 |
442 | 437 |
650 #if FLOAT_CODE | 645 #if FLOAT_CODE |
651 int | 646 int |
652 get_dregister(int d) | 647 get_dregister(int d) |
653 { /* 使われていないレジスタを調べる */ | 648 { /* 使われていないレジスタを調べる */ |
654 int i,reg; | 649 int i,reg; |
655 if (d) { | 650 if (arch_mode==GameBoyAdvance) { |
656 i = get_lregister(); | 651 i = get_lregister(); |
657 if (i!=-1) regs[i]=USING_DREG; | 652 if (i!=-1) regs[i]=USING_DREG; |
658 return i; | 653 return i; |
659 } | 654 } |
660 for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { | 655 for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { |
1139 xreg = reg; | 1134 xreg = reg; |
1140 } | 1135 } |
1141 return xreg; | 1136 return xreg; |
1142 } | 1137 } |
1143 | 1138 |
1139 static int gvar_ref_list; | |
1140 static int gvar_ref_disp; | |
1141 | |
1142 static int | |
1143 new_gvar_ref(NMTBL *nptr) | |
1144 { | |
1145 return | |
1146 gvar_ref_list = | |
1147 glist3((int)nptr,gvar_ref_list,gvar_ref_disp+=SIZE_OF_INT); | |
1148 } | |
1149 | |
1150 static int | |
1151 search_gvar_ref(NMTBL *nptr) | |
1152 { | |
1153 int p; | |
1154 for(p = gvar_ref_list; | |
1155 p && neqname(((NMTBL *)car(p))->nm,nptr->nm);p=cadr(p)); | |
1156 if (p) return caddr(p); | |
1157 return caddr(new_gvar_ref(nptr)); | |
1158 } | |
1159 | |
1160 static void | |
1161 gvar_ref_list() | |
1162 { | |
1163 int p,next,lb; | |
1164 if (control) { | |
1165 lb = fwdlabel(); | |
1166 jmp(lb); | |
1167 printf("\t.align\t2\n"); | |
1168 } | |
1169 gvar_ref_list = reverse0(gvar_ref_list); | |
1170 fwddef(gvar_ref_label); | |
1171 for(p = gvar_ref_list; p ;) { | |
1172 printf("\t.word\t%s\n",((NMTBL *)car(p))->nm); | |
1173 next = cadr(p); | |
1174 free_glist3(p); | |
1175 p = next; | |
1176 } | |
1177 if (lb) { | |
1178 fwddef(lb); | |
1179 } | |
1180 } | |
1181 | |
1144 extern void | 1182 extern void |
1145 code_ptr_cache_def(int r, NMTBL *nptr) | 1183 code_ptr_cache_def(int r, NMTBL *nptr) |
1146 { | 1184 { |
1147 char *rrn = register_name(r); | 1185 char *rrn = register_name(r); |
1148 printf("\tla %s,%s\n",rrn,nptr->nm); | 1186 printf("\tldr %s, .L%d+%d\n",rrn,gvar_ref_label, |
1187 search_gvar_ref(nptr)); | |
1188 } | |
1189 | |
1190 #define mask8(d,bit) (d & (255 << bit)) | |
1191 | |
1192 static void | |
1193 make_const(int c) | |
1194 { | |
1195 int sign,im,jm,km; | |
1196 int min_stage = 4; | |
1197 int msign,mim,mjm,mkm; | |
1198 int id,jd,kd; | |
1199 int i,j,k; | |
1200 for(sign=1;sign>=-1;sign-=2) { | |
1201 int d; | |
1202 if (sign==1) { d = c; } else { d = -c; } | |
1203 if (min_stage==1) break; | |
1204 for(i=24;i>=0;i-=2) { | |
1205 jm = km = 0; | |
1206 if (!(im=mask8(d,i))) continue; | |
1207 id = d - im; | |
1208 if (id==0) { | |
1209 min_stage=1; msign = sign; | |
1210 mim = im;mjm = jm;mkm = km; | |
1211 break; | |
1212 } | |
1213 if (min_stage<=2) continue; | |
1214 for(j=i-8;j>=0;j-=2) { | |
1215 km = 0; | |
1216 if (!(jm=mask8(id,j))) continue; | |
1217 jd = id - jm; | |
1218 if (jd==0) { | |
1219 min_stage=2; msign = sign; | |
1220 mim = im;mjm = jm;mkm = km; | |
1221 break; | |
1222 } | |
1223 if (min_stage<=3) continue; | |
1224 for(k=j-8;k>=0;k-=2) { | |
1225 if (!(km=mask8(jd,k))) continue; | |
1226 kd = jd - km; | |
1227 if (kd==0) { | |
1228 min_stage=3; msign = sign; | |
1229 mim = im;mjm = jm;mkm = km; | |
1230 break; | |
1231 } | |
1232 } | |
1233 } | |
1234 } | |
1235 } | |
1236 if (min_stage<=3) { emit(sign,im,jm,km); } | |
1237 else { print "emit const c\n"; } | |
1149 } | 1238 } |
1150 | 1239 |
1151 static void | 1240 static void |
1152 code_add(int reg,int offset,int r) | 1241 code_add(int reg,int offset,int r) |
1153 { | 1242 { |
1154 char *crn = register_name(reg); | 1243 char *crn = register_name(reg); |
1155 char *rrn = register_name(r); | 1244 char *rrn = register_name(r); |
1156 if (offset==0) { | 1245 if (offset==0) { |
1157 if(r!=reg) | 1246 if(r!=reg) |
1158 printf("\tmove %s,%s\n",crn,rrn); | 1247 printf("\tmov %s,%s\n",crn,rrn); |
1159 } else | 1248 } else if (offset > 0) { |
1160 printf("\taddu %s,%s,%d\n",crn,rrn,offset); | 1249 if (offset> |
1250 printf("\tadd %s, %s, #%d\n",crn,rrn,offset); | |
1251 } else { | |
1252 } | |
1161 } | 1253 } |
1162 | 1254 |
1163 | 1255 |
1164 static void | 1256 static void |
1165 code_ld(char *ld,int reg,int offset,int r) | 1257 code_ld(char *ld,int reg,int offset,int r) |
2747 | 2839 |
2748 void | 2840 void |
2749 code_opening(char *filename) | 2841 code_opening(char *filename) |
2750 { | 2842 { |
2751 static int count=0; | 2843 static int count=0; |
2752 char *asi_name; | |
2753 /* this is called once per file */ | 2844 /* this is called once per file */ |
2754 printf("\t.file %d \"%s\"\n",count++,filename); | 2845 printf("\t.file %d \"%s\"\n",count++,filename); |
2755 printf(".abicalls\n"); | |
2756 printf(".text\n"); | 2846 printf(".text\n"); |
2757 | 2847 |
2758 if (asi) { | |
2759 fclose(asi); | |
2760 asi = 0; | |
2761 } | |
2762 asi_name = make_filename_with_extension(filename,"i"); | |
2763 if ( (asi = fopen(asi_name,"w")) == NULL ) error(FILERR); | |
2764 if (!asi) error(-1); | |
2765 printf(".include \"%s\"\n",asi_name); | |
2766 } | 2848 } |
2767 | 2849 |
2768 // should have pcond_const | 2850 // should have pcond_const |
2769 | 2851 |
2770 #define COND_BRANCH 1 | 2852 #define COND_BRANCH 1 |
3146 // leave part end | 3228 // leave part end |
3147 | 3229 |
3148 // entry part (save register) | 3230 // entry part (save register) |
3149 | 3231 |
3150 if (max_reg_var+max_freg_var==0) { | 3232 if (max_reg_var+max_freg_var==0) { |
3151 fprintf(asi,"$L_%d=$L_%d\n", | |
3152 register_save_label,register_save_return_label); | |
3153 } else { | 3233 } else { |
3154 code_label(register_save_label); | 3234 code_label(register_save_label); |
3155 code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2); | 3235 code_register_save(max_reg_var,max_freg_var,-arg_offset-SIZE_OF_INT*2); |
3156 jmp(register_save_return_label); | 3236 jmp(register_save_return_label); |
3157 } | 3237 } |
3397 void | 3477 void |
3398 local_table(void) | 3478 local_table(void) |
3399 { | 3479 { |
3400 NMTBL *n; | 3480 NMTBL *n; |
3401 int init; | 3481 int init; |
3482 gvar_ref_list(); | |
3402 init=0; | 3483 init=0; |
3403 /* static local variables */ | 3484 /* static local variables */ |
3404 for(n=local_static_list;n;n=n->next) { | 3485 for(n=local_static_list;n;n=n->next) { |
3405 if (n->sc == GVAR) { | 3486 if (n->sc == GVAR) { |
3406 if (n->dsp != -1) { /* initialized static */ | 3487 if (n->dsp != -1) { /* initialized static */ |
5212 void | 5293 void |
5213 code_closing() | 5294 code_closing() |
5214 { | 5295 { |
5215 global_table(); | 5296 global_table(); |
5216 /* printf("\t.ident \"Micro-C compiled\"\n"); */ | 5297 /* printf("\t.ident \"Micro-C compiled\"\n"); */ |
5217 fclose(asi); asi=0; | |
5218 } | 5298 } |
5219 | 5299 |
5220 #if CASE_CODE | 5300 #if CASE_CODE |
5221 | 5301 |
5222 int | 5302 int |