qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] New emulator: MIPS-user
@ 2005-02-09 18:49 McMullan, Jason
  2005-02-09 22:02 ` J. Mayer
  0 siblings, 1 reply; 6+ messages in thread
From: McMullan, Jason @ 2005-02-09 18:49 UTC (permalink / raw)
  To: qemu-devel


[-- Attachment #1.1: Type: text/plain, Size: 647 bytes --]


So, I'm working on converting my pure-emulation mips-user emulator
( http://www.sourceforge.net/projects/gehail ) to QEMU's dynamic
code generator system, and I was wondering if there's a document
that describes the general architecture, and:

a) What PARAM1..PARAM3 are, and where and where not to use them.

b) The proper way to use JUMP_TB()

c) The rules for creating a proper op.c file

d) etc.

Attached is the 'mips64.spec' file I'll be using to automatically
generate my op.c and translate.c, just so you know that there's real
code behind this.

-- 
Jason McMullan <jason.mcmullan@timesys.com>
TimeSys Corporation


[-- Attachment #1.2: mips64.spec --]
[-- Type: text/plain, Size: 43495 bytes --]


/* ABS.fmt Abs - Floating Point Absolute Value
 */

010001 fmt(5) 00000 fs(5) fd(5) 000101:
	StoreFPR(fd, fmt, float_abs(ValueFPR(fs, fmt)));

/* ADD Add Word
 */
000000 rs(5) rt(5) rd(5) 00000 100000:
	uint64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt]) ) {
		UNPREDICTABLE;
	}
	temp  = (bit(GPR[rs],31) << 32) | GPR[rs];
	temp += (bit(GPR[rt],31) << 32) | GPR[rt];
	if (bit(temp,32) != bit(temp,31)) {
		SignalException(IntegerOverflow);
	} else {
		GPR[rd] = sign_extend(temp, 32);
	}

/* ADDI Add immediate
 */
001000 rs(5) rt(5) immediate(16):
	uint64_t temp;
 	if (NotWordValue(GPR[rs])) {
		UNPREDICTABLE;
	}
	temp  = (bit(GPR[rs],31) << 32) | GPR[rs];
	temp += sign_extend(immediate,16);
	if (bit(temp,32) != bit(temp,31)) {
		SignalException(IntegerOverflow);
	} else {
		GPR[rt] = sign_extend(temp, 32);
	}

/* ADDIU Add immediate, unsigned
 */
001001 rs(5) rt(5) immediate(16):
	uint64_t temp;
 	if (NotWordValue(GPR[rs])) {
		UNPREDICTABLE;
	}
	temp = GPR[rs] + sign_extend(immediate, 16);
	GPR[rt] = sign_extend(temp, 32);

/* ADDU Add unsigned word
 */
000000 rs(5) rt(5) rd(5) 00000 100001:
	uint64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = GPR[rs] + GPR[rt];
	GPR[rd] = sign_extend(temp, 32);

/* ALNV.PS Floating point align
 */
010011 rs(5) ft(5) fs(5) fd(5) 011110:
	if (bits(GPR[rs],0,2) == 0) {
		StoreFPR(fd, PS, ValueFPR(fd, PS));
	} else if (bits(GPR[rs],0,2) != 4) {
		UNPREDICTABLE;
	} else if (BigEndianCPU) {
		StoreFPR(fd, PS, (bits(ValueFPR(fs, PS),0,31) << 32) | bits(ValueFPR(ft, PS), 32, 63));
	} else {
		StoreFPR(fd, PS, (bits(ValueFPR(ft, PS),0,31) << 32) | bits(ValueFPR(fs, PS), 32, 63));
	}

/* AND And
 */
000000 rs(5) rt(5) rd(5) 00000 100100:
	GPR[rd] = GPR[rs] & GPR[rt];

/* ANDI And Immediate
 */
001100 rs(5) rt(5) immediate(16):
	GPR[rt] = GPR[rs] & zero_extend(immediate, 16);

/* B Unconditional branch
 */
000100 00000 00000 offset(16):
	uint64_t target_offset;
	/* I: */   target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ PC = PC + target_offset - 4;

/* BAL Branch and Link
 */
000001 00000 10001 offset(16):
	uint64_t target_offset;
	/* I: */   target_offset = sign_extend(offset << 2, 18);
	           GPR[31] = PC + 4;
	NextInstruction();
	/* I+1: */ PC = PC + target_offset - 4;

/* BC1F/T Branch on FP False/True
 */
010001 01000 cc(3) 0 tf(1) offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition=FPConditionCode(cc) == tf;
		   target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BC1F/TL Branch on FP False/True Likely
 */
010001 01000 cc(3) 1 tf(1) offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition=FPConditionCode(cc) == tf;
		   target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BC2F/T Branch on COP2 False/True
 */
010010 01000 cc(3) 0 tf(1) offset(16):
	SignalException(Unimplemented);

/* BC2F/TL Branch on COP2 False/True Likely
 */
010001 01000 cc(3) 1 tf(1) offset(16):
	SignalException(Unimplemented);

/* BEQ Branch on Equal
 */
000100 rs(5) rt(5) offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = (GPR[rs] == GPR[rt]);
	           target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BEQL branch on Equal Likely
 */
010100 rs(5) rt(5) offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = (GPR[rs] == GPR[rt]);
		   target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BGEZ Branch on Equal or Greater Than Zero
 */
000001 rs(5) 00001 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] >= 0);
	           target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BGEZL Branch on Equal or Greater Than Zero Likely
 */
000001 rs(5) 00011 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] >= 0);
	           target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BGEZAL Branch on greater Than or Equal to Zero and Link
 */
000001 rs(5) 10001 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] >= 0);
	           target_offset = sign_extend(offset << 2, 18);
		   GPR[31] = PC + 4;
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }


/* BGEZALL Branch on greater Than or Equal to Zero and Link Likely
 */
000001 rs(5) 10011 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] >= 0);
	           target_offset = sign_extend(offset << 2, 18);
		   GPR[31] = PC + 4;
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }


/* BGTZ Branch on Greater Than Zero
 */
000111 rs(5) 00000 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] > 0);
	           target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BGTZL Branch on Greater Than Zero Likely
 */
010111 rs(5) 00000 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] > 0);
	           target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BLEZ Branch on Less Than or Equal to Zero
 */
000110 rs(5) 00000 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] <= 0);
	           target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BLEZL Branch on Less Than or Equal to Zero Likely
 */
010110 rs(5) 00000 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] <= 0);
	           target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BLTZ Branch on Less Than Zero
 */
000001 rs(5) 00000 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] < 0);
	           target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BLTZL Branch on Less Than Zero Likely
 */
000001 rs(5) 00010 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] < 0);
	           target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BLTZAL Branch on Less Than Zero and Link
 */
000001 rs(5) 10000 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] < 0);
	           target_offset = sign_extend(offset << 2, 18);
		   GPR[31] = PC + 4;
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }


/* BLTZALL Branch on Less Than Zero and Link Likely
 */
000001 rs(5) 10010 offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = ((int64_t)GPR[rs] < 0);
	           target_offset = sign_extend(offset << 2, 18);
		   GPR[31] = PC + 4;
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BNE Branch on Not Equal
 */
000101 rs(5) rt(5) offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = (GPR[rs] != GPR[rt]);
	           target_offset = sign_extend(offset << 2, 18);
	NextInstruction();
	/* I+1: */ if (condition) {
			PC = PC + target_offset - 4;
		   }

/* BNEL Branch on Not Equal Likely
 */
010101 rs(5) rt(5) offset(16):
	uint64_t target_offset;
	int condition;
	/* I: */   condition = (GPR[rs] != GPR[rt]);
		   target_offset = sign_extend(offset << 2, 18);
	/* I+1: */ if (condition) {
			NextInstruction();
			PC = PC + target_offset - 4;
		   }

/* BREAK Breakpoint
 */
000000 code(20) 001101:
	SignalException(Breakpoint);

/* C.cond.fmt Floating Point Compare
 */
010001 fmt(5) ft(5) fs(5) cc(3) 0 0 11 cond(4):
	int less, equal, unordered, condition;
	if (SNaN(ValueFPR(fs, fmt)) || SNaN(ValueFPR(ft, fmt)) ||
	    QNaN(ValueFPR(fs, fmt)) || QNaN(ValueFPR(ft, fmt))) {
		less = 0;
		equal = 0;
		unordered = 1;
		if (SNaN(ValueFPR(fs,fmt)) || SNaN(ValueFPR(ft, fmt)) ||
		    (bit(cond,3) && (QNaN(ValueFPR(fs, fmt) || QNaN(ValueFPR(ft, fmt)))))) {
		    SignalException(InvalidOperation);
		}
	} else {
		less = float_less_than(ValueFPR(fs, fmt),ValueFPR(ft, fmt));
		equal = float_equal_to(ValueFPR(fs, fmt),ValueFPR(ft, fmt));
		unordered = 0;
	}
	condition = (bit(cond,2) && less) || (bit(cond,1) && equal) || 
	            (bit(cond,0) && unordered);
	SetFPConditionCode(condition);

/* CACHE Perform Cache Operation
 */
101111 base(5) op(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	/* (pAddr, uncached) = AddressTranslation(vAddr, DataReadReference); */
	/* CacheOp(op, vAddr, pAddr); */

/* CEIL.L.fmt Fixed Point Ceiling Convert to Long Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 001010:
	StoreFPR(fd, L, ConvertFmt(ValueFPR(fs, fmt), fmt, L));

/* CEIL.W.fmt Floating Point Ceiling Convert to Word Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 001110:
	StoreFPR(fd, W, ConvertFmt(ValueFPR(fs, fmt), fmt, W));

/* CFC1 Move Control Word From Floating Point
 * This has to be before ADD.fmt.
 */
010001 00010 rt(5) fs(5) 00000 000000:
	uint32_t temp;
	if (fs == 0) {
		temp = FIR;
	} else if (fs == 25) {
		temp = (bits(FCSR,25,31) << 1) | bit(FCSR,23);
	} else if (fs == 26) {
		temp = (bits(FCSR,12,17) << 12) | (bits(FCSR,2,6) << 2);
	} else if (fs == 28) {
		temp = (bits(FCSR,7,11) << 7) | (bit(FCSR,24) << 2) | bits(FCSR,0,1);
	} else if (fs == 31) {
		temp = FCSR;
	} else {
		temp = 0;
	}
	GPR[rt] = sign_extend(temp, 32);

/* CFC2 Move Control Word From Coprocessor 2
 */
010010 00010 rt(5) Impl(16):
	/* GPR[rt] = sign_extend(CP2CCR[Impl], 32); */
	GPR[rt] = 0;

/* CLO/Z Count Leading Ones/Zeros in Word
 */
011100 rs(5) rt(5) rd(5) 00000 10000 one_zero(1):
	int temp, i;
	if (NotWordValue(GPR[rs])) {
		UNPREDICTABLE;
	}
	temp = 32;
	for (i = 31; i >= 0; i--) {
		if (bit(GPR[rs],i) != one_zero) {
			temp = 31 - i;
			break;
		}
	}
	GPR[rd] = temp;

/* COP2 Coprocessor Operation to Coprocessor 2
 */
010010 1 cofun(25): 
	SignalException(Unimplemented);

/* CTC1 Move Control Word To Floating Point
 */
010001 00110 rt(5) fs(5) 00000 000000:
	uint32_t temp;
	temp=bits(GPR[rt],0,31);
	if (fs == 25) {
		if (bits(temp,8,31) != 0) {
			UNPREDICTABLE;
		} else {
			FCSR = (bits(temp,1,7) << 25) | (bit(FCSR,24) << 24) | (bit(temp,0) << 23) | bits(FCSR,0,22);
		}
	} else if (fs == 26) {
		if (bits(temp,18,22) != 0) {
			UNPREDICTABLE;
		} else {
			FCSR = (bits(FCSR,18,31) << 18) | (bits(temp,12,17) << 12) | (bits(FCSR,7,11) << 7) | (bits(temp,2,6) << 2) | bits(FCSR,0,1);
		}
	} else if (fs == 28) {
		if (bits(temp,18,22) != 0) {
			UNPREDICTABLE;
		} else {
			FCSR = (bits(FCSR,25,31) << 25) | (bit(temp,2) << 24) | (bits(FCSR,12,23) << 12) | (bits(temp,7,11) << 7) | (bits(FCSR,2,6) << 2) | bits(temp,0,1);
		}
	} else if (fs == 31) {
		if (bits(temp,18,22) != 0) {
			UNPREDICTABLE;
		} else {
			FCSR = temp;
		}
	} else {
		UNPREDICTABLE;
	}

/* CTC2 Move Control Word to Coprocessor 2
 */
010010 00110 rt(5) Impl(16):
	/* CP2CCR[Impl] = bits(GPR[rt],0,31); */

/* CVT.D.fmt Floating Point Convert to Double Floating Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 100001:
	StoreFPR(fd, D, ConvertFmt(ValueFPR(fs, fmt), fmt, D));

/* CVT.L.fmt Floating Point Convert to Long Fixed Format 
 */
010001 fmt(5) 00000 fs(5) fd(5) 100101:
	StoreFPR(fd, L, ConvertFmt(ValueFPR(fs, fmt), fmt, L));

/* CVT.PS.S Floating Point Convert Pair to Paired Single
 */
010001 10000 ft(5) fs(5) fd(5) 100110:
	StoreFPR(fd, S, (ValueFPR(fs, S) << 32) | ValueFPR(ft, S));

/* CVT.S.fmt Floating Point Convert to Single Floating Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 100000:
	StoreFPR(fd, S, ConvertFmt(ValueFPR(fs, fmt), fmt, S));

/* CVT.S.PL Floating Point Convert Pair Lower to Single Floating Point
 */
010001 10110 00000 fs(5) fd(5) 101000:
	StoreFPR(fd, S, ConvertFmt(ValueFPR(fs, PS), PL, S));

/* CVT.S.PU Floating Point Convert Pair Upper to Single Floating Point
 */
010001 10110 00000 fs(5) fd(5) 100000:
	StoreFPR(fd, S, ConvertFmt(ValueFPR(fs, PS), PU, S));

/* CVT.W.fmt Floating Point Convert to Word Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 100100:
	StoreFPR(fd, W, ConvertFmt(ValueFPR(fs, fmt), fmt, W));

/* DADD Doubleword Add
 */
000000 rs(5) rt(5) rd(5) 00000 101100:
	uint64_t temp;
	int carry;
	temp = add_carry64(GPR[rs], GPR[rt], &carry);
	if (carry) {
		SignalException(IntegerOverflow);
	} else {
		GPR[rd] = temp;
	}

/* DADDI Doubleword Add Immediate
 */
011000 rs(5) rt(5) immediate(16):
	uint64_t temp;
	int carry;
	temp = add_carry64(GPR[rs], sign_extend(immediate, 16), &carry);
	if (carry) {
		SignalException(IntegerOverflow);
	} else {
		GPR[rt] = temp;
	}

/* DADDIU Doubleword Add Immediate Unsigned
 */
011001 rs(5) rt(5) immediate(16):
	GPR[rt] = GPR[rs] + sign_extend(immediate, 16);

/* DADDU Doubleword Add Unsigned
 */
000000 rs(5) rt(5) rd(5) 00000 101101:
	GPR[rd] = GPR[rs] + GPR[rt];

/* DCLO/Z Count Leading Ones/Zeros in Doubleword
 */
011100 rs(5) rt(5) rd(5) 00000 10010 is_one(1):
	int temp, i;
	temp = 64;
	for (i = 63; i >= 0; i--) {
		if (bit(GPR[rs],i) == is_one) {
			temp = 63 - i;
			break;
		}
	}
	GPR[rd] = temp;

/* DDIV Doubleword Divide
 */
000000 rs(5) rt(5) 00000 00000 011110:
	LO = (int64_t)GPR[rs] / (int64_t)GPR[rt];
	HI = (int64_t)GPR[rs] % (int64_t)GPR[rt];

/* DDIVU Doubleword Divide Unsigned
 */
000000 rs(5) rt(5) 00000 00000 011111:
	LO = (uint64_t)GPR[rs] / (uint64_t)GPR[rt];
	HI = (uint64_t)GPR[rs] % (uint64_t)GPR[rt];

/* DERET Debug Exception Return
 */
010000 1 0000 00000 00000 00000 011111:
	Debug.DM=0;
	Debug.IEXI=0;
	PC = DEPC;

/* DIV Divide Word
 */
000000 rs(5) rt(5) 00000 00000 011010:
	int64_t q,r;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	q = (int32_t)GPR[rs] / (int32_t)GPR[rt];
	r = (int32_t)GPR[rs] % (int32_t)GPR[rt];
	LO = sign_extend(q, 32);
	HI = sign_extend(r, 32);

/* DIV.fmt Floating Point Divide
 */
010001 fmt(5) ft(5) fs(5) fd(5) 000011:
	StoreFPR(fd, fmt, float_div(ValueFPR(fs, fmt),ValueFPR(ft, fmt)));

/* DIVU Divide Unsigned Word
 */
000000 rs(5) rt(5) 00000 00000 011011:
	uint32_t q,r;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	q = (uint32_t)GPR[rs] / (uint32_t)GPR[rt];
	r = (uint32_t)GPR[rs] % (uint32_t)GPR[rt];
	LO = sign_extend(q, 32);
	HI = sign_extend(r, 32);

/* DMFC0 Doubleword Move from Coprocessor 0
 */
010000 00001 rt(5) rd(5) 00000 000 sel(3):
	SignalException(Unimplemented);

/* DMFC1 Doubleword Move from Floting Point
 */
010001 00001 rt(5) fs(5) 00000 000000:
	GPR[rt] = ValueFPR(fs, UNINTERPRETED_DOUBLEWORD);

/* DMFC2 Doubleword Move from Coprocessor 2
 */
010010 00001 rt(5) Impl(16):
	SignalException(Unimplemented);

/* DMTC0 Doubleword Move to Coprocessor 0
 */
010000 00101 rt(5) rd(5) 00000 000 sel(3):
	SignalException(Unimplemented);

/* DMTC1 Doubleword Move to Floating Point
 */
010001 00101 rt(5) fs(5) 00000 000000:
	StoreFPR(fs, UNINTERPRETED_DOUBLEWORD, GPR[rt]);

/* DMTC2 Doubleword Move to Coprocessor 2
 */
010010 00101 rt(5) Impl(16):
	SignalException(Unimplemented);

/* DMULT Doubleword Multiply
 */
000000 rs(5) rt(5) 00000 00000 011100:
	mult64(GPR[rs],GPR[rt],&LO,&HI);

/* DMULTU Doubleword Multiply Unsigned
 */
000000 rs(5) rt(5) 00000 00000 011101:
	umult64(GPR[rs],GPR[rt],&LO,&HI);

/* DSLL Doubleword Shift Left Logical
 */
000000 00000 rt(5) rd(5) sa(5) 111000:
	GPR[rd] = GPR[rt] << sa;

/* DSLL32 Doubleword Shift Left Logical Plus 32
 */
000000 00000 rt(5) rd(5) sa(5) 111100:
	GPR[rd] = GPR[rt] << (32+sa);

/* DSLLV Doubleword Shift Left Logical Variable
 */
000000 rs(5) rt(5) rd(5) 00000 010100:
	GPR[rd] = GPR[rt] << bits(GPR[rs],0,5);

/* DSRA Doubleword Shift Right Arithmetic
 */
000000 00000 rt(5) rd(5) sa(5) 111011:
	GPR[rd] = ((int64_t)GPR[rt]) >> sa;

/* DSRA32 Doubleword Shift Right Arithmetic Plus 32
 */
000000 00000 rt(5) rd(5) sa(5) 111111:
	sa += 32;
	GPR[rd] = ((int64_t)GPR[rt]) >> sa;

/* DSRAV Doubleword Shift Right Arithmetic Variable
 */
000000 rs(5) rt(5) rd(5) 00000 010111:
	int sa;
	sa = bits(GPR[rs],0,5);
	GPR[rd] = ((int64_t)GPR[rt]) >> sa;

/* DSLR Doubleword Shift Right Logical
 */
000000 00000 rt(5) rd(5) sa(5) 111010:
	GPR[rd] = ((uint64_t)GPR[rt]) >> sa;

/* DSLR32 Doubleword Shift Right Logical Plus 32
 */
000000 00000 rt(5) rd(5) sa(5) 111110:
	sa += 32;
	GPR[rd] = ((uint64_t)GPR[rt]) >> sa;

/* DSRLV Doubleword Shift Right Logical Variable
 */
000000 rs(5) rt(5) rd(5) 00000 010110:
	int sa;
	sa = bits(GPR[rs],0,5);
	GPR[rd] = ((uint64_t)GPR[rt]) >> sa;

/* DSUB Doubleword Subtract
 */
000000 rs(5) rt(5) rd(5) 00000 101110:
	int carry;
	int64_t temp;
	temp = sub_carry64(GPR[rs],GPR[rt],&carry);
	if (carry) {
		SignalException(IntegerOverflow);
	} else {
		GPR[rd] = temp;
	}

/* DSUBU Doubleword Subtract Unsigned
 */
000000 rs(5) rt(5) rd(5) 00000 101111:
	GPR[rd] = GPR[rs] - GPR[rt];

/* ERET Exception Return
 */
010000 1 0000 00000 00000 00000 011000:
	uint64_t temp;
	if (Status.ERL == 1) {
		temp = ErrorEPC;
		Status.ERL = 0;
	} else {
		temp = EPC;
		Status.EXL = 0;
	}
	PC = temp;
	LLbit = 0;

/* FLOOR.L.fmt Floting Point Convert to Long Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 001011:
	StoreFPR(fd, L, ConvertFmt(ValueFPR(fs, fmt), fmt, L));

/* FLOOR.W.fmt Floating Point Floor Convert to Word Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 001111:
	StoreFPR(fd, W, ConvertFmt(ValueFPR(fs, fmt), fmt, W));

/* J Jump
 */
000010 instr_index(26):
	/* I: */
	NextInstruction();
	/* I+1: */ PC = (PC & ((1 << 28)-1)) | (instr_index << 2);

/* JAL Jump and Link
 */
000011 instr_index(26):
	/* I: */   GPR[31] = PC + 4;
	NextInstruction();
	/* I+1: */ PC = (PC & ((1 << 28)-1)) | (instr_index << 2);

/* JALR Jump and Link Register
 */
000000 rs(5) 00000 rd(5) hint(5) 001001:
	uint64_t temp;
	/* I: */   temp = GPR[rs];
		   GPR[rd] = PC + 4;
	NextInstruction();
	/* I+1: */ PC = temp;

/* JR Jump Register
 */
000000 rs(5) 00000 00000 hint(5) 001000:
	uint64_t temp;
	/* I: */   temp = GPR[rs];
	NextInstruction();
	/* I+1: */ PC=temp;

/* LB Load Byte
 */
100000 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + sign_extend(offset, 16);
	doubleword = LoadMemory(vAddr, BYTE);
	GPR[rt] = sign_extend(doubleword,8);

/* LBU Load Byte Unsigned
 */
100100 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	GPR[rt] = LoadMemory(vAddr, BYTE);

/* LD Load Doubleword
 */
110111 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,2) != 0) {
		SignalException(AddressError);
	}
	GPR[rt] = LoadMemory(vAddr, DOUBLEWORD);

/* LDC1 Load Doubleword to Floating Point
 */
110101 base(5) ft(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,2) != 0) {
		SignalException(AddressError);
	}
	StoreFPR(ft, UNINTERPRETED_DOUBLEWORD, LoadMemory(vAddr, DOUBLEWORD));

/* LDC2 Load Doubleword to Coprocessor 2
 */
110110 base(5) rt(5) offset(16):
	SignalException(Unimplemented);
	
/* LDL Load Doubleword Left
 */
011010 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	int byte;
	vAddr = GPR[base] + sign_extend(offset, 16);
	byte = bits(vAddr,0,2);
	doubleword = LoadMemory(vAddr, DOUBLEWORD);
	GPR[rt] = (bits(doubleword,0,7+8*byte) << (64-8*byte)) | (bits(GPR[rt],0,63-8*byte));

/* LDR Load Doubleword Right
 */
011011 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	int byte;
	vAddr = GPR[base] + sign_extend(offset, 16);
	byte = bits(vAddr,0,2);
	doubleword = LoadMemory(vAddr, DOUBLEWORD);
	GPR[rt] = (bits(GPR[rt],64-8*byte,63) << (64-8*byte))  | bits(doubleword,8*byte,63);

/* LDXC1 Load Doubleword Indexed to Floating Point
 */
010011 base(5) index(5) 00000 fd(5) 000001:	
	uint64_t vAddr;
	vAddr = GPR[base] + GPR[index];
	if (bits(vAddr,0,2) != 0) {
		SignalException(AddressError);
	}
	StoreFPR(fd, UNINTERPRETED_DOUBLEWORD, LoadMemory(vAddr, DOUBLEWORD));

/* LH Load Halfword
 */
100001 base(5) rt(5) offset(16):
	uint64_t vAddr, doubleword;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bit(vAddr,0) != 0) {
		SignalException(AddressError);
	}
	doubleword = LoadMemory(vAddr, HALFWORD);
	GPR[rt] = sign_extend(doubleword,16);

/* LHU Load Halfword Unsigned
 */
100101 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bit(vAddr,0) != 0) {
		SignalException(AddressError);
	}
	GPR[rt] = LoadMemory(vAddr, HALFWORD);

/* LL Load Linked Word
 */
110000 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	GPR[rt] = LoadMemory(vAddr, WORD);
	LLbit = 1;

/* LLD Load Linked Doubleword
 */
110100 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,2) != 0) {
		SignalException(AddressError);
	}
	GPR[rt] = LoadMemory(vAddr, DOUBLEWORD);
	LLbit = 1;

/* LUI Load Upper Immediate
 */
001111 00000 rt(5) immediate(16):
	GPR[rt] = sign_extend(immediate, 16) << 16;

/* LUXC1 Load Doubleword Indexed Unaligned to Floring Point
 */
010011 base(5) index(5) 00000 fd(5) 000101:
	uint64_t vAddr;
	vAddr = (GPR[base]+GPR[index]) & ~(7LL);
	StoreFPR(fd, UNINTERPRETED_DOUBLEWORD, LoadMemory(vAddr, DOUBLEWORD));

/* LW Load Word
 */
100011 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	doubleword = LoadMemory(vAddr, WORD);
	GPR[rt] = sign_extend(doubleword,32);

/* LWC1 Load Word to Floating Point
 */
110001 base(5) ft(5) offset(16):
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	doubleword = LoadMemory(vAddr, WORD);
	StoreFPR(ft, UNINTERPRETED_WORD, sign_extend(doubleword,32));

/* LWC2 Load Word to Coprocessor 2
 */
110010 base(5) rt(5) offset(16):
	SignalException(Unimplemented);

/* LWL Load Word Left
 */
100010 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	int byte;
	vAddr = GPR[base] + sign_extend(offset, 16);
	byte = WORD - bits(vAddr,0,1);
	doubleword = LoadMemory(vAddr, byte);
	doubleword = (bits(doubleword,0,31-8*byte) << (8*byte)) | bits(GPR[rt],0,8*byte);
	GPR[rt]=sign_extend(doubleword,32);
	
/* LWR Load Word Right
 */
100110 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	int byte,word;
	vAddr = GPR[base] + sign_extend(offset, 16);
	byte = bits(vAddr,0,1) + 1;
	doubleword = LoadMemory(vAddr & ~3, byte);
	doubleword = (bits(GPR[rt],8*byte,31) << (8*byte)) | bits(doubleword,0,8*byte);
	if (byte == WORD)
		sign_extend(doubleword,32);
	GPR[rt]=doubleword;
	
/* LWU Load Word Unsigned
 */
100111 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset,16);
	GPR[rt] = LoadMemory(vAddr, WORD);

/* LWXC1 Load Word Indexed to Floating Point
 */
010011 base(5) index(5) 00000 fd(5) 000000:
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + GPR[index];
	doubleword = LoadMemory(vAddr, WORD);
	StoreFPR(fd, UNINTERPRETED_DOUBLEWORD, sign_extend(doubleword, 32));

/* MADD Multiply and Add Word to Hi,Lo
 */
011100 rs(5) rt(5) 00000 00000 000000:
	uint64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = (bits(HI,0,31) << 32) | bits(LO,0,31);
	temp += mult32(bits(GPR[rs],0,31),bits(GPR[rt],0,31));
	HI = sign_extend(bits(temp,32,63),32);
	LO = sign_extend(bits(temp,0,31),32);

/* MADD.fmt Floating Point Multiply Add
 */
010011 fr(5) ft(5) fs(5) fd(5) 100 fmt(3):
	uint64_t vfr,vfs,vft;
	vfr = ValueFPR(fr, fmt);
	vfs = ValueFPR(fs, fmt);
	vft = ValueFPR(ft, fmt);
	StoreFPR(fd, fmt, float_add(float_mult(vfs,vft),vfr));

/* MADDU Multiply and Add Unsigned Word to Hi,Lo
 */
011100 rs(5) rt(5) 00000 00000 000001:
	uint64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = (bits(HI,0,31) << 32) | bits(LO,0,31);
	temp += umult64(bits(GPR[rs],0,31),bits(GPR[rt],0,31),&LO,&HI);
	HI = sign_extend(bits(temp,32,63), 32);
	LO = sign_extend(bits(temp,0,31), 32);

/* MFC0 Move from Coprocessor 0
 */
010000 00000 rt(5) rd(5) 00000 000 sel(3):
	SignalException(Unimplemented);

/* MFC1 Move from Coprocessor 1
 */
010001 00000 rt(5) fs(5) 00000 000000:
	uint64_t data;
	data = bits(ValueFPR(fs, UNINTERPRETED_WORD),0,31);
	GPR[rt] = sign_extend(data, 32);

/* MFC2 Move from Coprocessor 2
 */
010010 00000 rt(5) Impl(16):
	SignalException(Unimplemented);

/* MFHI Move from HI Register
 */
000000 00000 00000 rd(5) 00000 010000:
	GPR[rd] = HI;

/* MFLO Move From LO Register
 */
000000 00000 00000 rd(5) 00000 010010:
	GPR[rd] = LO;

/* MOV.fmt Floating Point Move
 */
010001 fmt(5) 00000 fs(5) fd(5) 000110:
	StoreFPR(fd, fmt, ValueFPR(fs, fmt));

/* MOVF/T Move Conditional on Floating Point False/True
 */
000000 rs(5) cc(3) 0 tf(1) rd(5) 00000 000001:
	if (FPConditionCode(cc) == tf) {
		GPR[rd] = GPR[rs];
	}

/* MOVF/T.fmt Floating Point Move Conditional on Floating Point False/True
 */
010001 fmt(5) cc(3) 0 tf(1) fs(5) fd(5) 010001:
	SignalException(Unimplemented);
	/* 
	if (fmt != PS) {
		if (FPConditionCode(cc) == 1) {
			StoreFPR(fd, fmt, ValueFPR(fs, fmt));
		}
	} else {
		int mask=0;
		if (FPConditionCode(cc+0) == 1) {
			mask |= 0xF0;
		}
		if (FPConditionCode(cc+1) == 1) {
			mask |= 0x0F;
		}
		StoreFPR(fd, PS, ByteMerge(mask, fd, fs));
	} */

/* MOVN Move Conditional on Not Zero
 */
000000 rs(5) rt(5) rd(5) 00000 001011:
	if (GPR[rt] != 0) {
		GPR[rd] = GPR[rs];
	}

/* MOVN.fmt Floating Point Move Conditional on Not Zero
 */
010001 fmt(5) rt(5) fs(5) fd(5) 010011:
	if (GPR[rt] != 0) {
		StoreFPR(fd, fmt, ValueFPR(fs, fmt));
	}

/* MOVZ Move Conditional on Zero
 */
000000 rs(5) rt(5) rd(5) 00000 001010:
	if (GPR[rt] == 0) {
		GPR[rd] = GPR[rs];
	}

/* MOVZ.fmt Floating Point Move Conditional on Zero
 */
010001 fmt(5) rt(5) fs(5) fd(5) 010010:
	if (GPR[rt] == 0) {
		StoreFPR(fd, fmt, ValueFPR(fs, fmt));
	}

/* MSUB Multiply and Subtract Word to Hi,Lo
 */
011100 rs(5) rt(5) 00000 00000 000100:
	int64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = (bits(HI,0,31)<<32) | bits(LO,0,31);
	temp -= mult32(bits(GPR[rs],0,31),bits(GPR[rt],0,31));
	HI = sign_extend(bits(temp,32,63),32);
	LO = sign_extend(bits(temp,0,31),32);

/* MSUB.fmt Floating Point Multiply Subtract
 */
010011 fr(5) ft(5) fs(5) fd(5) 101 fmt(3):
	float_t vfr,vft,vfs;
	vfr = ValueFPR(fr, fmt);
	vfs = ValueFPR(fs, fmt);
	vft = ValueFPR(ft, fmt);
	StoreFPR(fd, fmt, float_sub(float_mult(vfs,vft),vfr));

/* MSUBU Multiply and Subtract Word to Hi,Lo
 */
011100 rs(5) rt(5) 00000 00000 000101:
	uint64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = (bits(HI,0,31)<<32) | bits(LO,0,31);
	temp -= umult32(bits(GPR[rs],0,31),bits(GPR[rt],0,31));
	HI = sign_extend(bits(temp,32,63),32);
	LO = sign_extend(bits(temp,0,31),32);

/* MTC0 Move to Coprocessor 0
 */
010000 00100 rt(5) rd(5) 00000 000 sel(3):
	SignalException(Unimplemented);

/* MTC1 Move Word to Floating Point
 */
010001 00100 rt(5) fs(5) 00000 000000:
	StoreFPR(fs, UNINTERPRETED_WORD, bits(GPR[rt],0,31));

/* MTC2 Move Word to Coprocessor 2
 */
010010 00100 rt(5) Impl(16):
	SignalException(Unimplemented);

/* MTHI Move to HI Register
 */
000000 rs(5) 00000 00000 00000 010001:
	HI = GPR[rs];

/* MTLO Move to LO Register
 */
000000 rs(5) 00000 00000 00000 010011:
	LO = GPR[rs];

/* MUL Multiply Word to GPR
 */
011100 rs(5) rt(5) rd(5) 00000 000010:
	int32_t temp;
	if (NotWordValue(GPR[rt]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = mult32(bits(GPR[rs],0,31), bits(GPR[rt],0,31));
	GPR[rd] = sign_extend(temp,32);

/* MUL.fmt Floating Point Multiply
 */
010001 fmt(5) ft(5) fs(5) fd(5) 000010:
	StoreFPR(fd, fmt, float_mult(ValueFPR(fs, fmt), ValueFPR(ft, fmt)));

/* MULT Multiply Word
 */
000000 rs(5) rt(5) 00000 00000 011000:
	int64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = mult32(bits(GPR[rs],0,31), bits(GPR[rt],0,31));
	LO = sign_extend(bits(temp,0,31),32);
	HI = sign_extend(bits(temp,32,63),32);

/* MULTU Multiply Unsigned Word
 */
000000 rs(5) rt(5) 00000 00000 011001:
	int64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp = umult32(bits(GPR[rs],0,31), bits(GPR[rt],0,31));
	LO = sign_extend(bits(temp,0,31),32);
	HI = sign_extend(bits(temp,32,63),32);

/* NEG.fmt Floating Point Negate
 */
010001 fmt(5) 00000 fs(5) fd(5) 000111:
	StoreFPR(fd, fmt, float_negate(ValueFPR(fs, fmt)));

/* NMADD.fmt Floating Point Negative Multiply Add
 */
010011 fr(5) ft(5) fs(5) fd(5) 110 fmt(3):
	float_t vfr,vfs,vft;
	vfr = ValueFPR(fr, fmt);
	vfs = ValueFPR(fs, fmt);
	vft = ValueFPR(ft, fmt);
	StoreFPR(fd, fmt, float_negate(float_add(vfr,float_mult(vfs,vft))));

/* NMSUB.fmt Floating Point Negative Multiply Subtract
 */
010011 fr(5) ft(5) fs(5) fd(5) 111 fmt(3):
	float_t vfr,vfs,vft;
	vfr = ValueFPR(fr, fmt);
	vfs = ValueFPR(fs, fmt);
	vft = ValueFPR(ft, fmt);
	StoreFPR(fd, fmt, float_negate(float_sub(float_mult(vfs,vft),vfr)));

/* NOP No operation
 */
000000 00000 00000 00000 00000 000000:
	/* Do nothing */

/* NOR Not Or
 */
000000 rs(5) rt(5) rd(5) 00000 100111:
	GPR[rd] = ~(GPR[rs] | GPR[rt]);

/* OR Or
 */
000000 rs(5) rt(5) rd(5) 00000 100101:
	GPR[rd] = GPR[rs] | GPR[rt];

/* ORI Or Immediate
 */
001101 rs(5) rt(5) immediate(16):
	GPR[rt] = GPR[rs] | zero_extend(immediate,16);

/* PLL.PS Pair Lower Lower
 */
010001 10110 ft(5) fs(5) fd(5) 101100:
	StoreFPR(fd, PS, (bits(ValueFPR(fs, PS),0,31) << 32) | bits(ValueFPR(ft, PS),0,31));

/* PLU.PS Pair Lower Upper
 */
010001 10110 ft(5) fs(5) fd(5) 101101:
	StoreFPR(fd, PS, (bits(ValueFPR(fs, PS),0,31) << 32) | bits(ValueFPR(ft, PS),32,63));

/* PREF Prefetch
 */
110011 base(5) hint(5) offset(16):
	/* Do nothing */

/* PREFI Prefetch Indexed
 */
010011 base(5) index(5) hint(5) 00000 001111:
	/* Do nothing */

/* PUL.PS Pair Upper Lower
 */
010001 10110 ft(5) fs(5) fd(5) 101110:
	StoreFPR(fd, PS, (bits(ValueFPR(fs, PS),32,63) << 32) | bits(ValueFPR(ft, PS),0,31));

/* PUU.PS Pair Upper Upper
 */
010001 10110 ft(5) fs(5) fd(5) 101111:
	StoreFPR(fd, PS, (bits(ValueFPR(fs, PS),32,63) << 32) | bits(ValueFPR(ft, PS),32,63));

/* RECIP.fmt Reciprocal Approximation
 */
010001 fmt(5) 00000 fs(5) fd(5) 010101:
	StoreFPR(fd, fmt, float_recip(ValueFPR(fs, fmt)));

/* ROUND.L.fmt Floating point Round
 */
010001 fmt(5) 00000 fs(5) fd(5) 001000:
	StoreFPR(fd, L, ConvertFmt(ValueFPR(fd, fmt), fmt, L));

/* ROUND.W.fmt Floating point Round
 */
010001 fmt(5) 00000 fs(5) fd(5) 001100:
	StoreFPR(fd, W, ConvertFmt(ValueFPR(fd, fmt), fmt, W));

/* RSQRT.fmt Reciprocal Square Root Approximation
 */
010001 fmt(5) 00000 fs(5) fd(5) 010110:
	StoreFPR(fd, fmt, float_recip(float_sqr(ValueFPR(fs, fmt))));

/* SB Store Byte
 */
101000 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset,16);
	StoreMemory(vAddr, BYTE, GPR[rt]);

/* SC Store Conditional Word
 */
111000 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset,16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	if (LLbit) {
		StoreMemory(vAddr, BYTE, GPR[rt]);
	}
	GPR[rt] = LLbit;

/* SCD Store Conditional Doubleword
 */
111100 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset,16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	if (LLbit) {
		StoreMemory(vAddr, DOUBLEWORD, GPR[rt]);
	}
	GPR[rt] = LLbit;

/* SD Store Doubleword
 */
111111 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + sign_extend(offset,16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	doubleword = GPR[rt];
	StoreMemory(vAddr, DOUBLEWORD, doubleword);

/* SDBBP Software Debug Breakpoint
 */
011100 code(20) 111111:
	if (Debug.DM == 0) {
		SignalDebugBreakpointException();
	} else {
		SignalDebugModeBreakpointException();
	}

/* SDC1 Store Doubleword from Floating Point
 */
111101 base(5) ft(5) offset(16):
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + sign_extend(offset,16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	doubleword = ValueFPR(ft, UNINTERPRETED_DOUBLEWORD);
	StoreMemory(vAddr, DOUBLEWORD, doubleword);

/* SDC2 Store Doubleword from Coprocessor 2
 */
111110 base(5) rt(5) offset(16):
	SignalException(Unimplemented);

/* SDL Store Doubleword Left
 */
101100 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	int byte;
	vAddr = GPR[base] + sign_extend(offset,16);
	byte = bits(vAddr,0,2);
	doubleword = bits(GPR[rt],56-8*byte,63);
	StoreMemory(vAddr, DOUBLEWORD, doubleword);

/* SDR Store Doubleword Right
 */
101101 base(5) rt(5) offset(16):
	uint64_t vAddr,doubleword;
	int byte;
	vAddr = GPR[base] + sign_extend(offset,16);
	byte = bits(vAddr,0,2);
	doubleword = bits(GPR[rt],8*byte,63) << (8*byte);
	StoreMemory(vAddr, DOUBLEWORD, doubleword);

/* SDXC1 Store Doubleword Indexed from Floating Point
 */
010011 base(5) index(5) fs(5) 00000 001001:
	uint64_t vAddr,doubleword;
	vAddr = GPR[base] + GPR[index];
	if (bits(vAddr,0,2) != 0) {
		SignalException(AddressError);
	}
	doubleword = ValueFPR(fs, UNINTERPRETED_DOUBLEWORD);
	StoreMemory(vAddr, DOUBLEWORD, doubleword);

/* SH Store Halfword
 */
101001 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset,16);
	if (bit(vAddr,0) != 0) {
		SignalException(AddressError);
	}
	StoreMemory(vAddr, HALFWORD, GPR[rt]);

/* SLL Shift Word Left Logical
 */
000000 00000 rt(5) rd(5) sa(5) 000000:
	GPR[rd] = sign_extend(GPR[rt] << sa,32);

/* SLLV Shift Word Left Logical Variable
 */
000000 rs(5) rt(5) rd(5) 00000 000100:
	GPR[rd] = sign_extend(GPR[rt] << bits(GPR[rs],0,4),32);

/* SLT Set on Less Than
 */
000000 rs(5) rt(5) rd(5) 00000 101010:
	if ((int64_t)GPR[rs] < (int64_t)GPR[rt]) {
		GPR[rd] = 1;
	} else {
		GPR[rd] = 0;
	}

/* SLTI Set on Less Than Immediate
 */
001010 rs(5) rt(5) immediate(16):
	if ((int64_t)GPR[rs] < (int64_t)sign_extend(immediate, 16) ) {
		GPR[rt] = 1;
	} else {
		GPR[rt] = 0;
	}

/* SLTIU Set on Less Than Immediate Unsigned
 */
001011 rs(5) rt(5) immediate(16):
	if (GPR[rs] < sign_extend(immediate,16)) {
		GPR[rt] = 1;
	} else {
		GPR[rt] = 0;
	}

/* SLTU Set on Less than Unsigned
 */
000000 rs(5) rt(5) rd(5) 00000 101011:
	if (GPR[rs] < GPR[rt]) {
		GPR[rd] = 1;
	} else {
		GPR[rd] = 0;
	}

/* SQRT.fmt Floating Point Square Root
 */
010001 fmt(5) 00000 fs(5) fd(5) 000100:
	StoreFPR(fd, fmt, float_sqr(ValueFPR(fs, fmt)));

/* SRA Shift Word Right Arithmetic
 */
000000 00000 rt(5) rd(5) sa(5) 000011:
	uint64_t temp;
	if (NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	GPR[rd] = sign_extend(GPR[rt] >> sa,32-sa);

/* SRAV Shift Word Right Arithmetic Variable
 */
000000 rs(5) rt(5) rd(5) 00000 000111:
	int sa;
	uint64_t temp;
	if (NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	sa = bits(GPR[rs],0,4);
	GPR[rd] = sign_extend(GPR[rt] >> sa,32-sa);


/* SRL Shift Word Right Logical
 */
000000 00000 rt(5) rd(5) sa(5) 000010:
	if (NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	GPR[rd] = zero_extend(GPR[rt] >> sa,32-sa);

/* SRLV Shift Word Right Logical Variable
 */
000000 rs(5) rt(5) rd(5) 00000 000110:
	int sa;
	if (NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	sa = bits(GPR[rs],0,4);
	GPR[rd] = zero_extend(GPR[rt] >> sa,32-sa);

/* SUB Subtract Word
 */
000000 rs(5) rt(5) rd(5) 00000 100010:
	uint64_t temp;
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	temp  = (bit(GPR[rs],31) << 32) | bits(GPR[rs],0,31);
	temp -= (bit(GPR[rt],31) << 32) | bits(GPR[rt],0,31);
	if (bit(temp,32) != bit(temp,31)) {
		SignalException(IntegerOverflow);
	} else {
		GPR[rd] = sign_extend(temp,32);
	}

/* SUB.fmt Floating Point Subtract
 */
010001 fmt(5) ft(5) fs(5) fd(5) 000001:
	StoreFPR(fd, fmt, float_sub(ValueFPR(fs, fmt), ValueFPR(ft, fmt)));

/* SUBU Subtract Unsigned Word
 */
000000 rs(5) rt(5) rd(5) 00000 100011:
	if (NotWordValue(GPR[rs]) || NotWordValue(GPR[rt])) {
		UNPREDICTABLE;
	}
	GPR[rd] = sign_extend((int32_t)GPR[rs] - (int32_t)GPR[rt], 32);

/* SUXC1 Store Doubleword Indexed Unaligned from Floating Point
 */
010011 base(5) index(5) fs(5) 00000 001101:
	uint64_t vAddr, doubleword;
	vAddr = bits(GPR[base] + GPR[index],3,63) << 3;
	doubleword = ValueFPR(fs, UNINTERPRETED_DOUBLEWORD);
	StoreMemory(vAddr, DOUBLEWORD, doubleword);

/* SW Store Word
 */
101011 base(5) rt(5) offset(16):
	uint64_t vAddr;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	StoreMemory(vAddr, WORD, GPR[rt]);

		
/* SWC1 Store Word from Floating Point
 */
111001 base(5) ft(5) offset(16):
	uint64_t vAddr, doubleword;
	vAddr = GPR[base] + sign_extend(offset, 16);
	if (bits(vAddr,0,1) != 0) {
		SignalException(AddressError);
	}
	doubleword = ValueFPR(ft, UNINTERPRETED_WORD);
	StoreMemory(vAddr, WORD, doubleword);

/* SWC2 Store Word from Coprocessor 2
 */
111010 base(5) rt(5) offset(16):
	SignalException(Unimplemented);

/* SWL Store Word Left
 */
101010 base(5) rt(5) offset(16):
	uint64_t vAddr;
	int byte;
	vAddr = GPR[base] + sign_extend(offset, 16);
	byte = WORD - bits(vAddr,0,1);
	StoreMemory(vAddr, byte, GPR[rt] >> (8*(WORD-byte)));

/* SWR Store Word Right
 */
101110 base(5) rt(5) offset(16):
	uint64_t vAddr;
	int byte;
	vAddr = GPR[base] + sign_extend(offset, 16);
	byte = bits(vAddr,0,1) + 1;
	StoreMemory(vAddr & ~3, byte, GPR[rt] >> (8*(WORD-byte)));

/* SWXC1 Store Word Indexed from Floating Point
 */
010011 base(5) index(5) fs(5) 00000 001000:
	uint64_t vAddr, doubleword;
	vAddr = GPR[base] + GPR[index];
	if (bits(vAddr,0,2) != 0) {
		SignalException(AddressError);
	}
	doubleword = ValueFPR(fs, UNINTERPRETED_WORD);
	StoreMemory(vAddr, WORD, doubleword);

/* SYNC Synchonize Shared Memory
 */
000000 00000 00000 00000 stype(5) 001111:
	/* SyncOperation(stype); */

/* SYSCALL System Call
 */
000000 code(20) 001100:
	SignalException(SystemCall);

/* TEQ Trap if Equal
 */
000000 rs(5) rt(5) code(10) 110100:
	if (GPR[rs] == GPR[rt]) {
		SignalException(Trap);
	}

/* TEQI Trap if Equal Immediate
 */
000001 rs(5) 01100 immediate(16):
	if (GPR[rs] == sign_extend(immediate, 16)) {
		SignalException(Trap);
	}

/* TGE Trap if Greater or Equal
 */
000000 rs(5) rt(5) code(10) 110000:
	if ((int64_t)GPR[rs] >= (int64_t)GPR[rt]) {
		SignalException(Trap);
	}

/* TGEI Trap if Greater or Equal Immediate
 */
000001 rs(5) 01000 immediate(16):
	if ((int64_t)GPR[rs] >= (int64_t)sign_extend(immediate, 16)) {
		SignalException(Trap);
	}

/* TGEIU Trap if Greator or Equal Immediate Unsigned
 */
000001 rs(5) 01001 immediate(16):
	if (GPR[rs] >= sign_extend(immediate, 16)) {
		SignalException(Trap);
	}
	
/* TGEU Trap if Greater or Equal Unsigned
 */
000000 rs(5) rt(5) code(10) 110001:
	if (GPR[rs] >= GPR[rt]) {
		SignalException(Trap);
	}

/* TLBP Probe TLB for Matching Entry
 */
010000 1 0000 00000 00000 00000 001000:
	SignalException(Unimplemented);

/* TLBR Read Indexed TLB Entry
 */
010000 1 0000 00000 00000 00000 000001:
	SignalException(Unimplemented);

/* TLBWI Write Indexed TLB Entry
 */
010000 1 0000 00000 00000 00000 000010:
	SignalException(Unimplemented);

/* TLBWR Write Random TLB Entry
 */
010000 1 0000 00000 00000 00000 000110:
	SignalException(Unimplemented);

/* TLT Trap if Less Than
 */
000000 rs(5) rt(5) code(10) 110010:
	if ((int64_t)GPR[rs] < (int64_t)GPR[rt]) {
		SignalException(Trap);
	}

/* TLTI Trap if Less Than Immediate
 */
000001 rs(5) 01010 immediate(16):
	if ((int64_t)GPR[rs] < (int64_t)sign_extend(immediate, 16)) {
		SignalException(Trap);
	}

/* TLTIO Trap if Less Than Immediate Unsigned
 */
000001 rs(5) 01011 immediate(16):
	if (GPR[rs] < sign_extend(immediate, 16)) {
		SignalException(Trap);
	}

/* TLTU Trap if Less Than Unsigned
 */
000000 rs(5) rt(5) code(10) 110011:
	if (GPR[rs] < GPR[rt]) {
		SignalException(Trap);
	}

/* TNE Trap if Not Equal
 */
000000 rs(5) rt(5) code(10) 110110:
	if (GPR[rs] != GPR[rt]) {
		SignalException(Trap);
	}

/* TNEI Trap if Not Equal Immediate
 */
000001 rs(5) 01110 immediate(16):
	if (GPR[rs] != sign_extend(immediate, 16)) {
		SignalException(Trap);
	}

/* TRUNC.L.fmt Floating Point Truncate to Long Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 001001:
	StoreFPR(fd, L, ConvertFmt(ValueFPR(fs, fmt), fmt, L));

/* TRUNC.W.fmt Floating Point truncate to Word Fixed Point
 */
010001 fmt(5) 00000 fs(5) fd(5) 001101:
	StoreFPR(fd, W, ConvertFmt(ValueFPR(fs, fmt), fmt, W));

/* WAIT Enter Standby Mode
 */
010000 1 code(19) 100000:
	WaitForInterrupt(code);

/* XOR Exclusive Or
 */
000000 rs(5) rt(5) rd(5) 00000 100110:
	GPR[rd] = GPR[rs] ^ GPR[rt];

/* XORI Exclusive Or Immediate
 */
001110 rs(5) rt(5) immediate(16):
	GPR[rt] = GPR[rs] ^ zero_extend(immediate, 16);

/* ADD.fmt Add Float
 * This is at the end, because otherwise we miss some of the
 * "pull crud from FPU special registers" instructions.
 */
010001 fmt(5) ft(5) fs(5) fd(5) 000000:
	StoreFPR(fd, fmt, float_add(ValueFPR(fs, fmt),ValueFPR(ft, fmt)));



[-- Attachment #1.3: spec2c.pl --]
[-- Type: application/x-perl, Size: 2882 bytes --]

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] New emulator: MIPS-user
  2005-02-09 18:49 [Qemu-devel] New emulator: MIPS-user McMullan, Jason
@ 2005-02-09 22:02 ` J. Mayer
  2005-02-10  5:35   ` Ming-Ching Tiew
  2005-02-10 13:28   ` McMullan, Jason
  0 siblings, 2 replies; 6+ messages in thread
