Example #1
0
/* Load sections from an ELF file */
void X86ContextLoadELFSections(X86Context *self, struct elf_file_t *elf_file)
{
	struct mem_t *mem = self->mem;
	struct x86_loader_t *loader = self->loader;

	struct elf_section_t *section;
	int i;

	enum mem_access_t perm;
	char flags_str[200];

	x86_loader_debug("\nLoading ELF sections\n");
	loader->bottom = 0xffffffff;
	for (i = 0; i < list_count(elf_file->section_list); i++)
	{
		section = list_get(elf_file->section_list, i);

		perm = mem_access_init | mem_access_read;
		str_map_flags(&elf_section_flags_map, section->header->sh_flags,
				flags_str, sizeof(flags_str));
		x86_loader_debug("  section %d: name='%s', offset=0x%x, "
				"addr=0x%x, size=%u, flags=%s\n",
				i, section->name, section->header->sh_offset,
				section->header->sh_addr, section->header->sh_size, flags_str);

		/* Process section */
		if (section->header->sh_flags & SHF_ALLOC)
		{
			/* Permissions */
			if (section->header->sh_flags & SHF_WRITE)
				perm |= mem_access_write;
			if (section->header->sh_flags & SHF_EXECINSTR)
				perm |= mem_access_exec;

			/* Load section */
			mem_map(mem, section->header->sh_addr, section->header->sh_size, perm);
			mem->heap_break = MAX(mem->heap_break, section->header->sh_addr
				+ section->header->sh_size);
			loader->bottom = MIN(loader->bottom, section->header->sh_addr);

			/* If section type is SHT_NOBITS (sh_type=8), initialize to 0.
			 * Otherwise, copy section contents from ELF file. */
			if (section->header->sh_type == 8)
			{
				void *ptr;

				ptr = xcalloc(1, section->header->sh_size);
				mem_access(mem, section->header->sh_addr,
						section->header->sh_size,
						ptr, mem_access_init);
				free(ptr);
			} else {
				mem_access(mem, section->header->sh_addr,
						section->header->sh_size,
						section->buffer.ptr, mem_access_init);
			}
		}
	}
}
Example #2
0
File: memory.c Project: palmerc/lab
/* dump a block of memory, returns any faults encountered */
enum md_fault_type
mem_dump(struct mem_t *mem,		/* memory space to display */
	 md_addr_t addr,		/* target address to dump */
	 int len,			/* number bytes to dump */
	 FILE *stream)			/* output stream */
{
  int data;
  enum md_fault_type fault;

  if (!stream)
    stream = stderr;

  addr &= ~sizeof(word_t);
  len = (len + (sizeof(word_t) - 1)) & ~sizeof(word_t);
  while (len-- > 0)
    {
      fault = mem_access(mem, Read, addr, &data, sizeof(word_t));
      if (fault != md_fault_none)
	return fault;

      myfprintf(stream, "0x%08p: %08x\n", addr, data);
      addr += sizeof(word_t);
    }

  /* no faults... */
  return md_fault_none;
}
Example #3
0
/* system call memory access function */
enum md_fault_type
cheetah_access_fn(struct mem_t *mem,	/* memory space to access */
		  enum mem_cmd cmd,	/* memory access cmd, Read or Write */
		  md_addr_t addr,	/* data address to access */
		  void *p,		/* data input/output buffer */
		  int nbytes)		/* number of bytes to access */
{
  if (refs & REFS_DATA)
    cheetah_access(addr);
  return mem_access(mem, cmd, addr, p, nbytes);
}
Example #4
0
static
member_bin(stream, node, need_lval) {
extern stderr;
    expr_code( stream, node[3], node[0] == '.' );

    /* This is a bit of a fudge.  In 'struct foo { int x[2] };', x is an
     * address even though it's not an lvalue, per se. */
    if ( node[2][0] == '[]' ) need_lval = 1;

    /* We've stored the member offset as an integer in node[5] */
    mem_access( stream, node[5], need_lval );
}
Example #5
0
/* system call memory access function */
enum md_fault_type
dcache_access_fn(struct mem_t *mem,	/* memory space to access */
		 enum mem_cmd cmd,	/* memory access cmd, Read or Write */
		 md_addr_t addr,	/* data address to access */
		 void *p,		/* data input/output buffer */
		 int nbytes)		/* number of bytes to access */
{
  if (dtlb)
    cache_access(dtlb, cmd, addr, NULL, nbytes, 0, NULL, NULL, 0);
  if (cache_dl1)
    cache_access(cache_dl1, cmd, addr, NULL, nbytes, 0, NULL, NULL, 0);
  return mem_access(mem, cmd, addr, p, nbytes);
}
Example #6
0
void X86ContextExecute(X86Context *self)
{
	X86Emu *emu = self->emu;

	struct x86_regs_t *regs = self->regs;
	struct mem_t *mem = self->mem;

	unsigned char buffer[20];
	unsigned char *buffer_ptr;

	int spec_mode;

	/* Memory permissions should not be checked if the context is executing in
	 * speculative mode. This will prevent guest segmentation faults to occur. */
	spec_mode = X86ContextGetState(self, X86ContextSpecMode);
	mem->safe = spec_mode ? 0 : mem_safe_mode;

	/* Read instruction from memory. Memory should be accessed here in unsafe mode
	 * (i.e., allowing segmentation faults) if executing speculatively. */
	buffer_ptr = mem_get_buffer(mem, regs->eip, 20, mem_access_exec);
	if (!buffer_ptr)
	{
		/* Disable safe mode. If a part of the 20 read bytes does not belong to the
		 * actual instruction, and they lie on a page with no permissions, this would
		 * generate an undesired protection fault. */
		mem->safe = 0;
		buffer_ptr = buffer;
		mem_access(mem, regs->eip, 20, buffer_ptr, mem_access_exec);
	}
	mem->safe = mem_safe_mode;

	/* Disassemble */
	X86InstDecode(&self->inst, regs->eip, buffer_ptr);
	if (self->inst.opcode == X86InstOpcodeInvalid && !spec_mode)
		fatal("0x%x: not supported x86 instruction (%02x %02x %02x %02x...)",
			regs->eip, buffer_ptr[0], buffer_ptr[1], buffer_ptr[2], buffer_ptr[3]);


	/* Stop if instruction matches last instruction bytes */
	if (x86_emu_last_inst_size &&
		x86_emu_last_inst_size == self->inst.size &&
		!memcmp(x86_emu_last_inst_bytes, buffer_ptr, x86_emu_last_inst_size))
		esim_finish = esim_finish_x86_last_inst;

	/* Execute instruction */
	X86ContextExecuteInst(self);
	
	/* Statistics */
	asEmu(emu)->instructions++;
}
Example #7
0
/* load program text and initialized data into simulated virtual memory
   space and initialize program segment range variables */
