Пример #1
0
psim_halt(psim *system,
          int current_cpu,
          stop_reason reason,
          int signal)
{
    ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
    ASSERT(system->path_to_halt != NULL);
    system->last_cpu = current_cpu;
    system->halt_status.reason = reason;
    system->halt_status.signal = signal;
    if (current_cpu == system->nr_cpus) {
        system->halt_status.cpu_nr = 0;
        system->halt_status.program_counter =
            cpu_get_program_counter(system->processors[0]);
    }
    else {
        system->halt_status.cpu_nr = current_cpu;
        system->halt_status.program_counter =
            cpu_get_program_counter(system->processors[current_cpu]);
    }
    longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
}
Пример #2
0
deliver_hardware_interrupt(void *data)
{
  cpu *processor = (cpu*)data;
  interrupts *ints = cpu_interrupts(processor);
  ints->delivery_scheduled = NULL;
  if (cpu_registers(processor)->msr & msr_external_interrupt_enable) {
    /* external interrupts have a high priority and remain pending */
    if (ints->pending_interrupts & external_interrupt_pending) {
      unsigned_word cia = cpu_get_program_counter(processor);
      unsigned_word nia = perform_oea_interrupt(processor,
						cia, 0x00500, 0, 0, 0, 0);
      cpu_set_program_counter(processor, nia);
    }
    /* decrementer interrupts have a lower priority and are once only */
    else if (ints->pending_interrupts & decrementer_interrupt_pending) {
      unsigned_word cia = cpu_get_program_counter(processor);
      unsigned_word nia = perform_oea_interrupt(processor,
						cia, 0x00900, 0, 0, 0, 0);
      cpu_set_program_counter(processor, nia);
      ints->pending_interrupts &= ~decrementer_interrupt_pending;
    }
  }
}
Пример #3
0
psim_init(psim *system)
{
    int cpu_nr;

    /* scrub the monitor */
    mon_init(system->monitor, system->nr_cpus);

    /* trash any pending events */
    event_queue_init(system->events);

    /* if needed, schedule a halt event.  FIXME - In the future this
       will be replaced by a more generic change to psim_command().  A
       new command `schedule NNN halt' being added. */
    if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
        event_queue_schedule(system->events,
                             tree_find_integer_property(system->devices,
                                     "/openprom/options/max-iterations") - 2,
                             psim_max_iterations_exceeded,
                             system);
    }

    /* scrub all the cpus */
    for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
        cpu_init(system->processors[cpu_nr]);

    /* init all the devices (which updates the cpus) */
    tree_init(system->devices, system);

    /* and the emulation (which needs an initialized device tree) */
    os_emul_init(system->os_emulation, system->nr_cpus);

    /* now sync each cpu against the initialized state of its registers */
    for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
        cpu *processor = system->processors[cpu_nr];
        cpu_synchronize_context(processor, cpu_get_program_counter(processor));
        cpu_page_tlb_invalidate_all(processor);
    }

    /* force loop to start with first cpu */
    system->last_cpu = -1;
}
Пример #4
0
psim_read_register(psim *system,
                   int which_cpu,
                   void *buf,
                   const char reg[],
                   transfer_mode mode)
{
    register_descriptions description;
    char *cooked_buf;
    cpu *processor;

    /* find our processor */
    if (which_cpu == MAX_NR_PROCESSORS) {
        if (system->last_cpu == system->nr_cpus
                || system->last_cpu == -1)
            which_cpu = 0;
        else
            which_cpu = system->last_cpu;
    }
    ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);

    processor = system->processors[which_cpu];

    /* find the register description */
    description = register_description(reg);
    if (description.type == reg_invalid)
        return 0;
    cooked_buf = alloca (description.size);

    /* get the cooked value */
    switch (description.type) {

    case reg_gpr:
        *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
        break;

    case reg_spr:
        *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
        break;

    case reg_sr:
        *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
        break;

    case reg_fpr:
        *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
        break;

    case reg_pc:
        *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
        break;

    case reg_cr:
        *(creg*)cooked_buf = cpu_registers(processor)->cr;
        break;

    case reg_msr:
        *(msreg*)cooked_buf = cpu_registers(processor)->msr;
        break;

    case reg_fpscr:
        *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
        break;

    case reg_insns:
        *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
                                      which_cpu);
        break;

    case reg_stalls:
        if (cpu_model(processor) == NULL)
            error("$stalls only valid if processor unit model enabled (-I)\n");
        *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
        break;

    case reg_cycles:
        if (cpu_model(processor) == NULL)
            error("$cycles only valid if processor unit model enabled (-I)\n");
        *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
        break;

#ifdef WITH_ALTIVEC
    case reg_vr:
        *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
        break;

    case reg_vscr:
        *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
        break;
#endif

#ifdef WITH_E500
    case reg_gprh:
        *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
        break;

    case reg_evr:
        *(unsigned64*)cooked_buf = EVR(description.index);
        break;

    case reg_acc:
        *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
        break;
#endif

    default:
        printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
                        (unsigned long)processor, (unsigned long)buf, reg,
                        "read of this register unimplemented");
        break;

    }

    /* the PSIM internal values are in host order.  To fetch raw data,
       they need to be converted into target order and then returned */
    if (mode == raw_transfer) {
        /* FIXME - assumes that all registers are simple integers */
        switch (description.size) {
        case 1:
            *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
            break;
        case 2:
            *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
            break;
        case 4:
            *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
            break;
        case 8:
            *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
            break;
#ifdef WITH_ALTIVEC
        case 16:
            if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
            {
                union {
                    vreg v;
                    unsigned_8 d[2];
                } h, t;
                memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
                {
                    _SWAP_8(t.d[0] =, h.d[1]);
                }
                {
                    _SWAP_8(t.d[1] =, h.d[0]);
                }
                memcpy(buf/*dest*/, &t/*src*/, description.size);
                break;
            }
            else
                memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
            break;
#endif
        }
    }