From: J. Mayer @ 2005-02-09 22:02 UTC (permalink / raw)
  To: qemu-devel

On Wed, 2005-02-09 at 19:48, McMullan, Jason wrote:
> So, I'm working on converting my pure-emulation mips-user emulator
> ( http://www.sourceforge.net/projects/gehail ) to QEMU's dynamic
> code generator system, and I was wondering if there's a document
> that describes the general architecture, and:
> 

I wrote a MIPS32 emulation for qemu (which is still not released because
of lack of time for debugging). It supports MIPS32 with MIPS r4k<x> MMU
and preliminary code for MIPS16. There is some preliminary support for
MIPS64 (just load and stores, for now).
I did load a linux kernel until the "unable to find init" panic message
using this code.
Would you like to see it to avoid duplicate effort ?
Note that I did a system emulation, with no user mode only support.
-- 
J. Mayer <l_indien@magic.fr>
Never organized

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] New emulator: MIPS-user
  2005-02-09 22:02 ` J. Mayer
@ 2005-02-10  5:35   ` Ming-Ching Tiew
  2005-02-10 13:28   ` McMullan, Jason
  1 sibling, 0 replies; 6+ messages in thread
From: Ming-Ching Tiew @ 2005-02-10  5:35 UTC (permalink / raw)
  To: qemu-devel


From: "J. Mayer" <l_indien@magic.fr>
To: <qemu-devel@nongnu.org>
Sent: Thursday, February 10, 2005 6:02 AM
Subject: Re: [Qemu-devel] New emulator: MIPS-user


> 
> I wrote a MIPS32 emulation for qemu (which is still not released because
> of lack of time for debugging). It supports MIPS32 with MIPS r4k<x> MMU
> and preliminary code for MIPS16. There is some preliminary support for
> MIPS64 (just load and stores, for now).
> I did load a linux kernel until the "unable to find init" panic message
> using this code.
> Would you like to see it to avoid duplicate effort ?
> Note that I did a system emulation, with no user mode only support.
> -- 

It will be good if it could emulate WRT54g or the related hardware used
by the those Linux-based firewall/router. Those hardware are based on MIPSEL.

Cheers

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] New emulator: MIPS-user
  2005-02-09 22:02 ` J. Mayer
  2005-02-10  5:35   ` Ming-Ching Tiew
@ 2005-02-10 13:28   ` McMullan, Jason
  2005-02-11 14:17     ` J. Mayer
  1 sibling, 1 reply; 6+ messages in thread
From: McMullan, Jason @ 2005-02-10 13:28 UTC (permalink / raw)
  To: J. Mayer; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 791 bytes --]

On Wed, 2005-02-09 at 23:02 +0100, J. Mayer wrote:
> I wrote a MIPS32 emulation for qemu (which is still not released because
> of lack of time for debugging). It supports MIPS32 with MIPS r4k<x> MMU
> and preliminary code for MIPS16. There is some preliminary support for
> MIPS64 (just load and stores, for now).
> I did load a linux kernel until the "unable to find init" panic message
> using this code.
> Would you like to see it to avoid duplicate effort ?
> Note that I did a system emulation, with no user mode only support.

That would be fantastic! I've already done the user-mode support code,
and I could flesh out the MIPS64 and FPU support.

Can you email me your code, or give me a URL?

-- 
Jason McMullan <jason.mcmullan@timesys.com>
TimeSys Corporation


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] New emulator: MIPS-user
  2005-02-10 13:28   ` McMullan, Jason