void
ld_load_prog(char *fname,		/* program to load */
	     int argc, char **argv,	/* simulated program cmd line args */
	     char **envp,		/* simulated program environment */
	     struct regs_t *regs,	/* registers to initialize for load */
	     struct mem_t *mem,		/* memory space to load prog into */
	     int zero_bss_segs)		/* zero uninit data segment? */
{
  int i;
  word_t temp;
  md_addr_t sp, data_break = 0, null_ptr = 0, argv_addr, envp_addr;
  FILE *fobj;
  struct elf_filehdr fhdr;
  struct elf_scnhdr shdr;
  byte_t *strtab, *buffer;

  if (eio_valid(fname))
    {
      if (argc != 1)
	{
	  fprintf(stderr, "error: EIO file has arguments\n");
	  exit(1);
	}

      fprintf(stderr, "sim: loading EIO file: %s\n", fname);

      sim_eio_fname = mystrdup(fname);

      /* open the EIO file stream */
      sim_eio_fd = eio_open(fname);

      /* load initial state checkpoint */
      if (eio_read_chkpt(regs, mem, sim_eio_fd) != -1)
	fatal("bad initial checkpoint in EIO file");

      /* load checkpoint? */
      if (sim_chkpt_fname != NULL)
	{
	  counter_t restore_icnt;

	  FILE *chkpt_fd;

	  fprintf(stderr, "sim: loading checkpoint file: %s\n",
		  sim_chkpt_fname);

	  if (!eio_valid(sim_chkpt_fname))
	    fatal("file `%s' does not appear to be a checkpoint file",
		  sim_chkpt_fname);

	  /* open the checkpoint file */
	  chkpt_fd = eio_open(sim_chkpt_fname);

	  /* load the state image */
	  restore_icnt = eio_read_chkpt(regs, mem, chkpt_fd);

	  /* fast forward the baseline EIO trace to checkpoint location */
	  myfprintf(stderr, "sim: fast forwarding to instruction %n\n",
		    restore_icnt);
	  eio_fast_forward(sim_eio_fd, restore_icnt);
	}

      /* computed state... */
      ld_environ_base = regs->regs_R[MD_REG_SP];
      ld_prog_entry = regs->regs_PC;

      /* fini... */
      return;
    }
#ifdef MD_CROSS_ENDIAN
  else
    {
      warn("endian of `%s' does not match host", fname);
      warn("running with experimental cross-endian execution support");
      warn("****************************************");
      warn("**>> please check results carefully <<**");
      warn("****************************************");
#if 0
      fatal("SimpleScalar/ARM only supports binary execution on\n"
	    "       little-endian hosts, use EIO files on big-endian hosts");
#endif
    }
#endif /* MD_CROSS_ENDIAN */

  if (sim_chkpt_fname != NULL)
    fatal("checkpoints only supported while EIO tracing");

  /* record profile file name */
  ld_prog_fname = argv[0];

  /* load the program into memory, try both endians */
#if defined(__CYGWIN32__) || defined(_MSC_VER)
  fobj = fopen(argv[0], "rb");
#else
  fobj = fopen(argv[0], "r");
#endif
  if (!fobj)
    fatal("cannot open executable `%s'", argv[0]);

  if (fread(&fhdr, sizeof(struct elf_filehdr), 1, fobj) < 1)
    fatal("cannot read header from executable `%s'", argv[0]);

  /* check if it is a valid ELF file */
  if (!(fhdr.e_ident[EI_MAG0] == 0x7f &&
	fhdr.e_ident[EI_MAG1] == 'E' &&
	fhdr.e_ident[EI_MAG2] == 'L' &&
	fhdr.e_ident[EI_MAG3] == 'F'))
    fatal("bad magic number in executable `%s' (not an executable)", argv[0]);

  /* check if the file is executable */
  if (fhdr.e_type != ET_EXEC)
    fatal("object file `%s' is not executable", argv[0]);

  /* check if the file is for ARM architecture */
  if (fhdr.e_machine != EM_ARM)
    fatal("executable file `%s' is not for the ARM architecture", argv[0]);

  ld_prog_entry = fhdr.e_entry;

  debug("number of sections in executable = %d\n", fhdr.e_shnum);
  debug("offset to section header table = %d", fhdr.e_shoff);

  /* seek to the beginning of the first section header, the file header comes
     first, followed by the optional header (this is the aouthdr), the size
     of the aouthdr is given in Fdhr.f_opthdr */
  fseek(fobj, fhdr.e_shoff + (fhdr.e_shstrndx * fhdr.e_shentsize), SEEK_SET);
  if (fread(&shdr, sizeof(struct elf_scnhdr), 1, fobj) < 1)
    fatal("error reading string section header from `%s'", argv[0]);

  /* allocate space for string table */
  strtab = (char *)calloc(shdr.sh_size, sizeof(char));
  if (!strtab)
    fatal("out of virtual memory");

  /* read the string table */
  if (fseek(fobj, shdr.sh_offset, SEEK_SET) < 0)
    fatal("cannot seek to string table section");
  if (fread(strtab, shdr.sh_size, 1, fobj) < 0)
    fatal("cannot read string table section");

  debug("size of string table = %d", shdr.sh_size);
  debug("type of section = %d", shdr.sh_type);
  debug("offset of string table in file = %d", shdr.sh_offset);

  debug("processing %d sections in `%s'...", fhdr.e_shnum, argv[0]);

  /* loop through the section headers */
  for (i=0; i < fhdr.e_shnum; i++)
    {
      buffer = NULL;

      if (fseek(fobj, fhdr.e_shoff + (i * fhdr.e_shentsize), SEEK_SET) < 0)
	fatal("could not reset location in executable");
      if (fread(&shdr, sizeof(struct elf_scnhdr), 1, fobj) < 1)
	fatal("could not read section %d from executable", i);

      /* make sure the file is static */
      if (shdr.sh_type == SHT_DYNAMIC || shdr.sh_type == SHT_DYNSYM)
	fatal("file is dynamically linked, compile with `-static'");

      debug("processing section `%s'...", &strtab[shdr.sh_name]);
      debug("  section flags = 0x%08x", shdr.sh_flags);	
      debug("  section type = %d", shdr.sh_type);
      debug("  section address = 0x%08x", shdr.sh_addr);
      debug("  section offset = %d", shdr.sh_offset);
      debug("  section size = %d", shdr.sh_size);
      debug("  section link = %d", shdr.sh_link);
      debug("  section extra info = %d", shdr.sh_info);
      debug("  section entry size = %d", shdr.sh_entsize);

      if (shdr.sh_addr != 0
	  && shdr.sh_size != 0
	  && (shdr.sh_type == SHT_PROGBITS || shdr.sh_type == SHT_NOBITS))
	{
	  /* if the ELF format designates an address for the section then
	     load it into memory */
	  debug("  processing section `%s'...", &strtab[shdr.sh_name]);

	  if ((shdr.sh_flags & SHF_ALLOC) != 0 && shdr.sh_type != SHT_NOBITS)
	    {
	      debug("  loading section `%s'...", &strtab[shdr.sh_name]);
	      /* go to the offset in file where section is located */
	      if (fseek(fobj, shdr.sh_offset, SEEK_SET) < 0)
		fatal("cannot file pointer");

	      /* allocate memory for the section contents */
	      buffer = (char *)calloc(shdr.sh_size, sizeof(byte_t));
	      if (!buffer)
		fatal("out of virtual memory");

	      /* read section into buffer */	
	      if (fread(buffer, shdr.sh_size, 1, fobj) < 1)
		fatal("could not read all the contents of section");

	      /* copy the section contents into simulator target memory */
	      mem_bcopy(mem_access, mem, Write, shdr.sh_addr,
			buffer, shdr.sh_size);
	    }

	  /* update program space limits */
	  if ((shdr.sh_flags & SHF_EXECINSTR) != 0)
	    {
	      debug("updating text size...");
	      if (shdr.sh_addr < ld_text_base)
		ld_text_base = shdr.sh_addr;
	      if ((shdr.sh_addr + shdr.sh_size) > ld_text_bound)
		ld_text_bound = shdr.sh_addr + shdr.sh_size;
	    }
	  else
	    {
	      debug("updating data size...");
	      if (shdr.sh_addr < ld_data_base)
		ld_data_base = shdr.sh_addr;
	      if ((shdr.sh_addr + shdr.sh_size) > ld_data_bound)
		ld_data_bound = shdr.sh_addr + shdr.sh_size;
	    }
	  ld_text_size = ld_text_bound - ld_text_base;
	  ld_data_size = ld_data_bound - ld_data_base;

	  /* release buffer storage */
	  if (buffer != NULL)
	    free(buffer);	
	}
    }

  /* release string table storage */
  free(strtab);

  /* perform sanity checks on segment ranges */
  if (!ld_text_base || !ld_text_size)
    fatal("executable is missing a `.text' section");
  if (!ld_data_base || !ld_data_size)
    fatal("executable is missing a `.data' section");
  if (!ld_prog_entry)
    fatal("program entry point not specified");

  /* determine byte/words swapping required to execute on this host */
  sim_swap_bytes = (endian_host_byte_order() != endian_target_byte_order());
  if (sim_swap_bytes)
    {
#if 0 /* FIXME: disabled until further notice... */
      /* cross-endian is never reliable, why this is so is beyond the scope
	 of this comment, e-mail me for details... */
      fprintf(stderr, "sim: *WARNING*: swapping bytes to match host...\n");
      fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n");
      /* #else */
      fatal("binary endian does not match host endian");
#endif
    }
  sim_swap_words = (endian_host_word_order() != endian_target_word_order());
  if (sim_swap_words)
    {
#if 0 /* FIXME: disabled until further notice... */
      /* cross-endian is never reliable, why this is so is beyond the scope
	 of this comment, e-mail me for details... */
      fprintf(stderr, "sim: *WARNING*: swapping words to match host...\n");
      fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n");
      /* #else */
      fatal("binary endian does not match host endian");
#endif
    }

  /* set up a local stack pointer, this is where the argv and envp
     data is written into program memory */
  /* ld_stack_base = ld_text_base - (409600+4096); */

  ld_stack_base = 0xc0000000;
#if 0
  sp = ROUND_DOWN(ld_stack_base - MD_MAX_ENVIRON, sizeof(MD_DOUBLE_TYPE));
#endif
  sp = ld_stack_base - MD_MAX_ENVIRON;
  ld_stack_size = ld_stack_base - sp;

  /* initial stack pointer value */
  ld_environ_base = sp;

  /* write [argc] to stack */
  temp = argc;
  mem_access(mem, Write, sp, &temp, sizeof(word_t));
  regs->regs_R[MD_REG_R1] = temp;
  sp += sizeof(word_t);

  /* skip past argv array and NULL */
  argv_addr = sp;
  regs->regs_R[MD_REG_R2] = argv_addr;
  sp = sp + (argc + 1) * sizeof(md_addr_t);

  /* save space for envp array and NULL */
  envp_addr = sp;
  for (i=0; envp[i]; i++)
    sp += sizeof(md_addr_t);
  sp += sizeof(md_addr_t);

  /* fill in the argv pointer array and data */
  for (i=0; i<argc; i++)
    {
      /* write the argv pointer array entry */
      temp = sp;
      mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t),
		 &temp, sizeof(md_addr_t));
      /* and the data */
      mem_strcpy(mem_access, mem, Write, sp, argv[i]);
      sp += strlen(argv[i])+1;
    }
  /* terminate argv array with a NULL */
  mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t),
	     &null_ptr, sizeof(md_addr_t));

  /* write envp pointer array and data to stack */
  for (i = 0; envp[i]; i++)
    {
      /* write the envp pointer array entry */
      temp = sp;
      mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t),
		 &temp, sizeof(md_addr_t));
      /* and the data */
      mem_strcpy(mem_access, mem, Write, sp, envp[i]);
      sp += strlen(envp[i]) + 1;
    }
  /* terminate the envp array with a NULL */
  mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t),
	     &null_ptr, sizeof(md_addr_t));

  /* did we tromp off the stop of the stack? */
  if (sp > ld_stack_base)
    {
      /* we did, indicate to the user that MD_MAX_ENVIRON must be increased,
	 alternatively, you can use a smaller environment, or fewer
	 command line arguments */
      fatal("environment overflow, increase MD_MAX_ENVIRON in arm.h");
    }

  /* initialize the bottom of heap to top of data segment */
  ld_brk_point = ROUND_UP(ld_data_base + ld_data_size, MD_PAGE_SIZE);

  /* set initial minimum stack pointer value to initial stack value */
  ld_stack_min = regs->regs_R[MD_REG_SP];

  regs->regs_R[MD_REG_SP] = ld_environ_base;
  regs->regs_PC = ld_prog_entry;

  debug("ld_text_base: 0x%08x  ld_text_size: 0x%08x",
	ld_text_base, ld_text_size);
  debug("ld_data_base: 0x%08x  ld_data_size: 0x%08x",
	ld_data_base, ld_data_size);
  debug("ld_stack_base: 0x%08x  ld_stack_size: 0x%08x",
	ld_stack_base, ld_stack_size);
  debug("ld_prog_entry: 0x%08x", ld_prog_entry);
}
Example #8
0
/* load program text and initialized data into simulated virtual memory
   space and initialize program segment range variables */
