Sparc update (David S. Miller)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@161 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									d418c81eff
								
							
						
					
					
						commit
						ae22853141
					
				
							
								
								
									
										12
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										12
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS)
 | 
			
		|||
LDFLAGS+=-Wl,-T,s390.ld
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(ARCH),sparc)
 | 
			
		||||
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
 | 
			
		||||
LDFLAGS+=-m32
 | 
			
		||||
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(ARCH),sparc64)
 | 
			
		||||
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
 | 
			
		||||
LDFLAGS+=-m64
 | 
			
		||||
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(ARCH),alpha)
 | 
			
		||||
# -msmall-data is not used because we want two-instruction relocations
 | 
			
		||||
# for the constant constructions
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,12 @@ case "$cpu" in
 | 
			
		|||
  s390)
 | 
			
		||||
    cpu="s390"
 | 
			
		||||
  ;;
 | 
			
		||||
  sparc)
 | 
			
		||||
    cpu="sparc"
 | 
			
		||||
  ;;
 | 
			
		||||
  sparc64)
 | 
			
		||||
    cpu="sparc64"
 | 
			
		||||
  ;;
 | 
			
		||||
  ia64)
 | 
			
		||||
    cpu="ia64"
 | 
			
		||||
  ;;
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +137,7 @@ fi
 | 
			
		|||
else
 | 
			
		||||
 | 
			
		||||
# if cross compiling, cannot launch a program, so make a static guess
 | 
			
		||||
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
 | 
			
		||||
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64"; then
 | 
			
		||||
    bigendian="yes"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then
 | 
			
		|||
elif test "$cpu" = "alpha" ; then
 | 
			
		||||
  echo "ARCH=alpha" >> config.mak
 | 
			
		||||
  echo "#define HOST_ALPHA 1" >> $TMPH
 | 
			
		||||
elif test "$cpu" = "sparc" ; then
 | 
			
		||||
  echo "ARCH=sparc" >> config.mak
 | 
			
		||||
  echo "#define HOST_SPARC 1" >> $TMPH
 | 
			
		||||
elif test "$cpu" = "sparc64" ; then
 | 
			
		||||
  echo "ARCH=sparc64" >> config.mak
 | 
			
		||||
  echo "#define HOST_SPARC64 1" >> $TMPH
 | 
			
		||||