@ 2005-02-11 14:17     ` J. Mayer
       [not found]       ` <1108135188.15068.5.camel@localhost.localdomain>
  0 siblings, 1 reply; 6+ messages in thread
From: J. Mayer @ 2005-02-11 14:17 UTC (permalink / raw)
  To: McMullan, Jason; +Cc: qemu-devel

On Thu, 2005-02-10 at 14:26, McMullan, Jason wrote:
> On Wed, 2005-02-09 at 23:02 +0100, J. Mayer wrote:
> > I wrote a MIPS32 emulation for qemu (which is still not released because
> > of lack of time for debugging). It supports MIPS32 with MIPS r4k<x> MMU
> > and preliminary code for MIPS16. There is some preliminary support for
> > MIPS64 (just load and stores, for now).
> > I did load a linux kernel until the "unable to find init" panic message
> > using this code.
> > Would you like to see it to avoid duplicate effort ?
> > Note that I did a system emulation, with no user mode only support.
> 
> That would be fantastic! I've already done the user-mode support code,
> and I could flesh out the MIPS64 and FPU support.
> 
> Can you email me your code, or give me a URL?

As I was reworking some parts of this code, my current version may be
quite broken.
So, I'll take a close look this week-end and send you a snapshot.

Regards.

-- 
J. Mayer <l_indien@magic.fr>
Never organized

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] New emulator: MIPS-user
       [not found]       ` <1108135188.15068.5.camel@localhost.localdomain>
@ 2005-02-13 15:43         ` J. Mayer
  0 siblings, 0 replies; 6+ messages in thread
