Example #1
0
/* 
 * Description: 
 * 	Calls fetch and dispatches an instruction at the same cycle (if possible)
 * Inputs:
 *      trace: instruction trace with all the instructions executed
 * 	current_cycle: the cycle we are at
 * Returns:
 * 	None
 */
void fetch_To_dispatch(instruction_trace_t* trace, int current_cycle) {

    /* ECE552: YOUR CODE GOES HERE */
    /* ECE552 Assignment 3 - BEGIN CODE */

    if(instr_queue_size < INSTR_QUEUE_SIZE &&
        fetch_index <= sim_num_insn){
        instruction_t *currInstr = get_instr(trace, fetch_index);
        while(currInstr && (IS_TRAP(currInstr->op))){
            fetch_index++;
            currInstr = get_instr(trace, fetch_index); 
        }
        if(currInstr){
            currInstr->tom_dispatch_cycle = current_cycle;
            fetch(trace);
        }   
    }
    //Resolve target and source operand dependence
    //Set map table of r_out to tag which reservation
    //station will produce the result
    
    if(instr_front() && USES_FP_FU(instr_front()->op)){
        int i;
        for(i = 0; i < RESERV_FP_SIZE; i++){
            if(!reservFP[i]){
                reservFP[i] = instr_front();
                //Make sure we mark the existing raw dependences
                //BEFORE updating the map table with my target regs
                markRAWDependence(reservFP[i]);
                updateMapTable(reservFP[i]);
                instr_pop();
                break;
            }
        }
    }
    else if(instr_front() && (USES_INT_FU(instr_front()->op) || instr_front()->op == 0)){
        int i;
        for(i = 0; i < RESERV_INT_SIZE; i++){
            if(!reservINT[i]){
                reservINT[i] = instr_front();
                markRAWDependence(reservINT[i]);
                updateMapTable(reservINT[i]);
                instr_pop();
                break;
            }
        }
    }
    else if(instr_front() && 
            (IS_COND_CTRL(instr_front()->op) || 
             IS_UNCOND_CTRL(instr_front()->op))) {
        instr_pop();
    }
    return;
    /* ECE552 Assignment 3 - END CODE */

}
/*
 * The function looks through the trace and finds the next non trap instruction.
 */
instruction_t* get_next_non_trap_instr (instruction_trace_t* trace) {
  instruction_t* ret = NULL;
  while (fetch_index <= 1000000 && IS_TRAP(get_instr(trace, fetch_index)->op)) {
   fetch_index++;
  }
  if (fetch_index <= 1000000) {
    ret = get_instr(trace, fetch_index);
  }
  return ret;
}
int main()
{
    while(scanf("%s",mem),mem[0]!='8'){
        A = B = 0;
        ip = 0;
        while(get_instr(),instr!=8){
            switch(instr){
            case 0:f0();
                break;
            case 1:f1();
                break;
            case 2:f2();
                break;
            case 3:f3();
                break;
            case 4:f4();
                break;
            case 5:f5();
                break;
            case 6:f6();
                break;
            case 7:f7();
                break;
            }
        }
        printf("%s\n",mem);
    }
    return 0;
}
Example #4
0
/*
 * Write an ASCII disassembly of one instruction at "pc"
 * in "RAM" into "line" (max length "max_line"), return
 * number of bytes consumed.
 */
int
arch_pdp11_disasm_instr(cpu_t *cpu, addr_t pc, char *line, unsigned int max_line) {
	uint16_t opcode = cpu->RAM[pc];
	char line2[8];
	
	int addmode = get_addmode(opcode);

	if (addmode == ADDMODE_BRA) {
			snprintf(line2, sizeof(line2), "$%02" PRIX64, pc+2 + (int8_t)cpu->RAM[pc+1]);
	} else {
		switch (get_length(addmode)) {
			case 1:
				snprintf(line2, sizeof(line2), addmode_template[addmode], 0);
				break;
			case 2:
				snprintf(line2, sizeof(line2), addmode_template[addmode], cpu->RAM[pc+1]);
				break;
			case 3:
				snprintf(line2, sizeof(line2), addmode_template[addmode], cpu->RAM[pc+1] | cpu->RAM[pc+2]<<8);
				break;
			default:
				printf("Table error at %s:%d\n", __FILE__, __LINE__);
				exit(1);
		}
	}
	
	snprintf(line, max_line, "%s %s", mnemo[get_instr(opcode)], line2);
	return get_length(get_addmode(cpu->RAM[pc]));
}
Example #5
0
/* 
 * Description: 
 * 	Grabs an instruction from the instruction trace (if possible)
 * Inputs:
 *      trace: instruction trace with all the instructions executed
 * Returns:
 * 	None
 */
