/[qemu]/qemu/dyngen.c
ViewVC logotype

Diff of /qemu/dyngen.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.18 by bellard, Thu Jun 5 00:56:05 2003 UTC revision 1.19 by bellard, Mon Jun 9 15:34:19 2003 UTC
# Line 79  Line 79 
79  #define elf_check_arch(x) ((x) == EM_SPARCV9)  #define elf_check_arch(x) ((x) == EM_SPARCV9)
80  #define ELF_USES_RELOCA  #define ELF_USES_RELOCA
81    
82    #elif defined(HOST_ARM)
83    
84    #define ELF_CLASS       ELFCLASS32
85    #define ELF_ARCH        EM_ARM
86    #define elf_check_arch(x) ((x) == EM_ARM)
87    #define ELF_USES_RELOC
88    
89  #else  #else
90  #error unsupported CPU - please update the code  #error unsupported CPU - please update the code
91  #endif  #endif
# Line 301  int strstart(const char *str, const char Line 308  int strstart(const char *str, const char
308      return 1;      return 1;
309  }  }
310    
311    #ifdef HOST_ARM
312    
313    int arm_emit_ldr_info(const char *name, unsigned long start_offset,
314                          FILE *outfile, uint8_t *p_start, uint8_t *p_end,
315                          ELF_RELOC *relocs, int nb_relocs)
316    {
317        uint8_t *p;
318        uint32_t insn;
319        int offset, min_offset, pc_offset, data_size;
320        uint8_t data_allocated[1024];
321        unsigned int data_index;
322        
323        memset(data_allocated, 0, sizeof(data_allocated));
324        
325        p = p_start;
326        min_offset = p_end - p_start;
327        while (p < p_start + min_offset) {
328            insn = get32((uint32_t *)p);
329            if ((insn & 0x0d5f0000) == 0x051f0000) {
330                /* ldr reg, [pc, #im] */
331                offset = insn & 0xfff;
332                if (!(insn & 0x00800000))
333                            offset = -offset;
334                if ((offset & 3) !=0)
335                    error("%s:%04x: ldr pc offset must be 32 bit aligned",
336                          name, start_offset + p - p_start);
337                pc_offset = p - p_start + offset + 8;
338                if (pc_offset <= (p - p_start) ||
339                    pc_offset >= (p_end - p_start))
340                    error("%s:%04x: ldr pc offset must point inside the function code",
341                          name, start_offset + p - p_start);
342                if (pc_offset < min_offset)
343                    min_offset = pc_offset;
344                if (outfile) {
345                    /* ldr position */
346                    fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
347                            p - p_start);
348                    /* ldr data index */
349                    data_index = ((p_end - p_start) - pc_offset - 4) >> 2;
350                    fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n",
351                            data_index);
352                    fprintf(outfile, "    arm_ldr_ptr++;\n");
353                    if (data_index >= sizeof(data_allocated))
354                        error("%s: too many data", name);
355                    if (!data_allocated[data_index]) {
356                        ELF_RELOC *rel;
357                        int i, addend, type;
358                        const char *sym_name, *p;
359                        char relname[1024];
360    
361                        data_allocated[data_index] = 1;
362    
363                        /* data value */
364                        addend = get32((uint32_t *)(p_start + pc_offset));
365                        relname[0] = '\0';
366                        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
367                            if (rel->r_offset == (pc_offset + start_offset)) {
368                                sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
369                                /* the compiler leave some unnecessary references to the code */
370                                if (strstart(sym_name, "__op_param", &p)) {
371                                    snprintf(relname, sizeof(relname), "param%s", p);
372                                } else {
373                                    snprintf(relname, sizeof(relname), "(long)(&%s)", sym_name);
374                                }
375                                type = ELF32_R_TYPE(rel->r_info);
376                                if (type != R_ARM_ABS32)
377                                    error("%s: unsupported data relocation", name);
378                                break;
379                            }
380                        }
381                        fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
382                                data_index, addend);
383                        if (relname[0] != '\0')
384                            fprintf(outfile, " + %s", relname);
385                        fprintf(outfile, ";\n");
386                    }
387                }
388            }
389            p += 4;
390        }
391        data_size = (p_end - p_start) - min_offset;
392        if (data_size > 0 && outfile) {
393            fprintf(outfile, "    arm_data_ptr += %d;\n", data_size >> 2);
394        }
395    
396        /* the last instruction must be a mov pc, lr */
397        if (p == p_start)
398            goto arm_ret_error;
399        p -= 4;
400        insn = get32((uint32_t *)p);
401        if ((insn & 0xffff0000) != 0xe91b0000) {
402        arm_ret_error:
403            if (!outfile)
404                printf("%s: invalid epilog\n", name);
405        }
406        return p - p_start;    
407    }
408    #endif
409    
410    
411  #define MAX_ARGS 3  #define MAX_ARGS 3
412    
413  /* generate op code */  /* generate op code */
# Line 388  void gen_code(const char *name, host_ulo Line 495  void gen_code(const char *name, host_ulo
495      case EM_SPARC:      case EM_SPARC:
496      case EM_SPARC32PLUS:      case EM_SPARC32PLUS:
497          {          {
498              uint32_t start_insn, end_insn1, end_insn2, skip_insn;              uint32_t start_insn, end_insn1, end_insn2;
499              uint8_t *p;              uint8_t *p;
500              p = (void *)(p_end - 8);              p = (void *)(p_end - 8);
501              if (p <= p_start)              if (p <= p_start)
# Line 406  void gen_code(const char *name, host_ulo Line 513  void gen_code(const char *name, host_ulo
513              } else {              } else {
514                  error("No save at the beginning of %s", name);                  error("No save at the beginning of %s", name);
515              }              }
516    #if 0
517              /* Skip a preceeding nop, if present.  */              /* Skip a preceeding nop, if present.  */
518              if (p > p_start) {              if (p > p_start) {
519                  skip_insn = get32((uint32_t *)(p - 0x4));                  skip_insn = get32((uint32_t *)(p - 0x4));
520                  if (skip_insn == 0x01000000)                  if (skip_insn == 0x01000000)
521                      p -= 4;                      p -= 4;
522              }              }
523    #endif
524              copy_size = p - p_start;              copy_size = p - p_start;
525          }          }
526          break;          break;
# Line 448  void gen_code(const char *name, host_ulo Line 555  void gen_code(const char *name, host_ulo
555              copy_size = p - p_start;              copy_size = p - p_start;
556          }          }
557          break;          break;
558    #ifdef HOST_ARM
559        case EM_ARM:
560            if ((p_end - p_start) <= 16)
561                error("%s: function too small", name);
562            if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
563                (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||
564                get32((uint32_t *)(p_start + 8)) != 0xe24cb004)
565                error("%s: invalid prolog", name);
566            p_start += 12;
567            start_offset += 12;
568            copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
569                                          relocs, nb_relocs);
570            break;
571    #endif
572      default:      default:
573          error("unknown ELF architecture");          error("unknown ELF architecture");
574      }      }
# Line 458  void gen_code(const char *name, host_ulo Line 579  void gen_code(const char *name, host_ulo
579    
580      for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {      for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
581          if (rel->r_offset >= start_offset &&          if (rel->r_offset >= start_offset &&
582              rel->r_offset < start_offset + copy_size) {              rel->r_offset < start_offset + (p_end - p_start)) {
583              sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;              sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
584              if (strstart(sym_name, "__op_param", &p)) {              if (strstart(sym_name, "__op_param", &p)) {
585                  n = strtoul(p, NULL, 10);                  n = strtoul(p, NULL, 10);
# Line 496  void gen_code(const char *name, host_ulo Line 617  void gen_code(const char *name, host_ulo
617    
618          for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {          for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
619              if (rel->r_offset >= start_offset &&              if (rel->r_offset >= start_offset &&
620                  rel->r_offset < start_offset + copy_size) {                  rel->r_offset < start_offset + (p_end - p_start)) {
621                  sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;                  sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
622                  if (*sym_name &&                  if (*sym_name &&
623                      !strstart(sym_name, "__op_param", NULL) &&                      !strstart(sym_name, "__op_param", NULL) &&
# Line 900  void gen_code(const char *name, host_ulo Line 1021  void gen_code(const char *name, host_ulo
1021                      }                      }
1022                  }                  }
1023              }              }
1024    #elif defined(HOST_ARM)
1025                {
1026                    char name[256];
1027                    int type;
1028                    int addend;
1029    
1030                    arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
1031                                      relocs, nb_relocs);
1032    
1033                    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1034                    if (rel->r_offset >= start_offset &&
1035                        rel->r_offset < start_offset + copy_size) {
1036                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1037                        /* the compiler leave some unnecessary references to the code */
1038                        if (sym_name[0] == '\0')
1039                            continue;
1040                        if (strstart(sym_name, "__op_param", &p)) {
1041                            snprintf(name, sizeof(name), "param%s", p);
1042                        } else {
1043                            snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
1044                        }
1045                        type = ELF32_R_TYPE(rel->r_info);
1046                        addend = get32((uint32_t *)(text + rel->r_offset));
1047                        switch(type) {
1048                        case R_ARM_ABS32:
1049                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1050                                    rel->r_offset - start_offset, name, addend);
1051                            break;
1052                        case R_ARM_PC24:
1053                            fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
1054                                    rel->r_offset - start_offset, addend, name);
1055                            break;
1056                        default:
1057                            error("unsupported arm relocation (%d)", type);
1058                        }
1059                    }
1060                    }
1061                }
1062  #else  #else
1063  #error unsupported CPU  #error unsupported CPU
1064  #endif  #endif
# Line 1075  fprintf(outfile, Line 1234  fprintf(outfile,
1234  "{\n"  "{\n"
1235  "    uint8_t *gen_code_ptr;\n"  "    uint8_t *gen_code_ptr;\n"
1236  "    const uint16_t *opc_ptr;\n"  "    const uint16_t *opc_ptr;\n"
1237  "    const uint32_t *opparam_ptr;\n"  "    const uint32_t *opparam_ptr;\n");
1238    
1239    #ifdef HOST_ARM
1240    fprintf(outfile,
1241    "    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
1242    "    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
1243    "    uint32_t *arm_data_ptr = arm_data_table;\n");
1244    #endif
1245    
1246    fprintf(outfile,
1247    "\n"
1248  "    gen_code_ptr = gen_code_buf;\n"  "    gen_code_ptr = gen_code_buf;\n"
1249  "    opc_ptr = opc_buf;\n"  "    opc_ptr = opc_buf;\n"
1250  "    opparam_ptr = opparam_buf;\n");  "    opparam_ptr = opparam_buf;\n");
1251    
1252          /* Generate prologue, if needed. */          /* Generate prologue, if needed. */
         switch(ELF_ARCH) {  
         case EM_SPARC:  
                 fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a080; /* sub %%sp, 128, %%sp */\n");  
                 fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a080; /* sub %%fp, 128, %%fp */\n");  
                 break;  
   
         case EM_SPARCV9:  
                 fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a100; /* sub %%sp, 256, %%sp */\n");  
                 fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a100; /* sub %%fp, 256, %%fp */\n");  
                 break;  
         };  