From: J. Mayer @ 2005-02-13 15:43 UTC (permalink / raw)
  To: Jason McMullan; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1778 bytes --]

On Fri, 2005-02-11 at 16:19, Jason McMullan wrote:
> On Fri, 2005-02-11 at 15:17 +0100, J. Mayer wrote:
> > As I was reworking some parts of this code, my current version may be
> > quite broken.
> > So, I'll take a close look this week-end and send you a snapshot.
> 
> Broken I can handle (my 'mips64.spec' was taken pretty much directly
>  from the manuals, so I can use it as a verification suite on your
> code).
> 
> Anyway, any start you already have would be good for me, even if it's
> just a reference.

Here's a snapshot of a quite outdated version of my mips emulation. But
this version is, I think, very near from the one that did boot Linux.
This will give an idea of how I did it.
Don't care too much about the CALL_FROM_TB macros, which are not
specially related to mips emulation.

What I did since this version is mainly:
- debugging
- remove quite all #ifdef, using a features field in the CPUMIPSState
structure.
- start implementing mips16 opcodes
- try using some generic micro-ops: the goal here is not to re-implement
the same simple micro-operations for all emulated targets. This is the
patch that isn't finished and broke my code...

The hardware implemented is very simple: it's just the interrupt
controler + a serial port. I also implemented MIPS R4Kc like MMU (which,
I think, is not completely finished/debugged in this version).
I didn't make anything to emulate mipsel targets. I only did big-endian
support, but little-endian is planned and would not be very hard to add.
I can't release the BIOS I used for my tests, as it's not open-source,
but one could patch yamon and make it boot (or start booting) Linux.