void
ld_load_prog(char *fname,		/* program to load */
	     int argc, char **argv,	/* simulated program cmd line args */
	     char **envp,		/* simulated program environment */
	     struct regs_t *regs,	/* registers to initialize for load */
	     struct mem_t *mem,		/* memory space to load prog into */
	     int zero_bss_segs)		/* zero uninit data segment? */
{
  int i;
  qword_t temp;
  md_addr_t sp, data_break = 0, null_ptr = 0, argv_addr, envp_addr;

  if (eio_valid(fname))
    {
      if (argc != 1)
	{
	  fprintf(stderr, "error: EIO file has arguments\n");
	  exit(1);
	}

      fprintf(stderr, "sim: loading EIO file: %s\n", fname);

      sim_eio_fname = mystrdup(fname);

      /* open the EIO file stream */
      sim_eio_fd = eio_open(fname);

      /* load initial state checkpoint */
      if (eio_read_chkpt(regs, mem, sim_eio_fd) != -1)
	fatal("bad initial checkpoint in EIO file");

      /* load checkpoint? */
      if (sim_chkpt_fname != NULL)
	{
	  counter_t restore_icnt;

	  FILE *chkpt_fd;

	  fprintf(stderr, "sim: loading checkpoint file: %s\n",
		  sim_chkpt_fname);

	  if (!eio_valid(sim_chkpt_fname))
	    fatal("file `%s' does not appear to be a checkpoint file",
		  sim_chkpt_fname);

	  /* open the checkpoint file */
	  chkpt_fd = eio_open(sim_chkpt_fname);

	  /* load the state image */
	  restore_icnt = eio_read_chkpt(regs, mem, chkpt_fd);

	  /* fast forward the baseline EIO trace to checkpoint location */
	  myfprintf(stderr, "sim: fast forwarding to instruction %n\n",
		    restore_icnt);
	  eio_fast_forward(sim_eio_fd, restore_icnt);
	}

      /* computed state... */
      ld_environ_base = regs->regs_R[MD_REG_SP];
      ld_prog_entry = regs->regs_PC;

      /* fini... */
      return;
    }
#ifdef MD_CROSS_ENDIAN
  else
    {
      warn("endian of `%s' does not match host", fname);
      warn("running with experimental cross-endian execution support");
      warn("****************************************");
      warn("**>> please check results carefully <<**");
      warn("****************************************");
#if 0
      fatal("SimpleScalar/Alpha only supports binary execution on\n"
	    "       little-endian hosts, use EIO files on big-endian hosts");
#endif
    }
#endif /* MD_CROSS_ENDIAN */

  if (sim_chkpt_fname != NULL)
    fatal("checkpoints only supported while EIO tracing");

#ifdef BFD_LOADER

  {
    bfd *abfd;
    asection *sect;

    /* set up a local stack pointer, this is where the argv and envp
       data is written into program memory */
    ld_stack_base = MD_STACK_BASE;
    sp = ROUND_DOWN(MD_STACK_BASE - MD_MAX_ENVIRON, sizeof(MD_DOUBLE_TYPE));
    ld_stack_size = ld_stack_base - sp;
    printf("Thread 0 stack size (3)%d\n",  current->ld_stack_size);

    /* initial stack pointer value */
    ld_environ_base = sp;

    /* load the program into memory, try both endians */
    if (!(abfd = bfd_openr(argv[0], "ss-coff-big")))
      if (!(abfd = bfd_openr(argv[0], "ss-coff-little")))
	fatal("cannot open executable `%s'", argv[0]);

    /* this call is mainly for its side effect of reading in the sections.
       we follow the traditional behavior of `strings' in that we don't
       complain if we don't recognize a file to be an object file.  */
    if (!bfd_check_format(abfd, bfd_object))
      {
	bfd_close(abfd);
	fatal("cannot open executable `%s'", argv[0]);
      }

    /* record profile file name */
    ld_prog_fname = argv[0];

    /* record endian of target */
    ld_target_big_endian = abfd->xvec->byteorder_big_p;

    debug("processing %d sections in `%s'...",
	  bfd_count_sections(abfd), argv[0]);

    /* read all sections in file */
    for (sect=abfd->sections; sect; sect=sect->next)
      {
	char *p;

	debug("processing section `%s', %d bytes @ 0x%08x...",
	      bfd_section_name(abfd, sect), bfd_section_size(abfd, sect),
	      bfd_section_vma(abfd, sect));

	/* read the section data, if allocated and loadable and non-NULL */
	if ((bfd_get_section_flags(abfd, sect) & SEC_ALLOC)
	    && (bfd_get_section_flags(abfd, sect) & SEC_LOAD)
	    && bfd_section_vma(abfd, sect)
	    && bfd_section_size(abfd, sect))
	  {
	    /* allocate a section buffer */
	    p = calloc(bfd_section_size(abfd, sect), sizeof(char));
	    if (!p)
	      fatal("cannot allocate %d bytes for section `%s'",
		    bfd_section_size(abfd, sect),
		    bfd_section_name(abfd, sect));

	    if (!bfd_get_section_contents(abfd, sect, p, (file_ptr)0,
					  bfd_section_size(abfd, sect)))
	      fatal("could not read entire `%s' section from executable",
		    bfd_section_name(abfd, sect));

	    /* copy program section it into simulator target memory */
	    mem_bcopy(mem_fn, Write, bfd_section_vma(abfd, sect),
		      p, bfd_section_size(abfd, sect));

	    /* release the section buffer */
	    free(p);
	  }
	/* zero out the section if it is loadable but not allocated in exec */
	else if (zero_bss_segs
		 && (bfd_get_section_flags(abfd, sect) & SEC_LOAD)
		 && bfd_section_vma(abfd, sect)
		 && bfd_section_size(abfd, sect))
	  {
	    /* zero out the section region */
	    mem_bzero(mem_fn,
		      bfd_section_vma(abfd, sect),
		      bfd_section_size(abfd, sect));
	  }
	else
	  {
	    /* else do nothing with this section, it's probably debug data */
	    debug("ignoring section `%s' during load...",
		  bfd_section_name(abfd, sect));
	  }

	/* expected text section */
	if (!strcmp(bfd_section_name(abfd, sect), ".text"))
	  {
	    /* .text section processing */
	    ld_text_size =
	      ((bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect))
	       - MD_TEXT_BASE)
		+ /* for speculative fetches/decodes */TEXT_TAIL_PADDING;

	    /* create tail padding and copy into simulator target memory */
#if 0
	    mem_bzero(mem_fn,
		      bfd_section_vma(abfd, sect)
		      + bfd_section_size(abfd, sect),
		      TEXT_TAIL_PADDING);
#endif
	  }
	/* expected data sections */
	else if (!strcmp(bfd_section_name(abfd, sect), ".rdata")
		 || !strcmp(bfd_section_name(abfd, sect), ".data")
		 || !strcmp(bfd_section_name(abfd, sect), ".sdata")
		 || !strcmp(bfd_section_name(abfd, sect), ".bss")
		 || !strcmp(bfd_section_name(abfd, sect), ".sbss"))
	  {
	    /* data section processing */
	    if (bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect) >
		data_break)
	      data_break = (bfd_section_vma(abfd, sect) +
			    bfd_section_size(abfd, sect));
	  }
	else
	  {
	    /* what is this section??? */
	    fatal("encountered unknown section `%s', %d bytes @ 0x%08x",
		  bfd_section_name(abfd, sect), bfd_section_size(abfd, sect),
		  bfd_section_vma(abfd, sect));
	  }
      }

    /* compute data segment size from data break point */
    ld_text_base = MD_TEXT_BASE;
    ld_data_base = MD_DATA_BASE;
    ld_prog_entry = bfd_get_start_address(abfd);
    ld_data_size = data_break - ld_data_base;

    /* done with the executable, close it */
    if (!bfd_close(abfd))
      fatal("could not close executable `%s'", argv[0]);
  }

#else /* !BFD_LOADER, i.e., standalone loader */

  {
    FILE *fobj;
    long floc;
    struct ecoff_filehdr fhdr;
    struct ecoff_aouthdr ahdr;
    struct ecoff_scnhdr shdr;

    /* record profile file name */
    ld_prog_fname = argv[0];

    /* load the program into memory, try both endians */
#if defined(__CYGWIN32__) || defined(_MSC_VER)
    fobj = fopen(argv[0], "rb");
#else
    fobj = fopen(argv[0], "r");
#endif
    if (!fobj)
      fatal("cannot open executable `%s'", argv[0]);

    if (fread(&fhdr, sizeof(struct ecoff_filehdr), 1, fobj) < 1)
      fatal("cannot read header from executable `%s'", argv[0]);

    /* record endian of target */
    if (fhdr.f_magic == MD_SWAPH(ECOFF_ALPHAMAGIC))
      ld_target_big_endian = FALSE;
    else if (fhdr.f_magic == MD_SWAPH(ECOFF_EB_MAGIC)
	     || fhdr.f_magic == MD_SWAPH(ECOFF_EL_MAGIC)
	     || fhdr.f_magic == MD_SWAPH(ECOFF_EB_OTHER)
	     || fhdr.f_magic == MD_SWAPH(ECOFF_EL_OTHER))
      fatal("Alpha simulator cannot run PISA binary `%s'", argv[0]);
    else
      fatal("bad magic number in executable `%s' (not an executable)",
	    argv[0]);

    if (fread(&ahdr, sizeof(struct ecoff_aouthdr), 1, fobj) < 1)
      fatal("cannot read AOUT header from executable `%s'", argv[0]);

    ld_text_base = MD_SWAPQ(ahdr.text_start);
    ld_text_size = MD_SWAPQ(ahdr.tsize);
    ld_prog_entry = MD_SWAPQ(ahdr.entry);
    ld_data_base = MD_SWAPQ(ahdr.data_start);
    ld_data_size = MD_SWAPQ(ahdr.dsize) + MD_SWAPQ(ahdr.bsize);
    regs->regs_R[MD_REG_GP] = MD_SWAPQ(ahdr.gp_value);

    /* compute data segment size from data break point */
    data_break = ld_data_base + ld_data_size;

    /* seek to the beginning of the first section header, the file header comes
       first, followed by the optional header (this is the aouthdr), the size
       of the aouthdr is given in Fdhr.f_opthdr */
    fseek(fobj, sizeof(struct ecoff_filehdr) + MD_SWAPH(fhdr.f_opthdr), 0);

    debug("processing %d sections in `%s'...",
	  MD_SWAPH(fhdr.f_nscns), argv[0]);

    /* loop through the section headers */
    floc = ftell(fobj);
    for (i = 0; i < MD_SWAPH(fhdr.f_nscns); i++)
      {
	char *p;

	if (fseek(fobj, floc, 0) == -1)
	  fatal("could not reset location in executable");
	if (fread(&shdr, sizeof(struct ecoff_scnhdr), 1, fobj) < 1)
	  fatal("could not read section %d from executable", i);
	floc = ftell(fobj);

	switch (MD_SWAPW(shdr.s_flags))
	  {
	  case ECOFF_STYP_TEXT:
	    p = calloc(MD_SWAPQ(shdr.s_size), sizeof(char));
	    if (!p)
	      fatal("out of virtual memory");

	    if (fseek(fobj, MD_SWAPQ(shdr.s_scnptr), 0) == -1)
	      fatal("could not read `.text' from executable", i);
	    if (fread(p, MD_SWAPQ(shdr.s_size), 1, fobj) < 1)
	      fatal("could not read text section from executable");

	    /* copy program section into simulator target memory */
	    mem_bcopy(mem_access, mem, Write,
		      MD_SWAPQ(shdr.s_vaddr), p, MD_SWAPQ(shdr.s_size));

#if 0
	    /* create tail padding and copy into simulator target memory */
	    mem_bzero(mem_access, mem,
		      MD_SWAPQ(shdr.s_vaddr) + MD_SWAPQ(shdr.s_size),
		      TEXT_TAIL_PADDING);
#endif

	    /* release the section buffer */
	    free(p);

#if 0
	    Text_seek = MD_SWAPQ(shdr.s_scnptr);
	    Text_start = MD_SWAPQ(shdr.s_vaddr);
	    Text_size = MD_SWAPQ(shdr.s_size) / 4;
	    /* there is a null routine after the supposed end of text */
	    Text_size += 10;
	    Text_end = Text_start + Text_size * 4;
	    /* create_text_reloc(shdr.s_relptr, shdr.s_nreloc); */
#endif
	    break;

	  case ECOFF_STYP_INIT:
	  case ECOFF_STYP_FINI:
	    if (MD_SWAPQ(shdr.s_size) > 0)
	      {
		p = calloc(MD_SWAPQ(shdr.s_size), sizeof(char));
		if (!p)
		  fatal("out of virtual memory");

		if (fseek(fobj, MD_SWAPQ(shdr.s_scnptr), 0) == -1)
		  fatal("could not read `.text' from executable", i);
		if (fread(p, MD_SWAPQ(shdr.s_size), 1, fobj) < 1)
		  fatal("could not read text section from executable");
		
		/* copy program section into simulator target memory */
		mem_bcopy(mem_access, mem,
			  Write, MD_SWAPQ(shdr.s_vaddr),
			  p, MD_SWAPQ(shdr.s_size));

		/* release the section buffer */
		free(p);
	      }
	    else
	      warn("section `%s' is empty...", shdr.s_name);
	    break;

	  case ECOFF_STYP_LITA:
	  case ECOFF_STYP_LIT8:
	  case ECOFF_STYP_LIT4:
	  case ECOFF_STYP_XDATA:
	  case ECOFF_STYP_PDATA:
	  case ECOFF_STYP_RCONST:
	    /* fall through */

	  case ECOFF_STYP_RDATA:
	    /* The .rdata section is sometimes placed before the text
	     * section instead of being contiguous with the .data section.
	     */
#if 0
	    Rdata_start = MD_SWAPQ(shdr.s_vaddr);
	    Rdata_size = MD_SWAPQ(shdr.s_size);
	    Rdata_seek = MD_SWAPQ(shdr.s_scnptr);
#endif
	    /* fall through */
	  case ECOFF_STYP_DATA:
#if 0
	    Data_seek = MD_SWAPQ(shdr.s_scnptr);
#endif
	    /* fall through */
	  case ECOFF_STYP_SDATA:
#if 0
	    Sdata_seek = MD_SWAPQ(shdr.s_scnptr);
#endif
	    if (MD_SWAPQ(shdr.s_size) > 0)
	      {
		p = calloc(MD_SWAPQ(shdr.s_size), sizeof(char));
		if (!p)
		  fatal("out of virtual memory");

		if (fseek(fobj, MD_SWAPQ(shdr.s_scnptr), 0) == -1)
		  fatal("could not read `.text' from executable", i);
		if (fread(p, MD_SWAPQ(shdr.s_size), 1, fobj) < 1)
		  fatal("could not read text section from executable");

		/* copy program section it into simulator target memory */
		mem_bcopy(mem_access, mem,
			  Write, MD_SWAPQ(shdr.s_vaddr),
			  p, MD_SWAPQ(shdr.s_size));

		/* release the section buffer */
		free(p);
	      }
	    else
	      warn("section `%s' is empty...", shdr.s_name);
	  break;

	  case ECOFF_STYP_BSS:
	  case ECOFF_STYP_SBSS:
	    /* no data to read... */
	    break;

	  default:
	    warn("section `%s' ignored...", shdr.s_name);
	  }
      }

    /* done with the executable, close it */
    if (fclose(fobj))
      fatal("could not close executable `%s'", argv[0]);
  }