elif test "$cpu" = "ia64" ; then
 | 
			
		||||
  echo "ARCH=ia64" >> config.mak
 | 
			
		||||
  echo "#define HOST_IA64 1" >> $TMPH
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										200
									
								
								dyngen.c
								
								
								
								
							
							
						
						
									
										200
									
								
								dyngen.c
								
								
								
								
							| 
						 | 
				
			
			@ -274,14 +274,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
{
 | 
			
		||||
    int copy_size = 0;
 | 
			
		||||
    uint8_t *p_start, *p_end;
 | 
			
		||||
    host_ulong start_offset;
 | 
			
		||||
    int nb_args, i, n;
 | 
			
		||||
    uint8_t args_present[MAX_ARGS];
 | 
			
		||||
    const char *sym_name, *p;
 | 
			
		||||
    ELF_RELOC *rel;
 | 
			
		||||
 | 
			
		||||
    /* compute exact size excluding return instruction */
 | 
			
		||||
    /* Compute exact size excluding prologue and epilogue instructions.
 | 
			
		||||
     * Increment start_offset to skip epilogue instructions, then compute
 | 
			
		||||
     * copy_size the indicate the size of the remaining instructions (in
 | 
			
		||||
     * bytes).
 | 
			
		||||
     */
 | 
			
		||||
    p_start = text + offset;
 | 
			
		||||
    p_end = p_start + size;
 | 
			
		||||
    start_offset = offset;
 | 
			
		||||
    switch(ELF_ARCH) {
 | 
			
		||||
    case EM_386:
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
    case EM_SPARC:
 | 
			
		||||
    case EM_SPARC32PLUS:
 | 
			
		||||
	{
 | 
			
		||||
	    uint32_t start_insn, end_insn1, end_insn2, skip_insn;
 | 
			
		||||
            uint8_t *p;
 | 
			
		||||
            p = (void *)(p_end - 8);
 | 
			
		||||
            if (p <= p_start)
 | 
			
		||||
                error("empty code for %s", name);
 | 
			
		||||
	    if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98)
 | 
			
		||||
                error("save %%sp,-104,%%sp expected at the start of %s "
 | 
			
		||||
		      "found [%08x]",
 | 
			
		||||
		      name, get32((uint32_t *)(p_start + 0x0)));
 | 
			
		||||
            if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 ||
 | 
			
		||||
		get32((uint32_t *)(p + 0x4)) != 0x81e80000)
 | 
			
		||||
                error("ret; restore; expected at the end of %s found [%08x:%08x]",
 | 
			
		||||
		      name,
 | 
			
		||||
		      get32((uint32_t *)(p + 0x0)),
 | 
			
		||||
		      get32((uint32_t *)(p + 0x4)));
 | 
			
		||||
	    start_insn = get32((uint32_t *)(p_start + 0x0));
 | 
			
		||||
	    end_insn1 = get32((uint32_t *)(p + 0x0));
 | 
			
		||||
	    end_insn2 = get32((uint32_t *)(p + 0x4));
 | 
			
		||||
	    if ((start_insn & ~0x1fff) == 0x9de3a000) {
 | 
			
		||||
		p_start += 0x4;
 | 
			
		||||
		start_offset += 0x4;
 | 
			
		||||
		if ((int)(start_insn | ~0x1fff) < -128)
 | 
			
		||||
		    error("Found bogus save at the start of %s", name);
 | 
			
		||||
		if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
 | 
			
		||||
		    error("ret; restore; not found at end of %s", name);
 | 
			
		||||
	    } else {
 | 
			
		||||
		error("No save at the beginning of %s", name);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    /* Skip a preceeding nop, if present.  */
 | 
			
		||||
	    if (p > p_start) {
 | 
			
		||||
		skip_insn = get32((uint32_t *)(p - 0x4));
 | 
			
		||||
		if (skip_insn == 0x01000000)
 | 
			
		||||
		    p -= 4;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
            copy_size = p - p_start;
 | 
			
		||||
	}
 | 
			
		||||
	break;
 | 
			
		||||
    case EM_SPARCV9:
 | 
			
		||||
	{
 | 
			
		||||
	    uint32_t start_insn, end_insn1, end_insn2, skip_insn;
 | 
			
		||||
            uint8_t *p;
 | 
			
		||||
            p = (void *)(p_end - 8);
 | 
			
		||||
            if (p <= p_start)
 | 
			
		||||
                error("empty code for %s", name);
 | 
			
		||||
	    if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40)
 | 
			
		||||
                error("save %%sp,-192,%%sp expected at the start of %s "
 | 
			
		||||
		      "found [%08x]",
 | 
			
		||||
		      name, get32((uint32_t *)(p_start + 0x0)));
 | 
			
		||||
            if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 ||
 | 
			
		||||
		get32((uint32_t *)(p + 0x4)) != 0x01000000)
 | 
			
		||||
                error("rett %%i7+8; nop; expected at the end of %s "
 | 
			
		||||
		      "found [%08x:%08x]",
 | 
			
		||||
		      name,
 | 
			
		||||
		      get32((uint32_t *)(p + 0x0)),
 | 
			
		||||
		      get32((uint32_t *)(p + 0x4)));
 | 
			
		||||
	    start_insn = get32((uint32_t *)(p_start + 0x0));
 | 
			
		||||
	    end_insn1 = get32((uint32_t *)(p + 0x0));
 | 
			
		||||
	    end_insn2 = get32((uint32_t *)(p + 0x4));
 | 
			
		||||
	    if ((start_insn & ~0x1fff) == 0x9de3a000) {
 | 
			
		||||
		p_start += 0x4;
 | 
			
		||||
		start_offset += 0x4;
 | 
			
		||||
		if ((int)(start_insn | ~0x1fff) < -256)
 | 
			
		||||
		    error("Found bogus save at the start of %s", name);
 | 
			
		||||
		if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
 | 
			
		||||
		    error("ret; restore; not found at end of %s", name);
 | 
			
		||||
	    } else {
 | 
			
		||||
		error("No save at the beginning of %s", name);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    /* Skip a preceeding nop, if present.  */
 | 
			
		||||
	    if (p > p_start) {
 | 
			
		||||
		skip_insn = get32((uint32_t *)(p - 0x4));
 | 
			
		||||
		if (skip_insn == 0x01000000)
 | 
			
		||||
		    p -= 4;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
            copy_size = p - p_start;
 | 
			
		||||
	}
 | 
			
		||||
	break;
 | 
			
		||||
| 
						 | 
				
			
			@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
        args_present[i] = 0;
 | 
			
		||||
 | 
			
		||||
    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
        if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
        if (rel->r_offset >= start_offset &&
 | 
			
		||||
	    rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
            sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
 | 
			
		||||
            if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                n = strtoul(p, NULL, 10);
 | 
			
		||||
| 
						 | 
				
			
			@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
        fprintf(outfile, "    extern void %s();\n", name);
 | 
			
		||||
 | 
			
		||||
        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
            if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
            if (rel->r_offset >= start_offset &&
 | 
			
		||||
		rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
 | 
			
		||||
                if (*sym_name && !strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
#if defined(HOST_SPARC)
 | 
			
		||||
| 
						 | 
				
			
			@ -443,7 +473,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fprintf(outfile, "    memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size);
 | 
			
		||||
        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size);
 | 
			
		||||
        for(i = 0; i < nb_args; i++) {
 | 
			
		||||
            fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +485,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                int type;
 | 
			
		||||
                int addend;
 | 
			
		||||
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
                if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
                if (rel->r_offset >= start_offset &&
 | 
			
		||||
		    rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
 | 
			
		||||
                    if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                        snprintf(name, sizeof(name), "param%s", p);
 | 
			
		||||
| 
						 | 
				
			
			@ -467,11 +498,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                    switch(type) {
 | 
			
		||||
                    case R_386_32:
 | 
			
		||||
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
 | 
			
		||||
                                rel->r_offset - offset, name, addend);
 | 
			
		||||
                                rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case R_386_PC32:
 | 
			
		||||
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", 
 | 
			
		||||
                                rel->r_offset - offset, name, rel->r_offset - offset, addend);
 | 
			
		||||
                                rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        error("unsupported i386 relocation (%d)", type);
 | 
			
		||||
| 
						 | 
				
			
			@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                int type;
 | 
			
		||||
                int addend;
 | 
			
		||||
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
                    if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
                    if (rel->r_offset >= start_offset &&
 | 
			
		||||
			rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
 | 
			
		||||
                        if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                            snprintf(name, sizeof(name), "param%s", p);
 | 
			
		||||
| 
						 | 
				
			
			@ -497,24 +529,24 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                        switch(type) {
 | 
			
		||||
                        case R_PPC_ADDR32:
 | 
			
		||||
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case R_PPC_ADDR16_LO:
 | 
			
		||||
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case R_PPC_ADDR16_HI:
 | 
			
		||||
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case R_PPC_ADDR16_HA:
 | 
			
		||||
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case R_PPC_REL24:
 | 
			
		||||
                            /* warning: must be at 32 MB distancy */
 | 
			
		||||
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", 
 | 
			
		||||
                                    rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            error("unsupported powerpc relocation (%d)", type);
 | 
			
		||||
| 
						 | 
				
			
			@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                int type;
 | 
			
		||||
                int addend;
 | 
			
		||||
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
                    if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
                    if (rel->r_offset >= start_offset &&
 | 
			
		||||
			rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                        sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
 | 
			
		||||
                        if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                            snprintf(name, sizeof(name), "param%s", p);
 | 
			
		||||
| 
						 | 
				
			
			@ -540,15 +573,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                        switch(type) {
 | 
			
		||||
                        case R_390_32:
 | 
			
		||||
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case R_390_16:
 | 
			
		||||
                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case R_390_8:
 | 
			
		||||
                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            error("unsupported s390 relocation (%d)", type);
 | 
			
		||||
| 
						 | 
				
			
			@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
#elif defined(HOST_ALPHA)
 | 
			
		||||
            {
 | 
			
		||||
                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
 | 
			
		||||
		    if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
		    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
			int type;
 | 
			
		||||
 | 
			
		||||
			type = ELF64_R_TYPE(rel->r_info);
 | 
			
		||||
| 
						 | 
				
			
			@ -569,9 +602,9 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
			    /* The gp is just 32 bit, and never changes, so it's easiest to emit it
 | 
			
		||||
			       as an immediate instead of constructing it from the pv or ra.  */
 | 
			
		||||
			    fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, gp);\n",
 | 
			
		||||
				    rel->r_offset - offset);
 | 
			
		||||
				    rel->r_offset - start_offset);
 | 
			
		||||
			    fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, gp);\n",
 | 
			
		||||
				    rel->r_offset - offset + rel->r_addend);
 | 
			
		||||
				    rel->r_offset - start_offset + rel->r_addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_ALPHA_LITUSE:
 | 
			
		||||
			    /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
 | 
			
		||||
| 
						 | 
				
			
			@ -591,18 +624,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
			       special treatment.  */
 | 
			
		||||
			    if (strstart(sym_name, "__op_param", &p))
 | 
			
		||||
				fprintf(outfile, "    immediate_ldah(gen_code_ptr + %ld, param%s);\n",
 | 
			
		||||
					rel->r_offset - offset, p);
 | 
			
		||||
					rel->r_offset - start_offset, p);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_ALPHA_GPRELLOW:
 | 
			
		||||
			    if (strstart(sym_name, "__op_param", &p))
 | 
			
		||||
				fprintf(outfile, "    immediate_lda(gen_code_ptr + %ld, param%s);\n",
 | 
			
		||||
					rel->r_offset - offset, p);
 | 
			
		||||
					rel->r_offset - start_offset, p);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_ALPHA_BRSGP:
 | 
			
		||||
			    /* PC-relative jump. Tweak offset to skip the two instructions that try to
 | 
			
		||||
			       set up the gp from the pv.  */
 | 
			
		||||
			    fprintf(outfile, "    fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n",
 | 
			
		||||
				    rel->r_offset - offset, sym_name, rel->r_offset - offset);
 | 
			
		||||
				    rel->r_offset - start_offset, sym_name, rel->r_offset - start_offset);
 | 
			
		||||
			    break;
 | 
			
		||||
			default:
 | 
			
		||||
			    error("unsupported Alpha relocation (%d)", type);
 | 
			
		||||
| 
						 | 
				
			
			@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                int type;
 | 
			
		||||
                int addend;
 | 
			
		||||
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
                    if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
                    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
 | 
			
		||||
                        if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                            snprintf(name, sizeof(name), "param%s", p);
 | 
			
		||||
| 
						 | 
				
			
			@ -642,7 +675,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                int type;
 | 
			
		||||
                int addend;
 | 
			
		||||
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
                    if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
                    if (rel->r_offset >= start_offset &&
 | 
			
		||||
			rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                        sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
 | 
			
		||||
                        if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                            snprintf(name, sizeof(name), "param%s", p);
 | 
			
		||||
| 
						 | 
				
			
			@ -660,16 +694,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                        switch(type) {
 | 
			
		||||
                        case R_SPARC_32:
 | 
			
		||||
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", 
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_SPARC_HI22:
 | 
			
		||||
                            fprintf(outfile,
 | 
			
		||||
				    "    *(uint32_t *)(gen_code_ptr + %d) = "
 | 
			
		||||
				    "((*(uint32_t *)(gen_code_ptr + %d)) "
 | 
			
		||||
				    " & ~0x3fffff) "
 | 
			
		||||
				    " | ((%s + %d) & 0x3fffff);\n",
 | 
			
		||||
                                    rel->r_offset - offset,
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
				    " | (((%s + %d) >> 10) & 0x3fffff);\n",
 | 
			
		||||
                                    rel->r_offset - start_offset,
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    name, addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_SPARC_LO10:
 | 
			
		||||
| 
						 | 
				
			
			@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
				    "((*(uint32_t *)(gen_code_ptr + %d)) "
 | 
			
		||||
				    " & ~0x3ff) "
 | 
			
		||||
				    " | ((%s + %d) & 0x3ff);\n",
 | 
			
		||||
                                    rel->r_offset - offset,
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
                                    rel->r_offset - start_offset,
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    name, addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_SPARC_WDISP30:
 | 
			
		||||
| 
						 | 
				
			
			@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
				    "    *(uint32_t *)(gen_code_ptr + %d) = "
 | 
			
		||||
				    "((*(uint32_t *)(gen_code_ptr + %d)) "
 | 
			
		||||
				    " & ~0x3fffffff) "
 | 
			
		||||
				    " | ((((%s + %d) - (long)gen_code_ptr)>>2) "
 | 
			
		||||
				    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
 | 
			
		||||
				    "    & 0x3fffffff);\n",
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
				    name, addend);
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    name, addend,
 | 
			
		||||
				    rel->r_offset - start_offset);
 | 
			
		||||
			    break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            error("unsupported sparc relocation (%d)", type);
 | 
			
		||||
| 
						 | 
				
			
			@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                int type;
 | 
			
		||||
                int addend;
 | 
			
		||||
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
 | 
			
		||||
                    if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
 | 
			
		||||
                    if (rel->r_offset >= start_offset &&
 | 
			
		||||
			rel->r_offset < start_offset + copy_size) {
 | 
			
		||||
                        sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
 | 
			
		||||
                        if (strstart(sym_name, "__op_param", &p)) {
 | 
			
		||||
                            snprintf(name, sizeof(name), "param%s", p);
 | 
			
		||||
| 
						 | 
				
			
			@ -717,16 +753,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
                        switch(type) {
 | 
			
		||||
                        case R_SPARC_32:
 | 
			
		||||
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
 | 
			
		||||
                                    rel->r_offset - offset, name, addend);
 | 
			
		||||
                                    rel->r_offset - start_offset, name, addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_SPARC_HI22:
 | 
			
		||||
                            fprintf(outfile,
 | 
			
		||||
				    "    *(uint32_t *)(gen_code_ptr + %d) = "
 | 
			
		||||
				    "((*(uint32_t *)(gen_code_ptr + %d)) "
 | 
			
		||||
				    " & ~0x3fffff) "
 | 
			
		||||
				    " | ((%s + %d) & 0x3fffff);\n",
 | 
			
		||||
                                    rel->r_offset - offset,
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
				    " | (((%s + %d) >> 10) & 0x3fffff);\n",
 | 
			
		||||
                                    rel->r_offset - start_offset,
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    name, addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_SPARC_LO10:
 | 
			
		||||
| 
						 | 
				
			
			@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
				    "((*(uint32_t *)(gen_code_ptr + %d)) "
 | 
			
		||||
				    " & ~0x3ff) "
 | 
			
		||||
				    " | ((%s + %d) & 0x3ff);\n",
 | 
			
		||||
                                    rel->r_offset - offset,
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
                                    rel->r_offset - start_offset,
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    name, addend);
 | 
			
		||||
			    break;
 | 
			
		||||
			case R_SPARC_WDISP30:
 | 
			
		||||
| 
						 | 
				
			
			@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
 | 
			
		|||
				    "    *(uint32_t *)(gen_code_ptr + %d) = "
 | 
			
		||||
				    "((*(uint32_t *)(gen_code_ptr + %d)) "
 | 
			
		||||
				    " & ~0x3fffffff) "
 | 
			
		||||
				    " | ((((%s + %d) - (long)gen_code_ptr)>>2) "
 | 
			
		||||
				    " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
 | 
			
		||||
				    "    & 0x3fffffff);\n",
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
				    rel->r_offset - offset,
 | 
			
		||||
				    name, addend);
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    rel->r_offset - start_offset,
 | 
			
		||||
				    name, addend,
 | 
			
		||||
				    rel->r_offset - start_offset);
 | 
			
		||||
			    break;
 | 
			
		||||
                        default:
 | 
			
		||||
			    error("unsupported sparc64 relocation (%d)", type);
 | 
			
		||||
| 
						 | 
				
			
			@ -933,7 +970,22 @@ fprintf(outfile,
 | 
			
		|||
"    const uint32_t *opparam_ptr;\n"
 | 
			
		||||
"    gen_code_ptr = gen_code_buf;\n"
 | 
			
		||||
"    opc_ptr = opc_buf;\n"
 | 
			
		||||
"    opparam_ptr = opparam_buf;\n"
 | 
			
		||||
"    opparam_ptr = opparam_buf;\n");
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
fprintf(outfile,
 | 
			
		||||
"    for(;;) {\n"
 | 
			
		||||
"        switch(*opc_ptr++) {\n"
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			@ -961,7 +1013,7 @@ fprintf(outfile,
 | 
			
		|||
" the_end:\n"
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/* generate a return */ 
 | 
			
		||||
/* generate epilogue */ 
 | 
			
		||||
    switch(ELF_ARCH) {
 | 
			
		||||
    case EM_386:
 | 
			
		||||
        fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -980,11 +1032,13 @@ fprintf(outfile,
 | 
			
		|||
        break;
 | 
			
		||||
    case EM_SPARC:
 | 
			
		||||
    case EM_SPARC32PLUS:
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc07a080; /* add %%fp, 256, %%fp */\n");
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c62008; /* jmpl %%i0 + 8, %%g0 */\n");
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c03a080; /* add %%sp, 256, %%sp */\n");
 | 
			
		||||
        break;
 | 
			
		||||
    case EM_SPARCV9:
 | 
			
		||||
	/* Fill the delay slot. */
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t *)gen_code_ptr - 1); /* delay slot */\n");
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl */\n");
 | 
			
		||||
	fprintf(outfile, "gen_code_ptr++;\n");
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret */\n");
 | 
			
		||||
	fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* restore */\n");
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
	error("unknown ELF architecture");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								exec-i386.c
								
								
								
								
							
							
						
						
									
										15
									
								
								exec-i386.c
								
								
								
								
							| 
						 | 
				
			
			@ -153,6 +153,13 @@ void raise_exception_err(int exception_index, int error_code)
 | 
			
		|||
{
 | 
			
		||||
    /* NOTE: the register at this point must be saved by hand because
 | 
			
		||||
       longjmp restore them */
 | 
			
		||||
#ifdef __sparc__
 | 
			
		||||
	/* We have to stay in the same register window as our caller,
 | 
			
		||||
	 * thus this trick.
 | 
			
		||||
	 */
 | 
			
		||||
	__asm__ __volatile__("restore\n\t"
 | 
			
		||||
			     "mov\t%o0, %i0");
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef reg_EAX
 | 
			
		||||
    env->regs[R_EAX] = EAX;
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1)
 | 
			
		|||
            /* execute the generated code */
 | 
			
		||||
            tc_ptr = tb->tc_ptr;
 | 
			
		||||
            gen_func = (void *)tc_ptr;
 | 
			
		||||
#ifdef __sparc__
 | 
			
		||||
	    __asm__ __volatile__("call	%0\n\t"
 | 
			
		||||
				 " mov	%%o7,%%i0"
 | 
			
		||||
				 : /* no outputs */
 | 
			
		||||
				 : "r" (gen_func)
 | 
			
		||||
				 : "i0", "i1", "i2", "i3", "i4", "i5");
 | 
			
		||||
#else
 | 
			
		||||
            gen_func();
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    ret = env->exception_index;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								exec-i386.h
								
								
								
								
							
							
						
						
									
										24
									
								
								exec-i386.h
								
								
								
								
							| 
						 | 
				
			
			@ -89,11 +89,27 @@ register unsigned int A0 asm("s2");
 | 
			
		|||
register struct CPUX86State *env asm("s3");
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __sparc__
 | 
			
		||||
register unsigned int T0 asm("l0");
 | 
			
		||||
register unsigned int T1 asm("l1");
 | 
			
		||||
register unsigned int A0 asm("l2");
 | 
			
		||||
register struct CPUX86State *env asm("l3");
 | 
			
		||||
register unsigned int EAX asm("l0");
 | 
			
		||||
register unsigned int ECX asm("l1");
 | 
			
		||||
register unsigned int EDX asm("l2");
 | 
			
		||||
register unsigned int EBX asm("l3");
 | 
			
		||||
register unsigned int ESP asm("l4");
 | 
			
		||||
register unsigned int EBP asm("l5");
 | 
			
		||||
register unsigned int ESI asm("l6");
 | 
			
		||||
register unsigned int EDI asm("l7");
 | 
			
		||||
register unsigned int T0 asm("g1");
 | 
			
		||||
register unsigned int T1 asm("g2");
 | 
			
		||||
register unsigned int A0 asm("g3");
 | 
			
		||||
register struct CPUX86State *env asm("g6");
 | 
			
		||||
#define USE_FP_CONVERT
 | 
			
		||||
#define reg_EAX
 | 
			
		||||
#define reg_ECX
 | 
			
		||||
#define reg_EDX
 | 
			
		||||
#define reg_EBX
 | 
			
		||||
#define reg_ESP
 | 
			
		||||
#define reg_EBP
 | 
			
		||||
#define reg_ESI
 | 
			
		||||
#define reg_EDI
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __s390__
 | 
			
		||||
register unsigned int T0 asm("r7");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue