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