#endif /* BFD_LOADER */

  /* perform sanity checks on segment ranges */
  if (!ld_text_base || !ld_text_size)
    fatal("executable is missing a `.text' section");
  if (!ld_data_base || !ld_data_size)
    fatal("executable is missing a `.data' section");
  if (!ld_prog_entry)
    fatal("program entry point not specified");

  /* determine byte/words swapping required to execute on this host */
  sim_swap_bytes = (endian_host_byte_order() != endian_target_byte_order());
  if (sim_swap_bytes)
    {
#if 0 /* FIXME: disabled until further notice... */
      /* cross-endian is never reliable, why this is so is beyond the scope
	 of this comment, e-mail me for details... */
      fprintf(stderr, "sim: *WARNING*: swapping bytes to match host...\n");
      fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n");
      /* #else */
      fatal("binary endian does not match host endian");
#endif
    }
  sim_swap_words = (endian_host_word_order() != endian_target_word_order());
  if (sim_swap_words)
    {
#if 0 /* FIXME: disabled until further notice... */
      /* cross-endian is never reliable, why this is so is beyond the scope
	 of this comment, e-mail me for details... */
      fprintf(stderr, "sim: *WARNING*: swapping words to match host...\n");
      fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n");
      /* #else */
      fatal("binary endian does not match host endian");
#endif
    }

  /* set up a local stack pointer, this is where the argv and envp
     data is written into program memory */
  ld_stack_base = ld_text_base - (409600+4096);
#if 0
  sp = ROUND_DOWN(ld_stack_base - MD_MAX_ENVIRON, sizeof(MD_DOUBLE_TYPE));