Here's the diff with the current qemu CVS + a bzip'ed tarball of all new
files.

-- 
J. Mayer <l_indien@magic.fr>
Never organized

[-- Attachment #2: target-mips.diff --]
[-- Type: text/x-patch, Size: 17246 bytes --]

Index: Makefile.target
===================================================================
RCS file: /cvsroot/qemu/qemu/Makefile.target,v
retrieving revision 1.57
diff -u -d -w -B -b -d -p -r1.57 Makefile.target
--- Makefile.target	10 Feb 2005 21:48:51 -0000	1.57
+++ Makefile.target	13 Feb 2005 15:23:30 -0000
@@ -78,13 +78,33 @@ PROGS+=$(QEMU_SYSTEM)
 endif
 endif # ARCH = i386
 
+ifeq ($(ARCH), amd64)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = amd64
+
+endif # TARGET_ARCH = ppc
+
+ifeq ($(TARGET_ARCH), mips)
+
+ifeq ($(ARCH), ppc)
+PROGS+=$(QEMU_SYSTEM)
+endif
+
+ifeq ($(ARCH), i386)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = i386
+
 ifeq ($(ARCH), x86_64)
 ifdef CONFIG_SOFTMMU
 PROGS+=$(QEMU_SYSTEM)
 endif
 endif # ARCH = x86_64
 
-endif # TARGET_ARCH = ppc
+endif # TARGET_ARCH = mips
 
 ifeq ($(TARGET_ARCH), sparc)
 
@@ -255,6 +275,10 @@ ifeq ($(TARGET_ARCH), ppc)
 LIBOBJS+= op_helper.o helper.o
 endif
 
+ifeq ($(TARGET_ARCH), mips)
+LIBOBJS+= op_helper.o helper.o
+endif
+
 ifeq ($(TARGET_BASE_ARCH), sparc)
 LIBOBJS+= op_helper.o helper.o
 endif
@@ -276,6 +300,9 @@ endif
 ifeq ($(findstring ppc, $(TARGET_ARCH) $(ARCH)),ppc)
 LIBOBJS+=ppc-dis.o
 endif
+ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips)
+LIBOBJS+=mips-dis.o
+endif
 ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
 LIBOBJS+=sparc-dis.o
 endif
