Esempio n. 1
0
static void set_debug_next(uint32_t *next) {
    if (debug_next != NULL)
        RAM_FLAGS(debug_next) &= ~RF_EXEC_DEBUG_NEXT;
    if (next != NULL) {
        if (RAM_FLAGS(next) & RF_CODE_TRANSLATED)
            flush_translations();
        RAM_FLAGS(next) |= RF_EXEC_DEBUG_NEXT;
    }
    debug_next = next;
}
Esempio n. 2
0
File: mem.c Progetto: Pear0/firebird
void write_action(void *ptr) {
    uint32_t addr = phys_mem_addr(ptr);
    volatile uint32_t *flags = &RAM_FLAGS((size_t)ptr & ~3);
    if (*flags & RF_WRITE_BREAKPOINT) {
        if (!gdb_connected)
            emuprintf("Hit write breakpoint at %08x. Entering debugger.\n", addr);
        debugger(DBG_WRITE_BREAKPOINT, addr);
    }
#ifndef NO_TRANSLATION
    if (*flags & RF_CODE_TRANSLATED) {
        logprintf(LOG_CPU, "Wrote to translated code at %08x. Deleting translations.\n", addr);
        invalidate_translation(*flags >> RFS_TRANSLATION_INDEX);
    } else {
Esempio n. 3
0
void gdbstub_loop(void) {
	int addr;
	int length;
	char *ptr, *ptr1;
	void *ramaddr;
	unsigned long regbuf[NUMREGS];
	bool reply, set;
	
	while (1)	{
		remcomOutBuffer[0] = 0;

		ptr = getpacket();
		if (!ptr) {
			gdbstub_disconnect();
			return;
		}
		reply = true;
		switch (*ptr++) 	{
			case '?':
				send_stop_reply(SIGNAL_TRAP, NULL, 0);
				reply = false; // already done
				break;

			case 'g':  /* return the value of the CPU registers */
				get_registers(regbuf);
				ptr = remcomOutBuffer;
				ptr = mem2hex(regbuf, ptr, NUMREGS * sizeof(unsigned long)); 
				break;
		
			case 'G':  /* set the value of the CPU registers - return OK */
				hex2mem(ptr, regbuf, NUMREGS * sizeof(unsigned long));
				set_registers(regbuf);
				strcpy(remcomOutBuffer,"OK");
				break;
				
			case 'p': /* pn Read the value of register n */
				if (hexToInt(&ptr, &addr) && (size_t)addr < sizeof(regbuf)) {
					mem2hex(get_registers(regbuf) + addr, remcomOutBuffer, sizeof(unsigned long));
				} else {
					strcpy(remcomOutBuffer,"E01");
				}
				break;
				
			case 'P': /* Pn=r Write register n with value r */
				ptr = strtok(ptr, "=");
				if (hexToInt(&ptr, &addr)
					  && (ptr=strtok(NULL, ""))
					  && (size_t)addr < sizeof(regbuf)
					  // TODO hex2mem doesn't check the format
					  && hex2mem((char*)ptr, &get_registers(regbuf)[addr], sizeof(u32))
					  ) {
					set_registers(regbuf);
					strcpy(remcomOutBuffer, "OK");
				} else {
					strcpy(remcomOutBuffer,"E01");
				}
				break;
		
			case 'm':  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
				/* Try to read %x,%x */
				if (hexToInt(&ptr, &addr)
				    && *ptr++ == ','
				    && hexToInt(&ptr, &length)) {
					ramaddr = virt_mem_ptr(addr, length);
					if (!ramaddr || mem2hex(ramaddr, remcomOutBuffer, length))
						break;
					strcpy(remcomOutBuffer, "E03");
				}	else
					strcpy(remcomOutBuffer,"E01");
				break;
		
			case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA  */
				/* Try to read '%x,%x:' */
				if (hexToInt(&ptr, &addr)
				    && *ptr++ == ','
				    && hexToInt(&ptr, &length)
				    && *ptr++ == ':')	{
				  ramaddr = virt_mem_ptr(addr, length);
				  if (!ramaddr) {
				  	strcpy(remcomOutBuffer, "E03");
				  	break;
				  }
				  if (range_translated((u32)ramaddr, (u32)((char *)ramaddr + length)))
				  	flush_translations();
					if (hex2mem(ptr, ramaddr, length))
						strcpy(remcomOutBuffer, "OK");
					else
						strcpy(remcomOutBuffer, "E03");
				}	else
					strcpy(remcomOutBuffer, "E02");
				break;
		
			case 'S': /* Ssig[;AA..AA] Step with signal at address AA..AA(optional). Same as 's' for us. */
				ptr = strchr(ptr, ';'); /* skip the signal */
				if (ptr)
					ptr++;
			case 's': /* s[AA..AA]  Step at address AA..AA(optional) */
				cpu_events |= EVENT_DEBUG_STEP;
				goto parse_new_pc;
			case 'C': /* Csig[;AA..AA] Continue with signal at address AA..AA(optional). Same as 'c' for us. */
				ptr = strchr(ptr, ';'); /* skip the signal */
				if (ptr)
					ptr++;
			case 'c':    /* c[AA..AA]    Continue at address AA..AA(optional) */
parse_new_pc:
				if (ptr && hexToInt(&ptr, &addr)) {
					arm.reg[15] = addr;
				}
				return;
			case 'q':
				if (!strcmp("Offsets", ptr)) {
					sprintf(remcomOutBuffer, "Text=%x;Data=%x;Bss=%x",
						ndls_debug_alloc_block, ndls_debug_alloc_block,	ndls_debug_alloc_block);
				}
				break;
			case 'Z': /* 0|1|2|3|4,addr,kind  */
				set = true;
				goto z;
			case 'z': /* 0|1|2|3|4,addr,kind  */
				set = false;
			// kinds other than 4 aren't supported
z:
				ptr1 = ptr++;
				ptr = strtok(ptr, ","); 
				if (ptr && hexToInt(&ptr, &addr) && (ramaddr = virt_mem_ptr(addr & ~3, 4))) {
					u32 *flags = &RAM_FLAGS(ramaddr);
					switch (*ptr1) {
						case '0': // mem breakpoint
						case '1': // hw breakpoint
							if (set) {
								if (*flags & RF_CODE_TRANSLATED) flush_translations();
								*flags |= RF_EXEC_BREAKPOINT;
							} else
								*flags &= ~RF_EXEC_BREAKPOINT;
							break;
						case '2': // write watchpoint
						case '4': // access watchpoint
							if (set) *flags |= RF_WRITE_BREAKPOINT;
							else *flags &= ~RF_WRITE_BREAKPOINT;
							if (*ptr1 != 4)
								break;
						case '3': // read watchpoint, access watchpoint
							if (set) *flags |= RF_READ_BREAKPOINT;
							else *flags &= ~RF_READ_BREAKPOINT;
							break;
						default:
							goto reply;
					}
					strcpy(remcomOutBuffer, "OK");
				} else
					strcpy(remcomOutBuffer, "E01");
				break;
		}			/* switch */

reply:
		/* reply to the request */
		if (reply)
			putpacket(remcomOutBuffer);
	}
}
Esempio n. 4
0
void translate(uint32_t start_pc, uint32_t *start_insnp) {
    out = insn_bufptr;
    outj = jtbl_bufptr;
    uint32_t pc = start_pc;
    uint32_t *insnp = start_insnp;

    if (next_index >= MAX_TRANSLATIONS)
        error("too many translations");

    uint8_t *insn_start;
    int stop_here = 0;
    while (1) {
        if (out >= &insn_buffer[INSN_BUFFER_SIZE - 1000])
            error("Out of instruction space");
        if (outj >= &jtbl_buffer[sizeof jtbl_buffer / sizeof *jtbl_buffer])
            error("Out of jump table space");

        insn_start = out;

        if ((pc ^ start_pc) & ~0x3FF) {
            //printf("stopping translation - end of page\n");
            goto branch_conditional;
        }
        if (RAM_FLAGS(insnp) & (RF_EXEC_BREAKPOINT | RF_EXEC_DEBUG_NEXT | RF_EXEC_HACK | RF_CODE_TRANSLATED | RF_CODE_NO_TRANSLATE)) {
            //printf("stopping translation - at breakpoint %x (%x)\n", pc);
            goto branch_conditional;
        }
        uint32_t insn = *insnp;

        /* Condition code */
        int cond = insn >> 28;
        int jcc = JZ;
        uint8_t *cond_jmp_offset = NULL;
        switch (cond >> 1) {
            case 0: /* EQ (Z), NE (!Z) */
                emit_cmp_flag_immediate(&arm.cpsr_z, 0);
                break;
            case 1: /* CS (C), CC (!C) */
                emit_cmp_flag_immediate(&arm.cpsr_c, 0);
                break;
            case 2: /* MI (N), PL (!N) */
                emit_cmp_flag_immediate(&arm.cpsr_n, 0);
                break;
            case 3: /* VS (V), VC (!V) */
                emit_cmp_flag_immediate(&arm.cpsr_v, 0);
                break;
            case 4: /* HI (!Z & C), LS (Z | !C) */
                emit_mov_x86reg8_flag(AL, &arm.cpsr_z);
                emit_alu_x86reg8_flag(CMP, AL, &arm.cpsr_c);
                jcc = JAE; // execute if Z is less than C
                break;
            case 5: /* GE (N = V), LT (N != V) */
                emit_mov_x86reg8_flag(AL, &arm.cpsr_n);
                emit_alu_x86reg8_flag(CMP, AL, &arm.cpsr_v);
                jcc = JNZ;
                break;
            case 6: /* GT (!Z & N = V), LE (Z | N != V) */
                emit_mov_x86reg8_flag(AL, &arm.cpsr_n);
                emit_alu_x86reg8_flag(XOR, AL, &arm.cpsr_v);
                emit_alu_x86reg8_flag(OR, AL, &arm.cpsr_z);
                jcc = JNZ;
                break;
            case 7: /* AL */
                if (cond & 1) goto unimpl;
                goto no_condition;
        }
        /* If condition not met, jump around code.
         * (If ARM condition code is inverted, invert x86 code too) */
        emit_byte(jcc ^ (cond & 1));
        emit_byte(0);
        cond_jmp_offset = out;
no_condition:

        if ((insn & 0xE000090) == 0x0000090) {
            if ((insn & 0xFC000F0) == 0x0000090) {
                /* MUL, MLA - 32x32->32 multiplications */
                int left_reg  = insn & 15;
                int right_reg = insn >> 8 & 15;
                int acc_reg   = insn >> 12 & 15;
                int dest_reg  = insn >> 16 & 15;
                if (left_reg == 15 || right_reg == 15 || acc_reg == 15 || dest_reg == 15)
                    goto unimpl;

                emit_mov_x86reg_armreg(EAX, left_reg);
                emit_unary_armreg(MUL, right_reg);
                if (insn & 0x0200000)
                    emit_alu_x86reg_armreg(ADD, EAX, acc_reg);
                emit_mov_armreg_x86reg(dest_reg, EAX);

                if (insn & 0x0100000) {
                    if (!(insn & 0x0200000))
                        emit_test_x86reg_x86reg(EAX, EAX);
                    emit_setcc_flag(SETS, &arm.cpsr_n);
                    emit_setcc_flag(SETZ, &arm.cpsr_z);
                }
            } else if ((insn & 0xF8000F0) == 0x0800090) {
                /* UMULL, UMLAL, SMULL, SMLAL: 32x32 to 64 multiplications */
                uint32_t left_reg  = insn & 15;
                uint32_t right_reg = insn >> 8  & 15;
                uint32_t reg_lo    = insn >> 12 & 15;
                uint32_t reg_hi    = insn >> 16 & 15;

                if (left_reg == 15 || right_reg == 15 || reg_lo == 15 || reg_hi == 15)
                    goto unimpl;
                if (reg_lo == reg_hi)
                    goto unimpl;
                if (insn & 0x0100000) // set flags
                    goto unimpl;

                emit_mov_x86reg_armreg(EAX, left_reg);
                emit_unary_armreg((insn & 0x0400000) ? IMUL : MUL, right_reg);
                if (insn & 0x0200000) {
                    /* Accumulate */
                    emit_alu_armreg_x86reg(ADD, reg_lo, EAX);
                    emit_alu_armreg_x86reg(ADC, reg_hi, EDX);
                } else {
                    emit_mov_armreg_x86reg(reg_lo, EAX);
                    emit_mov_armreg_x86reg(reg_hi, EDX);
                }
            } else {
Esempio n. 5
0
bool emu_start(unsigned int port_gdb, unsigned int port_rdbg, const char *snapshot_file)
{
    gui_busy_raii gui_busy;

    if(snapshot_file)
    {
        // Open snapshot
        size_t snapshot_size = gzip_filesize(snapshot_file);
        if(snapshot_size < sizeof(emu_snapshot))
            return false;

        FILE *fp = fopen_utf8(snapshot_file, "rb");
        if(!fp)
            return false;

        int dupfd = dup(fileno(fp));
        fclose(fp);
        fp = nullptr;

        // gzdopen takes ownership of the fd
        gzFile gzf = gzdopen(dupfd, "r");
        if(!gzf)
        {
            close(dupfd);
            return false;
        }

        auto snapshot = (struct emu_snapshot *) malloc(snapshot_size);
        if(!snapshot)
        {
            gzclose(gzf);
            return false;
        }

        if((size_t) gzread(gzf, snapshot, snapshot_size) != snapshot_size)
        {
            gzclose(gzf);
            free(snapshot);
            return false;
        }
        gzclose(gzf);

        //sched_reset();
        sched.items[SCHED_THROTTLE].clock = CLOCK_27M;
        sched.items[SCHED_THROTTLE].proc = throttle_interval_event;

        // TODO: Max length
        path_boot1 = std::string(snapshot->path_boot1);
        path_flash = std::string(snapshot->path_flash);

        // TODO: Pass snapshot_size to flash_resume to avoid reading after the buffer

        // Resume components
        uint32_t sdram_size;
        if(snapshot->sig != SNAPSHOT_SIG
                || snapshot->version != SNAPSHOT_VER
                || !flash_resume(snapshot)
                || !flash_read_settings(&sdram_size, &product, &features, &asic_user_flags)
                || !cpu_resume(snapshot)
                || !memory_resume(snapshot)
                || !sched_resume(snapshot))
        {
            emu_cleanup();
            free(snapshot);
            return false;
        }
        free(snapshot);
    }
    else
    {
        if (!flash_open(path_flash.c_str()))
                return false;

        uint32_t sdram_size;
        flash_read_settings(&sdram_size, &product, &features, &asic_user_flags);

        flash_set_bootorder(boot_order);

        if(!memory_initialize(sdram_size))
        {
            emu_cleanup();
            return false;
        }
    }

    if(debug_on_start)
        cpu_events |= EVENT_DEBUG_STEP;

    uint8_t *rom = mem_areas[0].ptr;
    memset(rom, -1, 0x80000);
    for (int i = 0x00000; i < 0x80000; i += 4)
        RAM_FLAGS(&rom[i]) = RF_READ_ONLY;

    /* Load the ROM */
    FILE *f = fopen_utf8(path_boot1.c_str(), "rb");
    if (!f) {
        gui_perror(path_boot1.c_str());
        emu_cleanup();
        return false;
    }
    (void)fread(rom, 1, 0x80000, f);
    fclose(f);

#ifndef NO_TRANSLATION
    if(!translate_init())
    {
        gui_debug_printf("Could not init JIT, disabling translation.\n");
        do_translate = false;
    }
#endif

    addr_cache_init();

    throttle_timer_on();

    if(port_gdb)
        gdbstub_init(port_gdb);

    if(port_rdbg)
        rdebug_bind(port_rdbg);

    usblink_queue_reset();

    if(!snapshot_file)
        emu_reset();

    return true;
}