#endif
  sp = ld_stack_base - MD_MAX_ENVIRON;
  ld_stack_size = ld_stack_base - sp;
    printf("Thread 0 stack size (4)%d\n",  current->ld_stack_size);

  /* initial stack pointer value */
  ld_environ_base = sp;

  /* write [argc] to stack */
  temp = MD_SWAPQ(argc);
  mem_access(mem, Write, sp, &temp, sizeof(qword_t));
  regs->regs_R[MD_REG_A0] = temp;
  sp += sizeof(qword_t);

  /* skip past argv array and NULL */
  argv_addr = sp;
  regs->regs_R[MD_REG_A1] = argv_addr;
  sp = sp + (argc + 1) * sizeof(md_addr_t);

  /* save space for envp array and NULL */
  envp_addr = sp;
  for (i=0; envp[i]; i++)
    sp += sizeof(md_addr_t);
  sp += sizeof(md_addr_t);

  /* fill in the argv pointer array and data */
  for (i=0; i<argc; i++)
    {
      /* write the argv pointer array entry */
      temp = MD_SWAPQ(sp);
      mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t),
		 &temp, sizeof(md_addr_t));
      /* and the data */
      mem_strcpy(mem_access, mem, Write, sp, argv[i]);
      sp += strlen(argv[i])+1;
    }
  /* terminate argv array with a NULL */
  mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t),
	     &null_ptr, sizeof(md_addr_t));

  /* write envp pointer array and data to stack */
  for (i = 0; envp[i]; i++)
    {
      /* write the envp pointer array entry */
      temp = MD_SWAPQ(sp);
      mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t),
		 &temp, sizeof(md_addr_t));
      /* and the data */
      mem_strcpy(mem_access, mem, Write, sp, envp[i]);
      sp += strlen(envp[i]) + 1;
    }
  /* terminate the envp array with a NULL */
  mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t),
	     &null_ptr, sizeof(md_addr_t));

  /* did we tromp off the stop of the stack? */
  if (sp > ld_stack_base)
    {
      /* we did, indicate to the user that MD_MAX_ENVIRON must be increased,
	 alternatively, you can use a smaller environment, or fewer
	 command line arguments */
      fatal("environment overflow, increase MD_MAX_ENVIRON in alpha.h");
    }

  /* initialize the bottom of heap to top of data segment */
  ld_brk_point = ROUND_UP(ld_data_base + ld_data_size, MD_PAGE_SIZE);

  /* set initial minimum stack pointer value to initial stack value */
  ld_stack_min = regs->regs_R[MD_REG_SP];

  regs->regs_R[MD_REG_SP] = ld_environ_base;
  regs->regs_PC = ld_prog_entry;

  printf("ld_text_base: 0x%08x  ld_text_size: 0x%08x",
	ld_text_base, ld_text_size);
  printf("ld_data_base: 0x%08x  ld_data_size: 0x%08x",
	ld_data_base, ld_data_size);
  printf("ld_stack_base: 0x%08x  ld_stack_size: 0x%08x",
	ld_stack_base, ld_stack_size);
  printf("ld_prog_entry: 0x%08x", ld_prog_entry);

  debug("ld_text_base: 0x%08x  ld_text_size: 0x%08x",
	ld_text_base, ld_text_size);
  debug("ld_data_base: 0x%08x  ld_data_size: 0x%08x",
	ld_data_base, ld_data_size);
  debug("ld_stack_base: 0x%08x  ld_stack_size: 0x%08x",
	ld_stack_base, ld_stack_size);
  debug("ld_prog_entry: 0x%08x", ld_prog_entry);
}
Example #9
0
/* start simulation, program loaded, processor precise state initialized */
void
sim_main(void)
{
  int i;
  md_inst_t inst;
  register md_addr_t addr;
  register int is_write;
  enum md_opcode op;
  unsigned int flags;
  enum md_fault_type fault;

  fprintf(stderr, "sim: ** starting functional simulation **\n");

  /* set up initial default next PC */
  regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

  /* check for DLite debugger entry condition */
  if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
    dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
	       sim_num_insn, &regs, mem);

  while (TRUE)
    {
      /* maintain $r0 semantics */
      regs.regs_R[MD_REG_ZERO] = 0;
#ifdef TARGET_ALPHA
      regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

      /* get the next instruction to execute */
      mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t));

      if (verbose)
	{
	  myfprintf(stderr, "%10n @ 0x%08p: ", sim_num_insn, regs.regs_PC);
	  md_print_insn(inst, regs.regs_PC, stderr);
	  fprintf(stderr, "\n");
	  /* fflush(stderr); */
	}

      /* keep an instruction count */
      sim_num_insn++;

      /* set default reference address and access mode */
      addr = 0; is_write = FALSE;

      /* set default fault - none */
      fault = md_fault_none;

      /* decode the instruction */
      MD_SET_OPCODE(op, inst);

      /* execute the instruction */
      switch (op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)		\
	case OP:							\
          SYMCAT(OP,_IMPL);						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "machine.def"
	default:
	  panic("attempted to execute a bogus opcode");
      }

      if (MD_OP_FLAGS(op) & F_MEM)
	{
	  sim_num_refs++;
	  if (MD_OP_FLAGS(op) & F_STORE)
	    is_write = TRUE;
	}

      /*
       * profile this instruction
       */
      flags = MD_OP_FLAGS(op);

      if (prof_ic)
	{
	  enum inst_class_t ic;

	  /* compute instruction class */
	  if (flags & F_LOAD)
	    ic = ic_load;
	  else if (flags & F_STORE)
	    ic = ic_store;
	  else if (flags & F_UNCOND)
	    ic = ic_uncond;
	  else if (flags & F_COND)
	    ic = ic_cond;      
	  else if (flags & F_ICOMP)
	    ic = ic_icomp;
	  else if (flags & F_FCOMP)
	    ic = ic_fcomp;
	  else if (flags & F_TRAP)
	    ic = ic_trap;
	  else
	    panic("instruction has no class");

	  /* update instruction class profile */
	  stat_add_sample(ic_prof, (int)ic);
	}

      if (prof_inst)
	{
	  /* update instruction profile */
	  stat_add_sample(inst_prof, (int)op - /* skip NA */1);
	}

      if (prof_bc)
	{
	  enum branch_class_t bc;

	  /* compute instruction class */
	  if (flags & F_CTRL)
	    {
	      if ((flags & (F_CALL|F_DIRJMP)) == (F_CALL|F_DIRJMP))
		bc = bc_call_dir;
	      else if ((flags & (F_CALL|F_INDIRJMP)) == (F_CALL|F_INDIRJMP))
		bc = bc_call_indir;
	      else if ((flags & (F_UNCOND|F_DIRJMP)) == (F_UNCOND|F_DIRJMP))
		bc = bc_uncond_dir;
	      else if ((flags & (F_UNCOND|F_INDIRJMP))== (F_UNCOND|F_INDIRJMP))
		bc = bc_uncond_indir;
	      else if ((flags & (F_COND|F_DIRJMP)) == (F_COND|F_DIRJMP))
		bc = bc_cond_dir;
	      else if ((flags & (F_COND|F_INDIRJMP)) == (F_COND|F_INDIRJMP))
		bc = bc_cond_indir;
	      else
		panic("branch has no class");

	      /* update instruction class profile */
	      stat_add_sample(bc_prof, (int)bc);
	    }
	}

      if (prof_am)
	{
	  enum md_amode_type am;

	  /* update addressing mode pre-probe FSM */
	  MD_AMODE_PREPROBE(op, fsm);

	  /* compute addressing mode */
	  if (flags & F_MEM)
	    {
	      /* compute addressing mode */
	      MD_AMODE_PROBE(am, op, fsm);

	      /* update the addressing mode profile */
	      stat_add_sample(am_prof, (int)am);

	      /* addressing mode pre-probe FSM, after all loads and stores */
	      MD_AMODE_POSTPROBE(fsm);
	    }
	}

      if (prof_seg)
	{
	  if (flags & F_MEM)
	    {
	      /* update instruction profile */
	      stat_add_sample(seg_prof, (int)bind_to_seg(addr));
	    }
	}

      if (prof_tsyms)
	{
	  int tindex;

	  /* attempt to bind inst address to a text segment symbol */
	  sym_bind_addr(regs.regs_PC, &tindex, /* !exact */FALSE, sdb_text);

	  if (tindex >= 0)
	    {
	      if (tindex > sym_ntextsyms)
		panic("bogus text symbol index");

	      stat_add_sample(tsym_prof, tindex);
	    }
	  /* else, could not bind to a symbol */
	}

      if (prof_dsyms)
	{
	  int dindex;

	  if (flags & F_MEM)
	    {
	      /* attempt to bind inst address to a text segment symbol */
	      sym_bind_addr(addr, &dindex, /* !exact */FALSE, sdb_data);

	      if (dindex >= 0)
		{
		  if (dindex > sym_ndatasyms)
		    panic("bogus data symbol index");

		  stat_add_sample(dsym_prof, dindex);
		}
	      /* else, could not bind to a symbol */
	    }
	}

      if (prof_taddr)
	{
	  /* add regs_PC exec event to text address profile */
	  stat_add_sample(taddr_prof, regs.regs_PC);
	}

      /* update any stats tracked by PC */
      for (i=0; i<pcstat_nelt; i++)
	{
	  counter_t newval;
	  int delta;

	  /* check if any tracked stats changed */
	  newval = STATVAL(pcstat_stats[i]);
	  delta = newval - pcstat_lastvals[i];
	  if (delta != 0)
	    {
	      stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta);
	      pcstat_lastvals[i] = newval;
	    }

	}

      /* check for DLite debugger entry condition */
      if (dlite_check_break(regs.regs_NPC,
			    is_write ? ACCESS_WRITE : ACCESS_READ,
			    addr, sim_num_insn, sim_num_insn))
	dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

      /* go to the next instruction */
      regs.regs_PC = regs.regs_NPC;
      regs.regs_NPC += sizeof(md_inst_t);

      /* finish early? */
      if (max_insts && sim_num_insn >= max_insts)
	return;
    }
}
Example #10
0
/* start simulation, program loaded, processor precise state initialized */
void
sim_main(void)
{
  md_inst_t inst;
  register md_addr_t addr, target_PC;
  enum md_opcode op;
  register int is_write;
  int stack_idx;
  enum md_fault_type fault;

  fprintf(stderr, "sim: ** starting functional simulation w/ predictors **\n");

  /* set up initial default next PC */
  regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

  /* check for DLite debugger entry condition */
  if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
    dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
	       sim_num_insn, &regs, mem);

  while (TRUE)
    {
      /* maintain $r0 semantics */
      regs.regs_R[MD_REG_ZERO] = 0;
#ifdef TARGET_ALPHA
      regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

      /* get the next instruction to execute */
      mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t));

      /* keep an instruction count */
      sim_num_insn++;

      /* set default reference address and access mode */
      addr = 0; is_write = FALSE;

      /* set default fault - none */
      fault = md_fault_none;

      /* decode the instruction */
      MD_SET_OPCODE(op, inst);

      /* execute the instruction */
      switch (op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)		\
	case OP:							\
          SYMCAT(OP,_IMPL);						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "machine.def"
	default:
	  panic("attempted to execute a bogus opcode");
      }

      if (fault != md_fault_none)
	fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC);

      if (MD_OP_FLAGS(op) & F_MEM)
	{
	  sim_num_refs++;
	  if (MD_OP_FLAGS(op) & F_STORE)
	    is_write = TRUE;
	}

      if (MD_OP_FLAGS(op) & F_CTRL)
	{
	  md_addr_t pred_PC;
	  struct bpred_update_t update_rec;

	  sim_num_branches++;

	  if (pred)
	    {
	      /* get the next predicted fetch address */
	      pred_PC = bpred_lookup(pred,
				     /* branch addr */regs.regs_PC,
				     /* target */target_PC,
				     /* inst opcode */op,
				     /* call? */MD_IS_CALL(op),
				     /* return? */MD_IS_RETURN(op),
				     /* stash an update ptr */&update_rec,
				     /* stash return stack ptr */&stack_idx);

	      /* valid address returned from branch predictor? */
	      if (!pred_PC)
		{
		  /* no predicted taken target, attempt not taken target */
		  pred_PC = regs.regs_PC + sizeof(md_inst_t);
		}

	      bpred_update(pred,
			   /* branch addr */regs.regs_PC,
			   /* resolved branch target */regs.regs_NPC,
			   /* taken? */regs.regs_NPC != (regs.regs_PC +
							 sizeof(md_inst_t)),
			   /* pred taken? */pred_PC != (regs.regs_PC +
							sizeof(md_inst_t)),
			   /* correct pred? */pred_PC == regs.regs_NPC,
			   /* opcode */op,
			   /* predictor update pointer */&update_rec);
	    }
	}

      /* check for DLite debugger entry condition */
      if (dlite_check_break(regs.regs_NPC,
			    is_write ? ACCESS_WRITE : ACCESS_READ,
			    addr, sim_num_insn, sim_num_insn))
	dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

      /* go to the next instruction */
      regs.regs_PC = regs.regs_NPC;
      regs.regs_NPC += sizeof(md_inst_t);

      /* finish early? */
      if (max_insts && sim_num_insn >= max_insts)
	return;
    }
}
Example #11
0
static int mips_sys_mmap(struct mips_ctx_t *ctx, unsigned int addr, unsigned int len,
	int prot, int flags, int guest_fd, int offset)
{
	struct mem_t *mem = ctx->mem;

	unsigned int len_aligned;

	int perm;
	int host_fd;

	struct mips_file_desc_t *desc;

	/* Check that protection flags match in guest and host */
	assert(PROT_READ == 1);
	assert(PROT_WRITE == 2);
	assert(PROT_EXEC == 4);

	/* Check that mapping flags match */
	assert(MAP_SHARED == 0x01);
	assert(MAP_PRIVATE == 0x02);
	assert(MAP_FIXED == 0x10);
	assert(MAP_ANONYMOUS == 0x20);

	/* Translate file descriptor */
	desc = mips_file_desc_table_entry_get(ctx->file_desc_table, guest_fd);
	host_fd = desc ? desc->host_fd : -1;
	if (guest_fd > 0 && host_fd < 0)
		fatal("%s: invalid guest descriptor", __FUNCTION__);

	/* Permissions */
	perm = mem_access_init;
	perm |= prot & PROT_READ ? mem_access_read : 0;
	perm |= prot & PROT_WRITE ? mem_access_write : 0;
	perm |= prot & PROT_EXEC ? mem_access_exec : 0;

	/* Flag MAP_ANONYMOUS.
	 * If it is set, the 'fd' parameter is ignored. */
	if (flags & MAP_ANONYMOUS)
		host_fd = -1;

	/* 'addr' and 'offset' must be aligned to page size boundaries.
	 * 'len' is rounded up to page boundary. */
	if (offset & ~MEM_PAGE_MASK)
		fatal("%s: unaligned offset", __FUNCTION__);
	if (addr & ~MEM_PAGE_MASK)
		fatal("%s: unaligned address", __FUNCTION__);
	len_aligned = ROUND_UP(len, MEM_PAGE_SIZE);

	/* Find region for allocation */
	if (flags & MAP_FIXED)
	{
		/* If MAP_FIXED is set, the 'addr' parameter must be obeyed, and is not just a
		 * hint for a possible base address of the allocated range. */
		if (!addr)
			fatal("%s: no start specified for fixed mapping", __FUNCTION__);

		/* Any allocated page in the range specified by 'addr' and 'len'
		 * must be discarded. */
		mem_unmap(mem, addr, len_aligned);
	}
	else
	{
		if (!addr || mem_map_space_down(mem, addr, len_aligned) != addr)
			addr = SYS_MMAP_BASE_ADDRESS;
		addr = mem_map_space_down(mem, addr, len_aligned);
		if (addr == -1)
			fatal("%s: out of guest memory", __FUNCTION__);
	}

	/* Allocation of memory */
	mem_map(mem, addr, len_aligned, perm);

	/* Host mapping */
	if (host_fd >= 0)
	{
		char buf[MEM_PAGE_SIZE];

		unsigned int last_pos;
		unsigned int curr_addr;

		int size;
		int count;

		/* Save previous position */
		last_pos = lseek(host_fd, 0, SEEK_CUR);
		lseek(host_fd, offset, SEEK_SET);

		/* Read pages */
		assert(len_aligned % MEM_PAGE_SIZE == 0);
		assert(addr % MEM_PAGE_SIZE == 0);
		curr_addr = addr;
		for (size = len_aligned; size > 0; size -= MEM_PAGE_SIZE)
		{
			memset(buf, 0, MEM_PAGE_SIZE);
			count = read(host_fd, buf, MEM_PAGE_SIZE);
			if (count)
				mem_access(mem, curr_addr, MEM_PAGE_SIZE, buf, mem_access_init);
			curr_addr += MEM_PAGE_SIZE;
		}

		/* Return file to last position */
		lseek(host_fd, last_pos, SEEK_SET);
	}

	/* Return mapped address */
	return addr;
}
Example #12
0
/* Load program headers table */
void X86ContextLoadProgramHeaders(X86Context *self)
{
	struct x86_loader_t *loader = self->loader;
	struct mem_t *mem = self->mem;

	struct elf_file_t *elf_file = loader->elf_file;
	struct elf_program_header_t *program_header;

	uint32_t phdt_base;
	uint32_t phdt_size;
	uint32_t phdr_count;
	uint32_t phdr_size;

	char str[MAX_STRING_SIZE];
	int i;

	/* Load program header table from ELF */
	x86_loader_debug("\nLoading program headers\n");
	phdr_count = elf_file->header->e_phnum;
	phdr_size = elf_file->header->e_phentsize;
	phdt_size = phdr_count * phdr_size;
	assert(phdr_count == list_count(elf_file->program_header_list));
	
	/* Program header PT_PHDR, specifying location and size of the program header table itself. */
	/* Search for program header PT_PHDR, specifying location and size of the program header table.
	 * If none found, choose loader->bottom - phdt_size. */
	phdt_base = loader->bottom - phdt_size;
	for (i = 0; i < list_count(elf_file->program_header_list); i++)
	{
		program_header = list_get(elf_file->program_header_list, i);
		if (program_header->header->p_type == PT_PHDR)
			phdt_base = program_header->header->p_vaddr;
	}
	x86_loader_debug("  virtual address for program header table: 0x%x\n", phdt_base);

	/* Load program headers */
	mem_map(mem, phdt_base, phdt_size, mem_access_init | mem_access_read);
	for (i = 0; i < list_count(elf_file->program_header_list); i++)
	{
		/* Load program header */
		program_header = list_get(elf_file->program_header_list, i);
		mem_access(mem, phdt_base + i * phdr_size, phdr_size,
			program_header->header, mem_access_init);

		/* Debug */
		str_map_value_buf(&elf_program_header_type_map, program_header->header->p_type,
			str, sizeof(str));
		x86_loader_debug("  header loaded at 0x%x\n", phdt_base + i * phdr_size);
		x86_loader_debug("    type=%s, offset=0x%x, vaddr=0x%x, paddr=0x%x\n",
			str, program_header->header->p_offset,
			program_header->header->p_vaddr,
			program_header->header->p_paddr);
		x86_loader_debug("    filesz=%d, memsz=%d, flags=%d, align=%d\n",
			program_header->header->p_filesz,
			program_header->header->p_memsz,
			program_header->header->p_flags,
			program_header->header->p_align);

		/* Program interpreter */
		if (program_header->header->p_type == 3)
		{
			mem_read_string(mem, program_header->header->p_vaddr, sizeof(str), str);
			loader->interp = str_set(NULL, str);
		}
	}

	/* Free buffer and save pointers */
	loader->phdt_base = phdt_base;
	loader->phdr_count = phdr_count;
}
Example #13
0
/* start simulation, program loaded, processor precise state initialized */
void
sim_main(void)
{
  md_inst_t inst;
  register md_addr_t addr, target_PC;
  enum md_opcode op;
  register int is_write;
  int stack_idx;
  enum md_fault_type fault;

  int out1, out2, in1, in2, in3;	  /* register names */
  int v_out1, v_out2, v_in1, v_in2, v_in3;/* register values */
  int vl_out1, vl_out2, vl_in1, vl_in2, vl_in3;
  md_addr_t addr_dispatch;              /* access_address */
  int m_size;                           /* access_size */
  FILE *stream;
  md_addr_t predicted_PC;

  fprintf(stderr, "sim: ** starting functional simulation w/ predictors **\n");

  /* set up initial default next PC */
  regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t);

  /* check for DLite debugger entry condition */
  if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0))
    dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC,
	       sim_num_insn, &regs, mem);

  while (TRUE)
    {
      /* maintain $r0 semantics */
      regs.regs_R[MD_REG_ZERO] = 0;
#ifdef TARGET_ALPHA
      regs.regs_F.d[MD_REG_ZERO] = 0.0;
#endif /* TARGET_ALPHA */

      /* get the next instruction to execute */
      mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t));

      /* keep an instruction count */
      sim_num_insn++;

      /* set default reference address and access mode */
      addr = 0; is_write = FALSE;

      /* set default fault - none */
      fault = md_fault_none;

      /* decode the instruction */
      MD_SET_OPCODE(op, inst);

      /* execute the instruction */
      switch (op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,CLASS,O1,O2,I1,I2,I3,            \
                VO1,LO1,VO2,LO2,ADDR,VI1,LI1,VI2,LI2,VI3,LI3,M_Size)    \
	case OP:							\
	  in1 = I1; in2 = I2; in3 = I3;					\
	  v_in1 = VI1; v_in2 = VI2; v_in3 = VI3;			\
	  vl_in1 = LI1; vl_in2 = LI2; vl_in3 = LI3;			\
          SYMCAT(OP,_IMPL);						\
	  out1 = O1; out2 = O2;						\
	  v_out1 = VO1; v_out2 = VO2;					\
	  vl_out1 = LO1; vl_out2 = LO2;					\
	  addr_dispatch = ADDR;						\
	  m_size = M_Size;						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "operand.def"
	default:
	  panic("attempted to execute a bogus opcode");
      }

      if (fault != md_fault_none)
	fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC);

      if (MD_OP_FLAGS(op) & F_MEM)
	{
	  sim_num_refs++;
	  if (MD_OP_FLAGS(op) & F_STORE)
	    is_write = TRUE;
	}

      if (MD_OP_FLAGS(op) & F_CTRL)
	{
	  md_addr_t pred_PC;
	  struct bpred_update_t update_rec;

	  sim_num_branches++;

	  if (pred)
	    {
	      /* get the next predicted fetch address */
	      pred_PC = bpred_lookup(pred,
				     /* branch addr */regs.regs_PC,
				     /* target */target_PC,
				     /* inst opcode */op,
				     /* call? */MD_IS_CALL(op),
				     /* return? */MD_IS_RETURN(op),
				     /* stash an update ptr */&update_rec,
				     /* stash return stack ptr */&stack_idx);

	      /* valid address returned from branch predictor? */
	      if (!pred_PC)
		{
		  /* no predicted taken target, attempt not taken target */
		  pred_PC = regs.regs_PC + sizeof(md_inst_t);
		}

	      bpred_update(pred,
			   /* branch addr */regs.regs_PC,
			   /* resolved branch target */regs.regs_NPC,
			   /* taken? */regs.regs_NPC != (regs.regs_PC +
							 sizeof(md_inst_t)),
			   /* pred taken? */pred_PC != (regs.regs_PC +
							sizeof(md_inst_t)),
			   /* correct pred? */pred_PC == regs.regs_NPC,
			   /* opcode */op,
			   /* predictor update pointer */&update_rec);
	    }
	  predicted_PC = pred_PC;
	}

      /*   ここから下を見ればどの変数に何が入っているか分かるはず。 */
      stream = stdout;
      fprintf(stream, "############################################################ \n");
      fprintf(stream, " --- trace count(%d) \n", (int)sim_num_insn);
      fprintf(sim_fd, "%s, inst: `",
      fprintf(stream, "       opcode: %s, inst: `",
	      MD_OP_NAME(op));
      md_print_insn(inst, regs.regs_PC, stream);
      fprintf(stream, "'\n");
      myfprintf(stream, "         PC: 0x%08p, NPC: 0x%08p",
		regs.regs_PC, regs.regs_NPC);
      if(pred)
	myfprintf(stream, " (pred_PC: 0x%08p)\n",
		  regs.regs_PC, regs.regs_NPC, predicted_PC);
      else
	myfprintf(stream, "\n");
      fprintf(stream," |  in(r%02d,r%02d,r%02d),out(r%02d,r%02d),\n",
	      in1, in2, in3, out1, out2);
      fprintf(stream," |  IN(%8x,%8x,%8x),OUT(%8x,%8x)addr(%8x)|\n",
	      v_in1, v_in2, v_in3, v_out1, v_out2, addr_dispatch);
      /* ダブルワードだった場合,この変数がセットされる */
      fprintf(stream," |  in(%8x,%8x,%8x),out(%8x,%8x)         |\n",
	      vl_in1, vl_in2, vl_in3, vl_out1, vl_out2);

      /* machine.h をみるとopから命令の種類を判別する方法が分かる。以下は例 */
      if (op == MD_NOP_OP)
	{
	  fprintf(stream, "   NOP instruction \n");
	}
      else if (MD_OP_FLAGS(op) & F_MEM)
	{
	  fprintf(stream, "   MEMORY instruction \n");
	  if (MD_OP_FLAGS(op) & F_STORE)
	    fprintf(stream, "        store instruction \n");
	  else if (MD_OP_FLAGS(op) & F_LOAD)
	    fprintf(stream, "        load instruction \n");
	  fprintf(stream, "          ld/st address is %010x\n",
		  addr_dispatch);
	  fprintf(stream, "          ld/st size is %2d\n",
		  m_size);
	  /* ロードストアがバイト単位なのか,ワード単位なのか,
	     ハーフワード単位なのかは,opを見て判断できる。
	     例えば, md_op2name[op] が "sh"ならハーフワードである。
	     しかし、これだと面倒なのでoperand.defを改良した方が良い
	     かも知れない。これはおまかせ。
	     */
	  
	  /* ロードストアの詳細に関しては,machine.def を参照。
	     例えば,store halfの場合,(machine.def をエディタで開いて
	     "sh"と言う文字列をサーチすれば該当箇所が見つかる)
	     以下のようにかかれている。*/
	  /*
                #define SH_IMPL                                     
                  {                                                 
                    half_t _src;                                    
                    enum md_fault_type _fault;                      
                    _src = (half_t)(word_t)GPR(RT);                 
                    WRITE_HALF(_src, GPR(BS) + OFS, _fault);        
                    if (_fault != md_fault_none)                    
                      DECLARE_FAULT(_fault);                        
                   }
		   */
	  /*ここで、GPR(BS)はBS番レジスタの値 OFS はオフセットを示す。
	    そして,GPR(RT)はRT番レジスタの値を示す。
	    そしてWRITE_HALF(_src, GPR(BS) + OFS, _fault);は
	    値 _src をアドレス GPR(BS) + OFS に書き込む事を意味する。
	    書き込みのサイズは,halfワードである。*/
	}
      else if (MD_OP_FLAGS(op) & F_CTRL)
	{
	  fprintf(stream, "   BRANCH instruction \n");
	  if (MD_IS_CALL(op))
	    fprintf(stream, "        function call \n");
	  else if (MD_IS_RETURN(op))
	    fprintf(stream, "        function return \n");
	  else if (MD_IS_INDIR(op))
	    fprintf(stream, "        indirect jump \n");
	  else if ((MD_OP_FLAGS(op) & (F_CTRL|F_DIRJMP)) == (F_CTRL|F_DIRJMP))
	    fprintf(stream, "        direct jump \n");
	}
      else
	{
	  fprintf(stream, "   other instruction \n");
	}
      /* この応用として,いきなりopからstoreを判別するには,以下のようにすれば良い*/
      if ((MD_OP_FLAGS(op) & (F_MEM|F_STORE)) == (F_MEM|F_STORE))
	{
	  /*fprintf(stream, "   store instruction \n");*/
	}
      else if ((MD_OP_FLAGS(op) & (F_MEM|F_LOAD)) == (F_MEM|F_LOAD))
	{
	  /*fprintf(stream, "   load instruction \n");*/
	}

      /* ここまで */


      /* check for DLite debugger entry condition */
      if (dlite_check_break(regs.regs_NPC,
			    is_write ? ACCESS_WRITE : ACCESS_READ,
			    addr, sim_num_insn, sim_num_insn))
	dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, &regs, mem);

      /* go to the next instruction */
      regs.regs_PC = regs.regs_NPC;
      regs.regs_NPC += sizeof(md_inst_t);

      /* finish early? */
      if (max_insts && sim_num_insn >= max_insts)
	return;
    }
}
Example #14
0
/* start simulation, program loaded, processor precise state initialized */
bool_t
sim_sample(unsigned int n_insn)
{
  md_inst_t inst;
  enum md_fault_t fault;
  struct predec_insn_t *pdi;
  counter_t sim_num_insn_begin = sim_num_insn;
  bool_t fdumpinsn;

  while (n_insn == 0 || sim_num_insn < sim_num_insn_begin + n_insn)
    {
      /* maintain $r0 semantics */
      regs.regs[MD_REG_ZERO].q = 0;
      regs.regs[MD_FREG_ZERO].d = 0.0;

      /* get the next instruction to execute */
      if (itlb)
	cache_access(itlb, mc_READ, regs.PC, sizeof(md_inst_t), 0, NULL, tlb_miss_handler);
      if (cache_il1)
	cache_access(cache_il1, mc_READ, regs.PC, sizeof(md_inst_t), 0, NULL, l1_miss_handler);

      mem_access(mem, mc_READ, regs.PC, &inst, sizeof(md_inst_t));

      /* set default reference address and access mode */
      regs.addr = 0; regs.dsize = 0;

      /* set default fault - none */
      fault = md_fault_none;

      /* get the next instruction to execute */
      pdi = predec_lookup(regs.PC);
      if (!pdi)
	{
	  mem_access(mem, mc_READ, regs.PC, &inst, sizeof(md_inst_t));
	  pdi = predec_enter(regs.PC, inst);
	}

      /* keep an instruction count */
      if (pdi->iclass != ic_nop)
	{
	  sim_num_insn++;
	  sim_sample_insn++;
	  sim_sample_insn_split[pdi->iclass]++;
	}

      fdumpinsn = fdump && sim_num_insn >= insn_dumpbegin && sim_num_insn < insn_dumpend; 
      inst = pdi->inst;
      
      /* execute the instruction */
      switch (pdi->poi.op)
	{
#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)		\
	case OP:							\
          SYMCAT(OP,_IMPL);						\
          break;
#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\
        case OP:							\
          panic("attempted to execute a linking opcode");
#define CONNECT(OP)
#define DECLARE_FAULT(FAULT)						\
	  { fault = (FAULT); break; }
#include "machine.def"
	default:
          panic("attempted to execute a bogus opcode");
	}

      if (fault != md_fault_none)
	fatal("fault (%d) detected @ 0x%08p", fault, regs.PC);

      if (pdi->iclass == ic_load || pdi->iclass == ic_store || pdi->iclass == ic_prefetch)
	{
	  enum mem_cmd_t dl1_cmd = pdi->iclass == ic_store ? mc_WRITE : (pdi->iclass == ic_load ? mc_READ : mc_PREFETCH);
	  enum mem_cmd_t dtlb_cmd = (pdi->iclass == ic_store || pdi->iclass == ic_load) ? mc_READ : mc_PREFETCH;
	  bool_t miss_info[ct_NUM] = {FALSE, FALSE, FALSE, FALSE};

	  if (cache_dl1)
	    cache_access(cache_dl1, dl1_cmd, regs.addr, regs.dsize, 0, miss_info, l1_miss_handler);

	  if (dtlb)
	    cache_access(dtlb, dtlb_cmd, regs.addr, regs.dsize, 0, NULL, tlb_miss_handler);
	}


      /* go to the next instruction */
      regs.PC = regs.NPC;
      regs.NPC += sizeof(md_inst_t);

      if (verbose)
	{
	  myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ",
		    sim_num_insn, md_xor_regs(&regs), regs.PC);
	  md_print_insn(inst, regs.PC, stderr);
	  if (MD_OP_HASFLAGS(pdi->poi.op, F_MEM))
	    myfprintf(stderr, "  mem: 0x%08p", regs.addr);
	  fprintf(stderr, "\n");
	  /* fflush(stderr); */
	}
	  
      if (fdumpinsn)
	{
	  fprintf(fdump, "%-9u: 0x%08x ", (word_t)sim_num_insn, (word_t)regs.PC);
	  if (LREG_ISDEP(pdi->lregnums[DEP_O1]))
	    myfprintf(fdump, " O1: %016p", regs_value(pdi->lregnums[DEP_O1]));
	  fprintf(fdump, "\n");
	}

      if (fdump && sim_num_insn == insn_dumpend)
	{
	  fflush(fdump);
	  fclose(fdump);
	}

      /* finish early? */
      if (insn_limit && sim_sample_insn >= insn_limit)
	{
	  myfprintf(stderr, "Reached instruction limit: %u\n", insn_limit);
	  return FALSE;
	}
      
      if (insn_progress && sim_sample_insn >= insn_progress)
	{
	  sim_print_stats(stderr);
	  fflush(stderr);
	  while (sim_sample_insn >= insn_progress)
	    insn_progress += insn_progress_update;
	}
    }

  return (sim_num_insn - sim_num_insn_begin == n_insn); 
}
int sc_main(int, char *[])
{
  // Silence the following deprecation warning:
  // Info: (I804) /IEEE_Std_1666/deprecated: positional binding
  // using << or , is deprecated, use () instead.


  sc_report_handler::set_actions("/IEEE_Std_1666/deprecated", SC_DO_NOTHING);

  // ************************ ICACHE ***********************************
  // ICACHE = ram_cs
  // ICACHE = ram_we
  // ICACHE = addr
  // ICACHE = ram_datain
  // ICACHE = ram_dataout
  // ICACHE = ld_valid = pid_valid
  // ICACHE = ld_data = pid_data
  sc_signal<bool>       icache_valid("ICACHE_VALID") ;

  // ************************ BIOS ***********************************
  sc_signal<bool>       ram_cs("RAM_CS") ;
  sc_signal<bool>       ram_we("RAM_WE") ;
  sc_signal<unsigned >    addr("Address") ;
  sc_signal<unsigned >    ram_datain("RAM_DATAIN") ;
  sc_signal<unsigned >    ram_dataout("RAM_DATAOUT") ;
  sc_signal<bool>       bios_valid("BIOS_VALID") ;
  const int delay_cycles = 2;

  // ************************ Paging ***********************************
  // Paging paging_din = ram_datain
  // Paging paging_csin = ram_cs
  // Paging paging_wein = ram_we
  // Paging logical_address = addr 
  sc_signal<unsigned >    icache_din("ICACHE_DIN") ;
  sc_signal<bool>       icache_validin("ICACHE_VALIDIN") ;
  sc_signal<bool>       icache_stall("ICACHE_STALL") ;
  sc_signal<unsigned >    paging_dout("PAGING_DOUT") ;
  sc_signal<bool>       paging_csout("PAGING_CSOUT") ;
  sc_signal<bool>       paging_weout("PAGING_WEOUT") ;
  sc_signal<unsigned >    physical_address("PHYSICAL_ADDRESS") ;
  // Paging dataout  = ram_dataout 
  // Paging data_valid = icache_valid
  // Paging stall_ifu = stall_fetch


  // ************************ Fetch ***********************************
  // IFU ramdata = ram_dataout
  sc_signal<unsigned >    branch_target_address("BRANCH_TARGET_ADDRESS") ;
  sc_signal<bool>       next_pc("NEXT_PC") ;
  sc_signal<bool>       branch_valid("BRANCH_VALID") ;
  sc_signal<bool>       stall_fetch("STALL_FETCH") ;
  sc_signal<bool>       pred_fetch("PRED_FETCH") ;
  // IFU ram_valid = bios_valid
  // IFU ram_cs = ram_cs
  // IFU ram_we = ram_we
  // IFU address = addr
  // IFU smc_instrction = ram_datain
  // IFU pred_branch_address = pred_branch_address
  // IFU pred_branch_valid = pred_branch_valid
  sc_signal<unsigned>   instruction("INSTRUCTION") ;
  sc_signal<bool>       instruction_valid("INSTRUCTION_VALID") ;
  sc_signal<unsigned >    program_counter("PROGRAM_COUNTER") ;
  sc_signal<bool>       branch_clear("BRANCH_CLEAR") ;
  sc_signal<bool>       pred_fetch_valid("PRED_FETCH_VALID") ;
  sc_signal<bool>       reset("RESET") ;

  // ************************ Branch ***********************************
  // BPU: fetch_inst = instruction
  // BPU: fetch_pc = program_counter
  // BPU: fetch_valid = instruction_valid
  // BPU: branch_inst_addr = branch_instruction_address
  // BPU: branch_target_address = branch_target_address
  // BPU: branch_valid = branch_valid
  sc_signal<unsigned >	pred_branch_address("PRED_BRANCH_ADDRESS");
  sc_signal<bool>       pred_branch_valid("PRED_BRANCH_VALID") ;
  sc_signal<bool>       pred_tellid("PRED_TELLID") ;
  sc_signal<unsigned>   pred_instruction("PRED_INSTRUCTION") ;
  sc_signal<bool>       pred_inst_valid("PRED_INST_VALID") ;
  sc_signal<unsigned >	pred_inst_pc("PRED_INST_PC");


  // ************************ Decode ***********************************
  // ID instruction = instruction
  // ID instruction = instruction_valid
  // ID destreg_write = out_valid
  // ID destreg_write_src = destout
  // ID clear_branch     = branch_clear 
  // ID pc = program_counter
  sc_signal<bool>       pred_on("PRED_ON") ;
  sc_signal<unsigned >	branch_instruction_address("BR_INSTRUCTION_ADDRESS");
  // ID alu_dataout = dout from EXEC 
  sc_signal<signed>     dram_dataout("DRAM_DATAOUT") ;
  sc_signal<bool>       dram_rd_valid("DRAM_RD_VALID") ;
  sc_signal<unsigned>   dram_write_src("DRAM_WRITE_SRC");
  // ID next_pc     = next_pc
  // ID branch_valid = branch_valid
  // ID branch_target_address = branch_target_address
  sc_signal<bool>       mem_access("MEM_ACCESS") ;
  sc_signal<unsigned >    mem_address("MEM_ADDRESS") ;
  sc_signal<int>        alu_op("ALU_OP") ;
  sc_signal<bool>       mem_write("MEM_WRITE") ;
  sc_signal<unsigned>   alu_src("ALU_SRC") ;
  sc_signal<bool>       reg_write("REG_WRITE") ;
  sc_signal<signed int> src_A("SRC_A") ;
  sc_signal<signed int> src_B("SRC_B") ;
  sc_signal<bool>       forward_A("FORWARD_A") ;
  sc_signal<bool>       forward_B("FORWARD_B") ;
  // ID stall_fetch = stall_fetch
  sc_signal<bool>       decode_valid("DECODE_VALID") ;
  sc_signal<bool>       float_valid("FLOAT_VALID") ;
  sc_signal<bool>       mmx_valid("MMX_VALID") ;
  sc_signal<bool>       pid_valid("PID_VALID") ;
  sc_signal<signed>     pid_data("PID_DATA") ;

  // ************************ DCACHE  ***********************************
  sc_signal<signed>       mmic_datain("MMIC_DATAIN") ;	/* DCU: datain 	*/
  sc_signal<unsigned>     mmic_statein("MMIC_STATEIN") ;/* DCU: statein */
  sc_signal<bool>     	  mmic_cs("MMIC_CS") ;		/* DCU: cs 	*/
  sc_signal<bool>     	  mmic_we("MMIC_WE") ;		/* DCU: we 	*/
  sc_signal<unsigned >      mmic_addr("MMIC_ADDR") ; /* DCU: addr	*/
  sc_signal<unsigned>     mmic_dest("MMIC_DEST") ;	/* DCU: dest 	*/
  sc_signal<unsigned>     mmic_destout("MMIC_DESTOUT") ;/* DCU: destout */
  sc_signal<signed>       mmic_dataout("MMIC_DATAOUT") ;/* DCU: dataout */
  sc_signal<bool>         mmic_out_valid("MMIC_OUT_VALID") ;/* DCU: out_valid*/
  sc_signal<unsigned>     mmic_stateout("MMIC_STATEOUT") ;/* DCU: stateout */

  // ************************ Execute ***********************************
  // EXEC in_valid = decode_valid
  sc_signal<bool>   	in_valid("IN_VALID") ;
  // EXEC opcode = alu_op
  sc_signal<bool>   	negate("NEGATE") ;
  sc_signal<int>   	add1("ADD1") ;
  sc_signal<bool>   	shift_sel("SHIFT_SEL") ;
  // EXEC dina = src_A
  // EXEC dinb = src_B
  // EXEC dest = alu_src
  sc_signal<bool>   		c("C") ;
  sc_signal<bool>   		v("V") ;
  sc_signal<bool>   		z("Z") ;
  sc_signal<signed>   		dout("DOUT") ;
  sc_signal<bool>   		out_valid("OUTPUT_VALID") ;
  sc_signal<unsigned> 		destout("DESTOUT") ;

  // ************************ Floating point ******************************
  // FPU in_valid = float_valid
  // FPU opcode = alu_op
  // FPU floata = src_A
  // FPU floatb = src_B
  // FPU dest = alu_src
  sc_signal<signed> 		fdout("FDOUT") ;
  sc_signal<bool> 		fout_valid("FOUT_VALID") ;
  sc_signal<unsigned> 		fdestout("FDESTOUT") ;
  
  // ************************ PIC *****************************************
  sc_signal<bool> 		ireq0("IREQ0") ;
  sc_signal<bool> 		ireq1("IREQ1") ;
  sc_signal<bool> 		ireq2("IREQ2") ;
  sc_signal<bool> 		ireq3("IREQ3") ;
  // PIC cs = interrupt_ack
  // PIC intack_cpu = interrupt_ack
  sc_signal<bool> 		rd_wr("RD_WR") ;
  sc_signal<bool> 		intreq("INTREQ") ;
  sc_signal<unsigned> 		vectno("VECTNO") ;
  sc_signal<bool> 		intack("INTACK") ;
  sc_signal<bool> 		intack_cpu("INTACK_CPU") ;

  // ************************ MMX ***********************************
  // MMX mmx_valid = mmx_valid
  // MMX opcode = alu_op
  // MMX mmxa = src_A
  // MMX mmxb = src_B
  // MMX dest = dest
  // MMX mmxdout = fdout
  // MMX mmxout_valid = fpu_valid
  // MMX mmxdestout = fpu_destout 

  // ************************ DSP *****************************************
  sc_signal<int> 		dsp_in1("DPS_IN1");
  sc_signal<int> 		dsp_out1("DSP_OUT1");
  sc_signal<bool> 		dsp_data_valid("DSP_DATA_VALID");
  sc_signal<bool> 		dsp_input_valid("DSP_INPUT_VALID");
  sc_signal<bool> 		dsp_data_requested("DSP_DATA_REQUESTED");

  ////////////////////////////////////////////////////////////////////////////
  // 				MAIN PROGRAM 
  ////////////////////////////////////////////////////////////////////////////
  sc_clock clk("Clock", 1, SC_NS, 0.5, 0.0, SC_NS);

  printf("/////////////////////////////////////////////////////////////////////////\n");
  printf("//  This code is written at SYNOPSYS, Inc.\n");
  printf("/////////////////////////////////////////////////////////////////////////\n");
  printf("//  Module   : main of CPU Model\n");
  printf("//  Author   : Martin Wang\n");
  printf("//  Company  : SYNOPSYS, Inc.\n");
  printf("//  Purpose  : This is a simple CPU modeling using SystemC.\n");
  printf("//             Instruction Set Architecure defined by Martin Wang.\n");
  printf("//             \n");
  printf("//           SystemC (TM) Copyright (c) 1988-2001 by Synopsys, Inc.  \n");
  printf("//             \n");
  printf("/////////////////////////////////////////////////////////////////////////\n");
  cout << "// IN THIS MACHINE Integer is " << sizeof (int) << " bytes.\n";
  cout << "// IN THIS MACHINE Floating is " << sizeof (float) << " bytes.\n";
  cout << "// IN THIS MACHINE Double is " << sizeof (double) << " bytes.\n";
  printf("//     \n");
  printf("//     \n");
  printf("//                            .,,uod8B8bou,,.\n");
  printf("//                   ..,uod8BBBBBBBBBBBBBBBBRPFT?l!i:.\n");
  printf("//              ,=m8BBBBBBBBBBBBBBBRPFT?!||||||||||||||\n");
  printf("//              !...:!TVBBBRPFT||||||||||!!^^\"\"    ||||\n");
  printf("//              !.......:!?|||||!!^^\"\"'            ||||\n");
  printf("//              !.........||||        ###  #  #    ||||\n");
  printf("//              !.........||||  ###  #  #  #  #    ||||\n");
  printf("//              !.........|||| #     #  #  #  #    ||||\n");
  printf("//              !.........|||| #     # #   #  #    ||||\n");
  printf("//              !.........|||| #     ##    #  #    ||||\n");
  printf("//              !.........|||| #     #     ###     ||||\n");
  printf("//              `.........|||| #   # #            ,||||\n");
  printf("//               .;.......||||  ###          _.-!!|||||\n");
  printf("//        .,uodWBBBBb.....||||       _.-!!|||||||||!:'\n");
  printf("//     !YBBBBBBBBBBBBBBb..!|||:..-!!|||||||!iof68BBBBBb....\n");
  printf("//     !..YBBBBBBBBBBBBBBb!!||||||||!iof68BBBBBBRPFT?!::   `.\n");
  printf("//     !....YBBBBBBBBBBBBBBbaaitf68BBBBBBRPFT?!:::::::::     `.\n");
  printf("//     !......YBBBBBBBBBBBBBBBBBBBRPFT?!::::::;:!^\"`;:::       `.\n");
  printf("//     !........YBBBBBBBBBBRPFT?!::::::::::^''...::::::;         iBBbo.\n");
  printf("//     `..........YBRPFT?!::::::::::::::::::::::::;iof68bo.      WBBBBbo.\n");
  printf("//       `..........:::::::::::::::::::::::;iof688888888888b.     `YBBBP^'\n");
  printf("//         `........::88::::::::::::;iof688888888888888888888b.     `\n");
  printf("//           `......::81:::::;iof688888888888888888888888888888b.\n");
  printf("//             `....:::;iof688888888888888888888888888888888899fT!\n");
  printf("//               `..::!8888888888888888888888888888888899fT|!^\"'\n");
  printf("//                 `' !!988888888888888888888888899fT|!^\"'\n");
  printf("//                     `!!8888888888888888899fT|!^\"'\n");
  printf("//                       `!988888888899fT|!^\"'\n");
  printf("//                         `!9899fT|!^\"'\n");
  printf("//                           `!^\"'\n");
  printf("//     \n");
  printf("//     \n");
  printf("/////////////////////////////////////////////////////////////////////////\n\n\n");
  	

  fetch 	IFU("FETCH_BLOCK");
                IFU.init_param(delay_cycles);
		IFU << ram_dataout << branch_target_address << next_pc << branch_valid
		<< stall_fetch << intreq << vectno << bios_valid << icache_valid
		<< pred_fetch << pred_branch_address << pred_branch_valid << ram_cs << ram_we 
		<< addr << ram_datain << instruction << instruction_valid << program_counter 
		<< intack_cpu << branch_clear << pred_fetch_valid << reset << clk;

  decode 	IDU("DECODE_BLOCK");
		IDU << reset << instruction << pred_instruction << instruction_valid
		<< pred_inst_valid << out_valid << destout << dout << dram_dataout
		<< dram_rd_valid << destout << fdout << fout_valid << fdestout
	        << branch_clear << dsp_data_valid << program_counter << pred_on
		<< branch_instruction_address << next_pc << branch_valid 
		<< branch_target_address << mem_access << mem_address << alu_op
		<< mem_write << alu_src << reg_write << src_A << src_B << forward_A
		<< forward_B << stall_fetch << decode_valid << float_valid << mmx_valid
		<< pid_valid << pid_data << clk;

  exec 		IEU("EXEC_BLOCK");
		IEU << reset << decode_valid << alu_op << negate << add1 << shift_sel 
		<< src_A << src_B << forward_A << forward_B << alu_src << c << v << z
		<< dout << out_valid << destout << clk;

  floating 	FPU("FLOAT_BLOCK");		// order dependent
		FPU << float_valid << alu_op << src_A << src_B << alu_src 
		<< fdout << fout_valid << fdestout << clk;

  mmxu	 	MMXU("MMX_BLOCK");
		MMXU << mmx_valid << alu_op << src_A << src_B << alu_src
		<< fdout << fout_valid << fdestout << clk;

  bios 		BIOS("BIOS_BLOCK");  
                BIOS.init_param(delay_cycles);
		BIOS.datain(ram_datain);	// order independent
                BIOS.cs(ram_cs);
		BIOS.we(ram_we);
		BIOS.addr(addr);
		BIOS.dataout(ram_dataout);
		BIOS.bios_valid(bios_valid);
		BIOS.stall_fetch(stall_fetch);
		BIOS.CLK(clk);

  paging 	PAGING("PAGING_BLOCK");
		PAGING << ram_datain << ram_cs << ram_we << addr << icache_din 
		<< icache_validin << icache_stall << paging_dout << paging_csout 
		<< paging_weout << physical_address << ram_dataout << icache_valid
		<< stall_fetch << clk ;
  	
  icache 	ICACHE("ICACHE_BLOCK"); 
		ICACHE.init_param(delay_cycles);
		ICACHE << paging_dout << paging_csout << paging_weout 	
		<< physical_address << pid_valid << pid_data << icache_din << icache_validin 
		<< icache_stall << clk;

  dcache 	DCACHE("DCACHE_BLOCK");
		DCACHE.init_param(delay_cycles);
		DCACHE << mmic_datain << mmic_statein << mmic_cs << mmic_we << mmic_addr
		<< mmic_dest << mmic_destout << mmic_dataout << mmic_out_valid << mmic_stateout << clk;

  pic		APIC("PIC_BLOCK");
		APIC << ireq0 << ireq1 << ireq2 << ireq3 <<intack_cpu << rd_wr 
		<< intack_cpu << intreq << intack << vectno;

  time_t tbuffer = time(NULL);

  sc_start();

  cout << "Time for simulation = " << (time(NULL) - tbuffer) << endl;

  return 0;	/* this is necessary */
}