@@ -333,6 +360,10 @@ VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o v
 VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
 endif
+ifeq ($(TARGET_ARCH), mips)
+VL_OBJS+= mips.o mips_r4k.o dma.o vga.o serial.o #ide.o ne2000.o pckbd.o
+VL_OBJS+= #i8259.o i8254.o fdc.o m48t59.o
+endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o fdc.o
 endif
@@ -422,6 +453,11 @@ op.o: op.c op_template.h op_mem.h
 op_helper.o: op_helper_mem.h
 endif
 
+ifeq ($(TARGET_ARCH), mips)
+op.o: op.c op_template.c op_mem.c
+op_helper.o: op_helper_mem.c
+endif
+
 mixeng.o: mixeng.c mixeng.h mixeng_template.h
 
 %.o: %.c
Index: configure
===================================================================
RCS file: /cvsroot/qemu/qemu/configure,v
retrieving revision 1.55
diff -u -d -w -B -b -d -p -r1.55 configure
--- configure	12 Feb 2005 18:58:00 -0000	1.55
+++ configure	13 Feb 2005 15:23:31 -0000
@@ -200,7 +200,7 @@ fi
 
 if test -z "$target_list" ; then
 # these targets are portable
-    target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu sparc64-softmmu"
+    target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu sparc64-softmmu mips-softmmu"
 # the following are Linux specific
     if [ "$linux" = "yes" ] ; then
         target_list="i386-user arm-user armeb-user sparc-user ppc-user sparc64-user $target_list"