void fetch(instruction_trace_t* trace) {

    /* ECE552: YOUR CODE GOES HERE */
    /* ECE552 Assignment 3 - BEGIN CODE */
    //I have valid index 
    instruction_t *currInstr = get_instr(trace, fetch_index);
    instr_push(currInstr); 
    fetch_index++;
    //REMOVE THIS BEFORE SUBMISSION
    /* ECE552 Assignment 3 - END CODE */
}
Example #6
0
int execute_instruction(ARCH arch, uint word)
{
    int c;
    
    if ((c = get_instr(word)) == NO_MATCH)
        return NO_MATCH;

    DESC_ARRAY[c].execute(arch, word);

    return MATCH;
}
Example #7
0
int display_instruction(ARCH arch, uint word, FILE* stream)
{
    int c;

    if ((c = get_instr(word)) == NO_MATCH)
        return NO_MATCH;

    DESC_ARRAY[c].display(word, stream, arch);

    return MATCH;
}
Example #8
0
Value *
arch_pdp11_translate_cond(cpu_t *cpu, addr_t pc, BasicBlock *bb) {
	uint16_t opcode = cpu->RAM[pc];
LOG("%s:%d pc=%" PRIx64 " opcode=%x\n", __func__, __LINE__, pc, opcode);

	switch (get_instr(opcode)) {							// Sort it out.
		case INSTR_BEQ: /* Z */		return CC_EQ;
		case INSTR_BNE: /* !Z */	return CC_NE;
		case INSTR_BCS: /* C */		return CC_CS;
		case INSTR_BCC: /* !C */	return CC_CC;
		case INSTR_BMI: /* N */		return CC_MI;
		case INSTR_BPL: /* !N */	return CC_PL;
		case INSTR_BVS: /* V */		return CC_VS;
		case INSTR_BVC: /* !V */	return CC_VC;
		default:			return NULL; /* no condition; should not be reached */
	}
}
Example #9
0
int
arch_6502_tag_instr(cpu_t *cpu, addr_t pc, tag_t *tag, addr_t *new_pc, addr_t *next_pc) {
	uint8_t opcode = cpu->RAM[pc];

	switch (get_instr(opcode)) {
		case INSTR_BRK:
			*tag = TAG_TRAP;
			break;
		case INSTR_RTS:
			*tag = TAG_RET;
			break;
		case INSTR_JMP:
			if (get_addmode(opcode) == ADDMODE_ABS)
				*new_pc = cpu->RAM[pc+1] | cpu->RAM[pc+2]<<8;
			else 
				*new_pc = NEW_PC_NONE;	/* jmp indirect */
			*tag = TAG_BRANCH;
			break;
		case INSTR_JSR:
			*new_pc = cpu->RAM[pc+1] | cpu->RAM[pc+2]<<8;
			*tag = TAG_CALL;
			break;
		case INSTR_BCC:
		case INSTR_BCS:
		case INSTR_BEQ:
		case INSTR_BMI:
		case INSTR_BNE:
		case INSTR_BPL:
		case INSTR_BVC:
		case INSTR_BVS:
			*new_pc = pc+2 + (int8_t)cpu->RAM[pc+1];
			*tag = TAG_COND_BRANCH;
			break;
		default:
			//XXX only known instrunctions should be TAG_CONTINUE,
			//XXX all others should be TAG_TRAP
			*tag = TAG_CONTINUE;
			break;
	}
	int length = get_length(get_addmode(opcode));
	*next_pc = pc + length;
	return length;
}
Example #10
0
int
arch_pdp11_translate_instr(cpu_t *cpu, addr_t pc, BasicBlock *bb) {
	uint16_t opcode = cpu->RAM[pc];

//LOG("%s:%d PC=$%04X\n", __func__, __LINE__, pc);

	switch (get_instr(opcode)) {
		/* flags */
		case INSTR_CLC:	LET1(cpu->ptr_C, FALSE);				break;
		case INSTR_CLD:	LET1(ptr_D, FALSE);				break;
		case INSTR_CLI:	LET1(ptr_I, FALSE);				break;
		case INSTR_CLV:	LET1(cpu->ptr_V, FALSE);				break;
		case INSTR_SEC:	LET1(cpu->ptr_C, TRUE);				break;
		case INSTR_SED:	LET1(ptr_D, TRUE);				break;
		case INSTR_SEI:	LET1(ptr_I, TRUE);				break;

		/* register transfer */
		case INSTR_TAX:	SET_NZ(LET(X,R(A)));			break;
		case INSTR_TAY:	SET_NZ(LET(Y,R(A)));			break;
		case INSTR_TXA:	SET_NZ(LET(A,R(X)));			break;
		case INSTR_TYA:	SET_NZ(LET(A,R(Y)));			break;
		case INSTR_TSX:	SET_NZ(LET(X,R(S)));			break;
		case INSTR_TXS:	SET_NZ(LET(S,R(X)));			break;

		/* load */
		case INSTR_LDA:	SET_NZ(LET(A,OPERAND));			break;
		case INSTR_LDX:	SET_NZ(LET(X,OPERAND));			break;
		case INSTR_LDY:	SET_NZ(LET(Y,OPERAND));			break;

		/* store */
		case INSTR_STA:	STORE(R(A),LOPERAND);			break;
		case INSTR_STX:	STORE(R(X),LOPERAND);			break;
		case INSTR_STY:	STORE(R(Y),LOPERAND);			break;

		/* stack */
		case INSTR_PHA:	PUSH(R(A));						break;
		case INSTR_PHP:	PUSH(arch_flags_encode(cpu, bb));	break;
		case INSTR_PLA:	SET_NZ(LET(A,PULL));			break;
		case INSTR_PLP:	arch_flags_decode(cpu, PULL, bb);	break;

		/* shift */
		case INSTR_ASL:	SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, false));	break;
		case INSTR_LSR:	SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, false));	break;
		case INSTR_ROL:	SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, true));	break;
		case INSTR_ROR:	SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, true));	break;

		/* bit logic */
		case INSTR_AND:	SET_NZ(LET(A,AND(R(A),OPERAND)));			break;
		case INSTR_ORA:	SET_NZ(LET(A,OR(R(A),OPERAND)));			break;
		case INSTR_EOR:	SET_NZ(LET(A,XOR(R(A),OPERAND)));			break;
		case INSTR_BIT:	SET_NZ(OPERAND);							break;

		/* arithmetic */
		case INSTR_ADC:	SET_NZ(ADC(ptr_A, ptr_A, OPERAND, true, false));		break;
		case INSTR_SBC:	SET_NZ(ADC(ptr_A, ptr_A, COM(OPERAND), true, false));	break;
		case INSTR_CMP:	SET_NZ(ADC(NULL, ptr_A, COM(OPERAND), false, true));		break;
		case INSTR_CPX:	SET_NZ(ADC(NULL, ptr_X, COM(OPERAND), false, true));		break;
		case INSTR_CPY:	SET_NZ(ADC(NULL, ptr_Y, COM(OPERAND), false, true));		break;

		/* increment/decrement */
		case INSTR_INX:	SET_NZ(LET(X,INC(R(X))));			break;
		case INSTR_INY:	SET_NZ(LET(Y,INC(R(Y))));			break;
		case INSTR_DEX:	SET_NZ(LET(X,DEC(R(X))));			break;
		case INSTR_DEY:	SET_NZ(LET(Y,DEC(R(Y))));			break;

		case INSTR_INC:	SET_NZ(STORE(INC(OPERAND),LOPERAND));			break;
		case INSTR_DEC:	SET_NZ(STORE(DEC(OPERAND),LOPERAND));			break;
		
		/* control flow */
		case INSTR_JMP:
			if (get_addmode(opcode) == ADDMODE_IND) {
				Value *v = LOAD_RAM16(CONST32(OPERAND_16));
				new StoreInst(v, cpu->ptr_PC, bb);
			}
			break;
		case INSTR_JSR:	PUSH16(pc+2);						break;
		case INSTR_RTS:	STORE(ADD(PULL16, CONST16(1)), cpu->ptr_PC);	break;

		/* branch */
		case INSTR_BEQ:
		case INSTR_BNE:
		case INSTR_BCS:
		case INSTR_BCC:
		case INSTR_BMI:
		case INSTR_BPL:
		case INSTR_BVS:
		case INSTR_BVC:
			break;

		/* other */
		case INSTR_NOP:											break;
		case INSTR_BRK:	arch_6502_trap(cpu, pc, bb);			break;
		case INSTR_RTI:	arch_6502_trap(cpu, pc, bb);			break;
		case INSTR_XXX:	arch_6502_trap(cpu, pc, bb);			break;
	}

	return get_length(get_addmode(opcode));
}
Example #11
0
int main(int argc, char *argv[]) {
	if (argc < 2) {
		usage(argv[0]);
	}

	if ((fin = fopen(argv[1], "rb")) == 0) {
		fprintf(stderr, "Error: could not open file\n");
		exit(1);
	}

	BYTE *fbuf = (BYTE *) malloc(16 * sizeof(BYTE));
	pe = (PESTRUCT *) malloc(sizeof(PESTRUCT));

	parse_pe_header();

	printf("EP RVA: %.8X\n", pe->rvaep);
	printf("Code section RVA: %.8X\n", pe->rvacode);
	printf("Data section RVA: %.8X\n", pe->rvadata);
	printf("Image base: %.8X\n", pe->imagebase);
	printf("Size of code section: %.8X\n", pe->codesize);

	/* Get size of headers to know where code section starts */
	fseek(fin, pe->offset + 84, SEEK_SET);
	fgets(fbuf, 4, fin);
	pe->codeoffset = lendian(fbuf, 4);
	printf("Code section offset: %.8X\n", pe->codeoffset);

	/* Get OEP address */
	pe->oep = pe->imagebase + pe->rvacode;
	printf("OEP address: %.8X\n", pe->oep);

	printf("\n");	// Formatting

	/* Get max offset from total file size */
	fseek(fin, 0L, SEEK_END);
	pe->maxoffset = ftell(fin);

	fseek(fin, pe->codeoffset, SEEK_SET);	// Go to start of code section

	DWORD len;
	DWORD cur_addr = pe->oep;	// First instruction at OEP
	DWORD addr;
	int i;
	int quit = 0;

	/* Start parsing and outputting 50 instructions at a time, waiting for user input after each block */
	while (!feof(fin) && !quit) {
		printf(":");

		/* Wait for user input */
		int ch = _getch();
		printf("\b");	// Erase character
		switch (ch) {
		case KEY_ESC:	// Quit
		case 'q':
			quit = 1;
			break;
		case 'n':	// Next instruction
			print_instr(&cur_addr);
			break;
		case ' ':	// Next 32 instructions
			print_ninstr(&cur_addr, 50);
			break;
		case 'o':	// Go back to OEP
			printf("\r \n");	// Clear line
			printf("EP RVA: %.8X\n", pe->rvaep);
			printf("Code section RVA: %.8X\n", pe->rvacode);
			printf("Data section RVA: %.8X\n", pe->rvadata);
			printf("Image base: %.8X\n", pe->imagebase);
			printf("Size of code section: %.8X\n", pe->codesize);
			printf("Code section offset: %.8X\n", pe->codeoffset);
			printf("OEP address: %.8X\n", pe->oep);
			printf("\n");
			fseek(fin, pe->codeoffset, SEEK_SET);
			cur_addr = pe->oep;
			break;
		case 'g': {	// Go to specific address
			printf("\r \n");	// Clear line
			printf("Go to address: ");
			char getaddr[32];
			fgets(getaddr, sizeof(getaddr), stdin);	// Get input
			if (getaddr[0] == '\n' || getaddr[0] == '\r') { printf("\n"); break; }	// Blank input (cancel instruction)
			addr = strtol(getaddr, NULL, 16);	// Parse input address
			if (!print_instr(&addr)) break;	// Print the first instruction
			cur_addr = addr;
			break;
		}
		case 'f': {	// Follow instruction at specific address
			printf("\r \n");	// Clear line
			printf("Address of instruction to follow: ");
			char addrstr[32];
			fgets(addrstr, sizeof(addrstr), stdin);	// Get input
			if (addrstr[0] == '\n' || addrstr[0] == '\r') { printf("\n"); break; }	// Blank input (cancel instruction)
			addr = strtol(addrstr, NULL, 16);
			char *instr = get_instr(addr);
			if (!instr) break;	// Error
			printf("%.8X\t%s\n", addr, instr);	// Print instruction to follow
			printf("\t\tv\n");
			addr = parse_addr(instr);
			if (!print_instr(&addr)) break;
			cur_addr = addr;
			free(instr);
			break;
		}
		case 'd': {	// Dump data at specific address
			printf("\r \n");	// Clear line
			printf("Address to dump: ");
			char addrstr[32];
			fgets(addrstr, sizeof(addrstr), stdin);	// Get input
			if (addrstr[0] == '\n' || addrstr[0] == '\r') { printf("\n"); break; }	// Blank input (cancel instruction)
			addr = strtol(addrstr, NULL, 16);
			if (!valid_addr(addr)) {
				printf("Address out of bounds\n");
				break;
			}
			printf("Number of bytes to dump (default 16): ");
			char bytesstr[3];
			fgets(bytesstr, sizeof(bytesstr), stdin);
			int bytes = strtol(bytesstr, NULL, 10);
			if (bytes == 0) bytes = 16;
			if (bytes > DUMP_MAX) {
				printf("Too high\n");
				break;
			}
			print_dump(addr, bytes);
			printf("\n");	// Formatting
			break;
		}
		case 's': {	// Search for a string in .data, .rdata, and .rsrc sections (no unicode support)
			printf("\r \n");	// Clear line
			printf("Search for string: ");
			char searchstr[STRLEN_MAX];
			fgets(searchstr, sizeof(searchstr), stdin);	// Get input
			if (searchstr[0] == '\n' || searchstr[0] == '\r') { printf("\n"); break; }	// Blank input (cancel instruction)
			addr = find_string_addr(searchstr);	// Find address of string
			if (addr == 0) {
				printf("String not found\n");
			} else {
				print_dump_str(addr);	// Print dump of matched string
			}
			printf("\n");	// Formatting
			break;
		}
		case 'e': {	// Edit binary
			printf("\r \n");	// Clear line
			printf("Starting address for editing: ");
			char addrstr[32];
			fgets(addrstr, sizeof(addrstr), stdin);	// Get input
			if (addrstr[0] == '\n' || addrstr[0] == '\r') { printf("\n"); break; }	// Blank input (cancel instruction)
			addr = strtol(addrstr, NULL, 16);
			if (!valid_addr(addr)) {
				printf("Address out of bounds\n");
				break;
			}
			printf("Input hex bytes: ");
			char bytestr[STRLEN_MAX];
			fgets(bytestr, sizeof(bytestr), stdin);	// Get input
			char *edit_file = (char *) calloc(strlen(argv[1]) + 6, sizeof(char));
			strncpy(edit_file, argv[1], strlen(argv[1]) - 4);
			strcat(edit_file, "_edit.exe");	// Edited file name: inputfilename_edit.exe
			save_edits_to_file(fin, edit_file, addr, bytestr);
			printf("Edited file %s saved\n\n", edit_file);
			free(edit_file);
			break;
		}
		case 'h':	// Show help
		case '?':
			print_help();
			break;

		// Special keys
		case SPECIAL_KEY:
			ch = _getch();
			switch (ch) {
			case KEY_DOWN:	// Next instruction
				print_instr(&cur_addr);
				break;
			case KEY_PGDN:	// Next 32 instructions
				print_ninstr(&cur_addr, 50);
				break;
			case KEY_HOME:	// Go back to OEP
				printf("\r \n");	// Clear line
				printf("EP RVA: %.8X\n", pe->rvaep);
				printf("Code section RVA: %.8X\n", pe->rvacode);
				printf("Data section RVA: %.8X\n", pe->rvadata);
				printf("Image base: %.8X\n", pe->imagebase);
				printf("Size of code section: %.8X\n", pe->codesize);
				printf("Code section offset: %.8X\n", pe->codeoffset);
				printf("OEP address: %.8X\n", pe->oep);
				printf("\n");
				fseek(fin, pe->codeoffset, SEEK_SET);
				cur_addr = pe->oep;
				break;
			default:
				//printf("0x%X\n", ch);	// DEBUGGING
				break;
			}
			break;

		default:
			//printf("0x%X\n", ch);	// DEBUGGING
			break;
		}

		fflush(stdin);
	}

	free(fbuf);
	free(pe);

	fclose(fin);

	return 0;
}
Example #12
0
TEST(FirstPass, get_instr) {
    char a[] = "NAME: .string \"Linus\"";
    char b[] = ".data +7,-57,  17 , 9";
    char c[] = "DATA: .data +7,-57,  17 , 9";
    char d[] = ".entry HELLO";
    char e[] = ".extern HELLO";
    char f[] = "some nonsense and white bears ";
    char g[] = "MOV ax, 125";

    EXPECT_EQ(get_instr(a), string);
    EXPECT_EQ(get_instr(a), string);

    EXPECT_EQ(get_instr(b), data);
    EXPECT_EQ(get_instr(b), data);

    EXPECT_EQ(get_instr(c), data);
    EXPECT_EQ(get_instr(c), data);

    EXPECT_EQ(get_instr(d), entry);

    EXPECT_EQ(get_instr(e), extrn);

    EXPECT_EQ(get_instr(f), NONE);
    EXPECT_EQ(get_instr(f), NONE);

    EXPECT_EQ(get_instr(g), NONE);
    EXPECT_EQ(get_instr(g), NONE);
}
Example #13
0
/* XXX Note, this fuction does not currently handle faults from
 * vmalloc/vmaped'd memory. That should probably be in a separate
 * function anyway.
 */