1253    
1254  fprintf(outfile,  fprintf(outfile,
1255  "    for(;;) {\n"  "    for(;;) {\n"
# Line 1116  fprintf(outfile, Line 1274  fprintf(outfile,
1274  fprintf(outfile,  fprintf(outfile,
1275  "        default:\n"  "        default:\n"
1276  "            goto the_end;\n"  "            goto the_end;\n"
1277  "        }\n"  "        }\n");
1278    
1279    #ifdef HOST_ARM
1280    /* generate constant table if needed */
1281    fprintf(outfile,
1282    "        if ((gen_code_ptr - last_gen_code_ptr) >= (MAX_FRAG_SIZE - MAX_OP_SIZE)) {\n"
1283    "            gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 1);\n"
1284    "            last_gen_code_ptr = gen_code_ptr;\n"
1285    "            arm_ldr_ptr = arm_ldr_table;\n"
1286    "            arm_data_ptr = arm_data_table;\n"
1287    "        }\n");        
1288    #endif
1289    
1290    
1291    fprintf(outfile,
1292  "    }\n"  "    }\n"
1293  " the_end:\n"  " the_end:\n"
1294  );  );
# Line 1140  fprintf(outfile, Line 1312  fprintf(outfile,
1312          break;          break;
1313      case EM_SPARC:      case EM_SPARC:
1314      case EM_SPARC32PLUS:      case EM_SPARC32PLUS:
         fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc07a080; /* add %%fp, 256, %%fp */\n");  
1315          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c62008; /* jmpl %%i0 + 8, %%g0 */\n");          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c62008; /* jmpl %%i0 + 8, %%g0 */\n");
1316          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c03a080; /* add %%sp, 256, %%sp */\n");          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x01000000; /* nop */\n");
1317          break;          break;
1318      case EM_SPARCV9:      case EM_SPARCV9:
1319          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret */\n");          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret */\n");
1320          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* restore */\n");          fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* restore */\n");
1321          break;          break;
1322        case EM_ARM:
1323            fprintf(outfile, "gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 0);\n");
1324            break;
1325      default:      default:
1326          error("unknown ELF architecture");          error("unknown ELF architecture");
1327      }      }

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26