@@ -228,7 +228,7 @@ fi
 else
 
 # if cross compiling, cannot launch a program, so make a static guess
-if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
+if test "$cpu" = "powerpc" -o "$cpu" = "powerpc64" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
     bigendian="yes"
 fi
 
@@ -575,6 +575,7 @@ target_bigendian="no"
 [ "$target_cpu" = "sparc" ] && target_bigendian=yes
 [ "$target_cpu" = "sparc64" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc" ] && target_bigendian=yes
+[ "$target_cpu" = "mips" ] && target_bigendian=yes
 target_softmmu="no"
 if expr $target : '.*-softmmu' > /dev/null ; then
   target_softmmu="yes"
@@ -635,6 +636,10 @@ elif test "$target_cpu" = "x86_64" ; the
   echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
   echo "#define TARGET_I386 1" >> $config_h
   echo "#define TARGET_X86_64 1" >> $config_h
+elif test "$target_cpu" = "mips" ; then
+  echo "TARGET_ARCH=mips" >> $config_mak
+  echo "#define TARGET_ARCH \"mips\"" >> $config_h
+  echo "#define TARGET_MIPS 1" >> $config_h
 else
   echo "Unsupported target CPU"
   exit 1
Index: cpu-all.h
===================================================================
RCS file: /cvsroot/qemu/qemu/cpu-all.h,v
retrieving revision 1.41
diff -u -d -w -B -b -d -p -r1.41 cpu-all.h
--- cpu-all.h	10 Feb 2005 21:56:58 -0000	1.41
+++ cpu-all.h	13 Feb 2005 15:23:31 -0000
@@ -616,6 +616,13 @@ void page_unprotect_range(uint8_t *data,
 #define cpu_gen_code cpu_ppc_gen_code
 #define cpu_signal_handler cpu_ppc_signal_handler
 
+#elif defined(TARGET_MIPS)
+#define CPUState CPUMIPSState
+#define cpu_init cpu_mips_init
+#define cpu_exec cpu_mips_exec
+#define cpu_gen_code cpu_mips_gen_code
+#define cpu_signal_handler cpu_mips_signal_handler
+
 #else
 
 #error unsupported target CPU
Index: cpu-exec.c
===================================================================
RCS file: /cvsroot/qemu/qemu/cpu-exec.c,v
retrieving revision 1.48
diff -u -d -w -B -b -d -p -r1.48 cpu-exec.c
--- cpu-exec.c	10 Feb 2005 22:04:41 -0000	1.48
+++ cpu-exec.c	13 Feb 2005 15:23:31 -0000
@@ -165,6 +165,7 @@ int cpu_exec(CPUState *env1)
     }
 #elif defined(TARGET_SPARC)
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_MIPS)
 #else
 #error unsupported target CPU
 #endif
@@ -203,6 +204,8 @@ int cpu_exec(CPUState *env1)
                                  env->exception_next_eip, 0);
 #elif defined(TARGET_PPC)
                     do_interrupt(env);
+#elif defined(TARGET_MIPS)
+                    do_interrupt(env);
 #elif defined(TARGET_SPARC)
                     do_interrupt(env->exception_index, 
                                  env->error_code);
@@ -285,6 +288,19 @@ int cpu_exec(CPUState *env1)
                             env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
 			}
                     }
+#elif defined(TARGET_MIPS)
+                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                        (env->CP0_Status & (1 << CP0St_IE)) &&
+                        (env->CP0_Cause & 0x0000FC00) &&
+                        !(env->hflags & MIPS_HFLAG_EXL) &&
+                        !(env->hflags & MIPS_HFLAG_ERL) &&
+                        !(env->hflags & MIPS_HFLAG_DM)) {
+                        /* Raise it */
+                        env->exception_index = EXCP_EXT_INTERRUPT;
+                        env->error_code = 0;
+                        do_interrupt(env);
+                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                    }
 #elif defined(TARGET_SPARC)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
 			do_interrupt(env->interrupt_index, 0);
@@ -333,6 +349,8 @@ int cpu_exec(CPUState *env1)
                     cpu_dump_state (env, logfile, fprintf, 0);
 #elif defined(TARGET_PPC)
                     cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_MIPS)
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #else
 #error unsupported target CPU 
 #endif
@@ -355,6 +373,10 @@ int cpu_exec(CPUState *env1)
                 flags = 0;
                 cs_base = 0;
                 pc = env->nip;
+#elif defined(TARGET_MIPS)
+                flags = env->hflags & MIPS_HFLAGS_TMASK;
+                cs_base = NULL;
+                pc = env->PC;
 #else
 #error unsupported CPU
 #endif
@@ -622,6 +663,7 @@ int cpu_exec(CPUState *env1)
     env->cpsr = compute_cpsr();
 #elif defined(TARGET_SPARC)
 #elif defined(TARGET_PPC)
+#elif defined(TARGET_MIPS)
 #else
 #error unsupported target CPU
 #endif
@@ -871,6 +913,57 @@ static inline int handle_cpu_signal(unsi
     /* never comes here */
     return 1;
 }
+
+#elif defined (TARGET_MIPS)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+    
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(address, pc, puc)) {
+        return 1;
+    }
+
+    /* see if it is an MMU fault */
+    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+    if (ret == 1) {
+#if 0
+        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
+               env->nip, env->error_code, tb);
+#endif
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+        sigprocmask(SIG_SETMASK, old_set, NULL);
+        do_raise_exception_err(env->exception_index, env->error_code);
+    } else {
+        /* activate soft MMU for this block */
+        cpu_resume_from_signal(env, puc);
+    }
+    /* never comes here */
+    return 1;
+}
+
 #else
 #error unsupported target CPU
 #endif