int
l4_do_page_fault(unsigned long address, long access, struct pt_regs *regs)
{
	struct vm_area_struct * vma;
	struct mm_struct *mm = current->mm;
	int fault, si_code = SEGV_MAPERR;
	siginfo_t info;

	/* If we're in an interrupt context, or have no user context,
	   we must not take the fault.  */
	if (!mm) /* || in_interrupt()) */
		goto bad_area_nosemaphore;

	down_read(&mm->mmap_sem);
	vma = find_vma(mm, address);
	if (!vma)
		goto bad_area;
	if (vma->vm_start <= address)
		goto good_area;
	if (!(vma->vm_flags & VM_GROWSDOWN))
		goto bad_area;
	if (expand_stack(vma, address))
		goto bad_area;

	/* Ok, we have a good vm_area for this memory access, so
	   we can handle it.  */
 good_area:
	si_code = SEGV_ACCERR;
	if (/* LOAD */ access & 0x4) {
		/* Allow reads even for write/execute-only mappings */
		if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
			goto bad_area;
	} else if (/* FETCH */ access & 0x1) {
		if (!(vma->vm_flags & VM_EXEC))
			goto bad_area;
	} else {
		if (!(vma->vm_flags & VM_WRITE))
			goto bad_area;
	}

 survive:
	/* If for any reason at all we couldn't handle the fault,
	   make sure we exit gracefully rather than endlessly redo
	   the fault.  */

	fault = handle_mm_fault(mm, vma, address, access & 0x2);
	up_read(&mm->mmap_sem);

	switch (fault) {
		case VM_FAULT_MINOR:
			current->min_flt++;
			break;
 		case VM_FAULT_MAJOR:
			current->maj_flt++;
			break;
		case VM_FAULT_SIGBUS:
			goto do_sigbus;
		case VM_FAULT_OOM:
			goto out_of_memory;
#if 0
	/*
	 * Well, it's a good idea to have this here, but apparently
	 * handle_mm_fault() can return all sorts of weird stuff, which
	 * makes it unsuitable to put BUG() here. 	-gl
	 */
	      default:
		BUG();
#endif
	}
	return 0;

	/* Something tried to access memory that isn't in our memory map.
	   Fix it, but check if it's kernel or user first.  */
bad_area:
	up_read(&mm->mmap_sem);
	/* Check if it is at TASK_SIG_BASE */
#ifdef CONFIG_ARCH_ARM
	/*
	 * Binary patching for NPTL
	 *
	 * XXX ??? Better place this thing?
	 */
	if (user_mode(regs) && ((address & PAGE_MASK) == 0xffff0000)) {
#if 0
		printk("Fault at address 0x%lx pc = 0x%lx, "
		    "need rewrite\n", address, L4_MsgWord(&current_regs()->msg, 1));
#endif
		if (address == 0xffff0fe0) {
			L4_Msg_t msg;
			unsigned long pc = L4_MsgWord(&current_regs()->msg, 1);
			unsigned long lr, fpc;
			unsigned long instr, r;
			long offs;

			if (pc != 0xffff0fe0)
				goto bad_area_nosemaphore;

			L4_Copy_regs_to_mrs(task_thread_info(current)->user_tid);
			L4_StoreMRs(0, 16, &msg.msg[0]);
			lr = msg.msg[14];
			fpc = lr - 4;

			L4_CacheFlushAll();
			instr = get_instr(fpc);
			if (instr == -1UL) 
				goto bad_area_nosemaphore;

			if ((instr & 0x0f000000) == 0x0b000000) {
				offs = instr << 8;
				offs = offs >> 6;	/* ASR */

				fpc = (fpc + 8) + offs;
				instr = get_instr(fpc);
				if (instr == -1UL)
					goto bad_area_nosemaphore;

				if ((instr & 0xffffffff) == 0xe3e00a0f) {
					/* mvn r0, 0xf000 */

					/*
					 * Rewrite to load the 
					 * kernel_reserved[0] from the
				 	 * utcb.
					 *
					 * This requires L4 to cooperate
					 * with the ExReg() syscall.
					 */
					/* mov r0, #0xff000000 */
					r = set_instr(fpc, 0xe3a004ff);
					if (r == -1UL)
						goto bad_area_nosemaphore;
					fpc += 4;

					/* ldr r0, [r0, #0xff0] */
					r = set_instr(fpc, 0xe5900ff0);
					if (r == -1UL)
						goto bad_area_nosemaphore;
					fpc += 4;

					/* ldr r0, [r0, #56] */
					r = set_instr(fpc, 0xe5900038);
					if (r == -1UL)
						goto bad_area_nosemaphore;
					fpc += 4;

					/* mov pc, lr */
					r = set_instr(fpc, 0xe1a0f00e);
					if (r == -1UL) 
						goto bad_area_nosemaphore;
					L4_CacheFlushAll();

					msg.msg[0] = current_thread_info()->tp_value;
					msg.msg[15] = lr;
					L4_LoadMRs(0, 16, &msg.msg[0]);
					L4_Copy_mrs_to_regs(
					    task_thread_info(current)->user_tid);
					L4_MsgPutWord(&current_regs()->msg, 1,
					    lr);
					return 0;
				}
			} else if (instr == 0xe240f01f) {