Index: dis-asm.h
===================================================================
RCS file: /cvsroot/qemu/qemu/dis-asm.h,v
retrieving revision 1.7
diff -u -d -w -B -b -d -p -r1.7 dis-asm.h
--- dis-asm.h	3 Jan 2005 23:35:10 -0000	1.7
+++ dis-asm.h	13 Feb 2005 15:23:32 -0000
@@ -404,6 +404,8 @@ extern int generic_symbol_at_address
 
 bfd_vma bfd_getl32 (const bfd_byte *addr);
 bfd_vma bfd_getb32 (const bfd_byte *addr);
+bfd_vma bfd_getl16 (const bfd_byte *addr);
+bfd_vma bfd_getb16 (const bfd_byte *addr);
 typedef enum bfd_boolean {false, true} boolean;
 
 #endif /* ! defined (DIS_ASM_H) */
Index: disas.c
===================================================================
RCS file: /cvsroot/qemu/qemu/disas.c,v
retrieving revision 1.19
diff -u -d -w -B -b -d -p -r1.19 disas.c
--- disas.c	31 Jan 2005 23:32:31 -0000	1.19
+++ disas.c	13 Feb 2005 15:23:32 -0000
@@ -108,6 +108,24 @@ bfd_vma bfd_getb32 (const bfd_byte *addr
   return (bfd_vma) v;
 }
 
+bfd_vma bfd_getl16 (const bfd_byte *addr)
+{
+  unsigned long v;
+
+  v = (unsigned long) addr[0];
+  v |= (unsigned long) addr[1] << 8;
+  return (bfd_vma) v;
+}
+
+bfd_vma bfd_getb16 (const bfd_byte *addr)
+{
+  unsigned long v;
+
+  v = (unsigned long) addr[0] << 24;
+  v |= (unsigned long) addr[1] << 16;
+  return (bfd_vma) v;
+}
+
 /* Disassemble this for me please... (debugging). 'flags' is only used
    for i386: non zero means 16 bit code */
 void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
@@ -142,6 +160,8 @@ void target_disas(FILE *out, target_ulon
     print_insn = print_insn_sparc;
 #elif defined(TARGET_PPC)
     print_insn = print_insn_ppc;
+#elif defined(TARGET_MIPS)
+    print_insn = print_insn_big_mips;
 #else
     fprintf(out, "Asm output not supported on this arch\n");
     return;
@@ -310,6 +330,8 @@ void monitor_disas(target_ulong pc, int 
     print_insn = print_insn_sparc;
 #elif defined(TARGET_PPC)
     print_insn = print_insn_ppc;
+#elif defined(TARGET_MIPS)
+    print_insn = print_insn_big_mips;
 #else
     term_printf("Asm output not supported on this arch\n");
     return;
Index: dyngen-exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/dyngen-exec.h,v
retrieving revision 1.20
diff -u -d -w -B -b -d -p -r1.20 dyngen-exec.h
--- dyngen-exec.h	26 Jan 2005 21:30:57 -0000	1.20
+++ dyngen-exec.h	13 Feb 2005 15:23:32 -0000
@@ -246,4 +246,28 @@ extern int __op_jmp0, __op_jmp1, __op_jm
 #define EXIT_TB() asm volatile ("rts")
 #endif
 
+#ifndef CALL_FROM_TB0
+#define CALL_FROM_TB0(func) func();
+#endif
+#ifndef CALL_FROM_TB1
+#define CALL_FROM_TB1(func, arg0) func(arg0);
+#endif
+#ifndef CALL_FROM_TB1_CONST16
+#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
+#endif
+#ifndef CALL_FROM_TB2
+#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
+#endif
+#ifndef CALL_FROM_TB2_CONST16
+#define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
+CALL_FROM_TB2(func, arg0, arg1);
+#endif
+#ifndef CALL_FROM_TB3
+#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
+#endif
+#ifndef CALL_FROM_TB4
+#define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
+        func(arg0, arg1, arg2, arg3);
+#endif
+
 #endif /* !defined(__DYNGEN_EXEC_H__) */
Index: elf.h
===================================================================
RCS file: /cvsroot/qemu/qemu/elf.h,v
retrieving revision 1.5
diff -u -d -w -B -b -d -p -r1.5 elf.h
--- elf.h	29 Apr 2003 21:06:46 -0000	1.5
+++ elf.h	13 Feb 2005 15:23:33 -0000
@@ -31,11 +31,29 @@ typedef int64_t  Elf64_Sxword;
 #define PT_LOPROC  0x70000000
 #define PT_HIPROC  0x7fffffff
 #define PT_MIPS_REGINFO		0x70000000
+#define PT_MIPS_OPTIONS		0x70000001
 
 /* Flags in the e_flags field of the header */
+/* MIPS architecture level. */
+#define EF_MIPS_ARCH_1		0x00000000	/* -mips1 code.  */
+#define EF_MIPS_ARCH_2		0x10000000	/* -mips2 code.  */
+#define EF_MIPS_ARCH_3		0x20000000	/* -mips3 code.  */
+#define EF_MIPS_ARCH_4		0x30000000	/* -mips4 code.  */
+#define EF_MIPS_ARCH_5		0x40000000	/* -mips5 code.  */
+#define EF_MIPS_ARCH_32		0x50000000	/* MIPS32 code.  */
+#define EF_MIPS_ARCH_64		0x60000000	/* MIPS64 code.  */
+
+/* The ABI of a file. */
+#define EF_MIPS_ABI_O32		0x00001000	/* O32 ABI.  */
+#define EF_MIPS_ABI_O64		0x00002000	/* O32 extended for 64 bit.  */
+
 #define EF_MIPS_NOREORDER 0x00000001
 #define EF_MIPS_PIC       0x00000002
 #define EF_MIPS_CPIC      0x00000004
+#define EF_MIPS_ABI2		0x00000020
+#define EF_MIPS_OPTIONS_FIRST	0x00000080
+#define EF_MIPS_32BITMODE	0x00000100
+#define EF_MIPS_ABI		0x0000f000
 #define EF_MIPS_ARCH      0xf0000000
 
 /* These constants define the different elf file types */
Index: exec-all.h
===================================================================
RCS file: /cvsroot/qemu/qemu/exec-all.h,v
retrieving revision 1.28
diff -u -d -w -B -b -d -p -r1.28 exec-all.h
--- exec-all.h	10 Feb 2005 22:02:59 -0000	1.28
+++ exec-all.h	13 Feb 2005 15:23:34 -0000
@@ -570,6 +570,8 @@ static inline target_ulong get_phys_addr
     is_user = ((env->hflags & HF_CPL_MASK) == 3);
 #elif defined (TARGET_PPC)
     is_user = msr_pr;
+#elif defined (TARGET_MIPS)
+    is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
 #elif defined (TARGET_SPARC)
     is_user = (env->psrs == 0);
 #else
Index: softmmu_header.h
===================================================================
RCS file: /cvsroot/qemu/qemu/softmmu_header.h,v
retrieving revision 1.8
diff -u -d -w -B -b -d -p -r1.8 softmmu_header.h
--- softmmu_header.h	3 Jan 2005 23:35:10 -0000	1.8
+++ softmmu_header.h	13 Feb 2005 15:23:34 -0000
@@ -55,6 +55,8 @@
 #define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
 #elif defined (TARGET_PPC)
 #define CPU_MEM_INDEX (msr_pr)
+#elif defined (TARGET_MIPS)
+#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
 #elif defined (TARGET_SPARC)
 #define CPU_MEM_INDEX ((env->psrs) == 0)
 #endif
@@ -66,6 +68,8 @@
 #define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
 #elif defined (TARGET_PPC)
 #define CPU_MEM_INDEX (msr_pr)
+#elif defined (TARGET_MIPS)
+#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
 #elif defined (TARGET_SPARC)
 #define CPU_MEM_INDEX ((env->psrs) == 0)
 #endif
Index: vl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.c,v
retrieving revision 1.120
diff -u -d -w -B -b -d -p -r1.120 vl.c
--- vl.c	10 Feb 2005 22:00:06 -0000	1.120
+++ vl.c	13 Feb 2005 15:23:35 -0000
@@ -2321,6 +2321,17 @@ int cpu_load(QEMUFile *f, void *opaque, 
 {
     return 0;
 }
+
+#elif defined(TARGET_MIPS)
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
+
 #elif defined(TARGET_SPARC)
 void cpu_save(QEMUFile *f, void *opaque)
 {
@@ -3376,10 +3387,11 @@ int main(int argc, char **argv)
 
     linux_boot = (kernel_filename != NULL);
         
+#if !defined(TARGET_MIPS) /* Don't have any disk on mips for now */
     if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
         fd_filename[0] == '\0')
         help();
-    
+#endif
     /* boot to cd by default if no hard disk */
     if (hd_filename[0] == '\0' && boot_device == 'c') {
         if (fd_filename[0] != '\0')
@@ -3645,6 +3657,10 @@ int main(int argc, char **argv)
     ppc_init(ram_size, vga_ram_size, boot_device,
 	     ds, fd_filename, snapshot,
 	     kernel_filename, kernel_cmdline, initrd_filename);
+#elif defined(TARGET_MIPS)
+    mips_init(ram_size, vga_ram_size, boot_device,
+              ds, fd_filename, snapshot,
+              kernel_filename, kernel_cmdline, initrd_filename);
 #elif defined(TARGET_SPARC)
     sun4m_init(ram_size, vga_ram_size, boot_device,
             ds, fd_filename, snapshot,

[-- Attachment #3: qemu-mips.tar.bz2 --]
[-- Type: application/x-bzip-compressed-tar, Size: 47910 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-02-13 15:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-09 18:49 [Qemu-devel] New emulator: MIPS-user McMullan, Jason
2005-02-09 22:02 ` J. Mayer
2005-02-10  5:35   ` Ming-Ching Tiew
2005-02-10 13:28   ` McMullan, Jason
2005-02-11 14:17     ` J. Mayer
     [not found]       ` <1108135188.15068.5.camel@localhost.localdomain>
2005-02-13 15:43         ` J. Mayer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).