| 
									
										
										
										
											2009-07-28 21:32:10 +00:00
										 |  |  | // Copyright (C) 2003 Dolphin Project.
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Additional copyrights go to Duddie and Tratax (c) 2004
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Multiplier and product register control
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DSPInterpreter.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DSPIntCCUtil.h"
 | 
					
						
							|  |  |  | #include "DSPIntUtil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace DSPInterpreter { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | // Only MULX family instructions have unsigned/mixed support.
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | inline s64 dsp_get_multiply_prod(u16 a, u16 b, u8 sign) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	s64 prod; | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | 	if ((sign == 1) && (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)) //unsigned
 | 
					
						
							|  |  |  | 		prod = (u64)a * (u64)b; | 
					
						
							|  |  |  | 	else if ((sign == 2) && (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)) //mixed
 | 
					
						
							|  |  |  | 		prod = (u64)a * (s64)(s16)b; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 		prod = (s64)(s16)a * (s64)(s16)b; //signed
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Conditionally multiply by 2.
 | 
					
						
							|  |  |  | 	if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0) | 
					
						
							|  |  |  | 		prod <<= 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return prod; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | inline s64 dsp_multiply(u16 a, u16 b, u8 sign = 0) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_get_multiply_prod(a, b, sign); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	return prod; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | inline s64 dsp_multiply_add(u16 a, u16 b, u8 sign = 0) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	return prod; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | inline s64 dsp_multiply_sub(u16 a, u16 b, u8 sign = 0) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_get_long_prod() -  dsp_get_multiply_prod(a, b, sign); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	return prod; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | inline s64 dsp_multiply_mulx(u8 axh0, u8 axh1, u16 val1, u16 val2) | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	s64 result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((axh0==0) && (axh1==0)) // axl.0 * axl.1
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		result = dsp_multiply(val1, val2, 1); // unsigned support ON if both ax?.l regs are used
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if ((axh0==0) && (axh1==1)) // axl.0 * axh.1
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if ((val1 >= 0x8000) && (val2 >= 0x8000))  | 
					
						
							|  |  |  | 			result = dsp_multiply(val1, val2, 2); | 
					
						
							|  |  |  | 		else if ((val1 >= 0x8000) && (val2 < 0x8000)) | 
					
						
							|  |  |  | 			result = dsp_multiply(val1, val2, 1); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			result = dsp_multiply(val1, val2, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if ((axh0==1) && (axh1==0)) // axh.0 * axl.1
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if ((val2 >= 0x8000) && (val1 >= 0x8000)) | 
					
						
							|  |  |  | 			result = dsp_multiply(val2, val1, 2); | 
					
						
							|  |  |  | 		else if ((val2 >= 0x8000) && (val1 < 0x8000)) | 
					
						
							|  |  |  | 			result = dsp_multiply(val2, val1, 1); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			result = dsp_multiply(val2, val1, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else // axh.0 * axh.1
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		result = dsp_multiply(val1, val2, 0); // unsigned support OFF if both ax?.h regs are used
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //----
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // CLRP
 | 
					
						
							|  |  |  | // 1000 0100 xxxx xxxx
 | 
					
						
							|  |  |  | // Clears product register $prod.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void clrp(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	// Magic numbers taken from duddie's doc
 | 
					
						
							|  |  |  | 	// These are probably a bad idea to put here.
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-01-13 00:11:29 +00:00
										 |  |  | 	g_dsp.r[DSP_REG_PRODL] = 0x0000; | 
					
						
							|  |  |  | 	g_dsp.r[DSP_REG_PRODM] = 0xfff0; | 
					
						
							|  |  |  | 	g_dsp.r[DSP_REG_PRODH] = 0x00ff; | 
					
						
							|  |  |  | 	g_dsp.r[DSP_REG_PRODM2] = 0x0010; | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2010-01-13 00:11:29 +00:00
										 |  |  | 	// 00ff_(fff0 + 0010)_0000 = 0100_0000_0000, conveniently, lower 40bits = 0
 | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	dsp_set_long_prod(0); // if we are doing it wrong then let's be consistent
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | // TSTPROD
 | 
					
						
							|  |  |  | // 1000 0101 xxxx xxxx
 | 
					
						
							|  |  |  | // Test prod regs value.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void tstprod(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	s64 prod = dsp_get_long_prod(); | 
					
						
							|  |  |  | 	Update_SR_Register64(prod); | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //----
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // MOVP $acD
 | 
					
						
							|  |  |  | // 0110 111d xxxx xxxx
 | 
					
						
							|  |  |  | // Moves multiply product from $prod register to accumulator $acD register.
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void movp(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 dreg = (opc >> 8) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(dreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(acc); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MOVNP $acD
 | 
					
						
							|  |  |  | // 0111 111d xxxx xxxx 
 | 
					
						
							|  |  |  | // Moves negative of multiply product from $prod register to accumulator
 | 
					
						
							|  |  |  | // $acD register.
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void movnp(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 dreg = (opc >> 8) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 acc = -dsp_get_long_prod(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(dreg, acc); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	Update_SR_Register64(acc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MOVPZ $acD
 | 
					
						
							|  |  |  | // 1111 111d xxxx xxxx
 | 
					
						
							|  |  |  | // Moves multiply product from $prod register to accumulator $acD
 | 
					
						
							|  |  |  | // register and sets $acD.l to 0
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void movpz(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 dreg = (opc >> 8) & 0x01; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod_round_prodl(); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(dreg, acc); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	Update_SR_Register64(acc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | // ADDPAXZ $acD, $axS
 | 
					
						
							|  |  |  | // 1111 10sd xxxx xxxx
 | 
					
						
							|  |  |  | // Adds secondary accumulator $axS to product register and stores result
 | 
					
						
							|  |  |  | // in accumulator register. Low 16-bits of $acD ($acD.l) are set to 0.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void addpaxz(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2010-02-22 00:22:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 dreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 9) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-02-22 00:22:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | 	s64 oldprod = dsp_get_long_prod(); | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 prod = dsp_get_long_prod_round_prodl(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 ax = dsp_get_long_acx(sreg); | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | 	s64 res = prod + (ax & ~0xffff); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | 	dsp_set_long_acc(dreg, res); | 
					
						
							|  |  |  | 	res = dsp_get_long_acc(dreg); | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | 	Update_SR_Register64(res, isCarry(oldprod, res), false);  | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //----
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | // MULAXH
 | 
					
						
							|  |  |  | // 1000 0011 xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply $ax0.h by $ax0.h 
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulaxh(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 prod = dsp_multiply(dsp_get_ax_h(0), dsp_get_ax_h(0)); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_prod(prod);		 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //----
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // MUL $axS.l, $axS.h
 | 
					
						
							|  |  |  | // 1001 s000 xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply low part $axS.l of secondary accumulator $axS by high part
 | 
					
						
							|  |  |  | // $axS.h of secondary accumulator $axS (treat them both as signed).
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mul(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 sreg  = (opc >> 11) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 axl = dsp_get_ax_l(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(sreg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply(axh, axl); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULAC $axS.l, $axS.h, $acR
 | 
					
						
							|  |  |  | // 1001 s10r xxxx xxxx
 | 
					
						
							|  |  |  | // Add product register to accumulator register $acR. Multiply low part
 | 
					
						
							|  |  |  | // $axS.l of secondary accumulator $axS by high part $axS.h of secondary
 | 
					
						
							|  |  |  | // accumulator $axS (treat them both as signed).
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulac(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 11) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 axl = dsp_get_ax_l(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(sreg); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_multiply(axl, axh); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 												 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULMV $axS.l, $axS.h, $acR
 | 
					
						
							|  |  |  | // 1001 s11r xxxx xxxx
 | 
					
						
							|  |  |  | // Move product register to accumulator register $acR. Multiply low part
 | 
					
						
							|  |  |  | // $axS.l of secondary accumulator $axS by high part $axS.h of secondary
 | 
					
						
							|  |  |  | // accumulator $axS (treat them both as signed).
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulmv(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg  = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg  = ((opc >> 11) & 0x1); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod(); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 axl = dsp_get_ax_l(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(sreg); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_multiply(axl, axh); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 												 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULMVZ $axS.l, $axS.h, $acR
 | 
					
						
							|  |  |  | // 1001 s01r xxxx xxxx
 | 
					
						
							|  |  |  | // Move product register to accumulator register $acR and clear low part
 | 
					
						
							|  |  |  | // of accumulator register $acR.l. Multiply low part $axS.l of secondary
 | 
					
						
							|  |  |  | // accumulator $axS by high part $axS.h of secondary accumulator $axS (treat
 | 
					
						
							|  |  |  | // them both as signed).
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulmvz(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 11) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod_round_prodl(); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 axl = dsp_get_ax_l(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(sreg); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_multiply(axl, axh); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //----
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // MULX $ax0.S, $ax1.T
 | 
					
						
							|  |  |  | // 101s t000 xxxx xxxx
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | // Multiply one part $ax0 by one part $ax1.
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // Part is selected by S and T bits. Zero selects low part, one selects high part.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulx(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 treg = ((opc >> 11) & 0x1); | 
					
						
							|  |  |  | 	u8 sreg = ((opc >> 12) & 0x1); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); | 
					
						
							|  |  |  | 	u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULXAC $ax0.S, $ax1.T, $acR
 | 
					
						
							|  |  |  | // 101s t01r xxxx xxxx
 | 
					
						
							|  |  |  | // Add product register to accumulator register $acR. Multiply one part
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | // $ax0 by one part $ax1. Part is selected by S and
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // T bits. Zero selects low part, one selects high part.
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulxac(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 treg = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); | 
					
						
							|  |  |  | 	u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULXMV $ax0.S, $ax1.T, $acR
 | 
					
						
							|  |  |  | // 101s t11r xxxx xxxx
 | 
					
						
							|  |  |  | // Move product register to accumulator register $acR. Multiply one part
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | // $ax0 by one part $ax1. Part is selected by S and
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // T bits. Zero selects low part, one selects high part.
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulxmv(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = ((opc >> 8) & 0x1); | 
					
						
							|  |  |  | 	u8 treg = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod(); | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | 	u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); | 
					
						
							|  |  |  | 	u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULXMV $ax0.S, $ax1.T, $acR
 | 
					
						
							|  |  |  | // 101s t01r xxxx xxxx
 | 
					
						
							|  |  |  | // Move product register to accumulator register $acR and clear low part
 | 
					
						
							| 
									
										
										
										
											2010-03-18 00:18:36 +00:00
										 |  |  | // of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1
 | 
					
						
							|  |  |  | // Part is selected by S and T bits. Zero selects low part,
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // one selects high part.
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulxmvz(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg  = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 treg = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod_round_prodl(); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 	u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); | 
					
						
							|  |  |  | 	u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //----
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULC $acS.m, $axT.h
 | 
					
						
							|  |  |  | // 110s t000 xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply mid part of accumulator register $acS.m by high part $axS.h of
 | 
					
						
							|  |  |  | // secondary accumulator $axS (treat them both as signed).
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulc(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 treg = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	u16 accm = dsp_get_acc_m(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(treg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply(accm, axh); | 
					
						
							|  |  |  | 												 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | // MULCAC $acS.m, $axT.h, $acR
 | 
					
						
							|  |  |  | // 110s	t10r xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply mid part of accumulator register $acS.m by high part $axS.h of
 | 
					
						
							|  |  |  | // secondary accumulator $axS  (treat them both as signed). Add product
 | 
					
						
							|  |  |  | // register before multiplication to accumulator $acR.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulcac(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 treg  = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg  = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); | 
					
						
							|  |  |  | 	u16 accm = dsp_get_acc_m(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(treg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply(accm, axh); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsp_set_long_prod(prod); | 
					
						
							|  |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULCMV $acS.m, $axT.h, $acR
 | 
					
						
							|  |  |  | // 110s t11r xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply mid part of accumulator register $acS.m by high part $axT.h of
 | 
					
						
							|  |  |  | // secondary accumulator $axT  (treat them both as signed). Move product
 | 
					
						
							|  |  |  | // register before multiplication to accumulator $acR.
 | 
					
						
							|  |  |  | // possible mistake in duddie's doc axT.h rather than axS.h
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulcmv(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 treg  = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg  = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	s64 acc = dsp_get_long_prod(); | 
					
						
							|  |  |  | 	u16 accm = dsp_get_acc_m(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(treg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply(accm, axh); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsp_set_long_prod(prod); | 
					
						
							|  |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MULCMVZ $acS.m, $axT.h, $acR
 | 
					
						
							|  |  |  | // 110s	t01r xxxx xxxx
 | 
					
						
							|  |  |  | // (fixed possible bug in duddie's description, s->t)
 | 
					
						
							|  |  |  | // Multiply mid part of accumulator register $acS.m by high part $axT.h of
 | 
					
						
							|  |  |  | // secondary accumulator $axT  (treat them both as signed). Move product
 | 
					
						
							|  |  |  | // register before multiplication to accumulator $acR, set low part of 
 | 
					
						
							|  |  |  | // accumulator $acR.l to zero.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2010-03-28 17:10:36 +00:00
										 |  |  | // flags out: --xx xx0x
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void mulcmvz(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 rreg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 treg  = (opc >> 11) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg  = (opc >> 12) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-19 21:53:41 +00:00
										 |  |  | 	s64 acc = dsp_get_long_prod_round_prodl(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	u16 accm = dsp_get_acc_m(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(treg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply(accm, axh); | 
					
						
							|  |  |  | 											 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsp_set_long_prod(prod); | 
					
						
							|  |  |  | 	dsp_set_long_acc(rreg, acc); | 
					
						
							|  |  |  | 	Update_SR_Register64(dsp_get_long_acc(rreg)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //----
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | // MADDX ax0.S ax1.T
 | 
					
						
							|  |  |  | // 1110 00st xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply one part of secondary accumulator $ax0 (selected by S) by
 | 
					
						
							|  |  |  | // one part of secondary accumulator $ax1 (selected by T) (treat them both as
 | 
					
						
							|  |  |  | // signed) and add result to product register.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void maddx(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 treg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 9) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); | 
					
						
							|  |  |  | 	u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); | 
					
						
							| 
									
										
										
										
											2009-11-14 17:45:35 +00:00
										 |  |  | 	s64 prod = dsp_multiply_add(val1, val2); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MSUBX $(0x18+S*2), $(0x19+T*2)
 | 
					
						
							|  |  |  | // 1110 01st xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply one part of secondary accumulator $ax0 (selected by S) by
 | 
					
						
							|  |  |  | // one part of secondary accumulator $ax1 (selected by T) (treat them both as
 | 
					
						
							|  |  |  | // signed) and subtract result from product register.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void msubx(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 treg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 9) & 0x1; | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); | 
					
						
							|  |  |  | 	u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); | 
					
						
							| 
									
										
										
										
											2009-11-14 17:45:35 +00:00
										 |  |  | 	s64 prod = dsp_multiply_sub(val1, val2); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MADDC $acS.m, $axT.h
 | 
					
						
							|  |  |  | // 1110 10st xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply middle part of accumulator $acS.m by high part of secondary
 | 
					
						
							|  |  |  | // accumulator $axT.h (treat them both as signed) and add result to product
 | 
					
						
							|  |  |  | // register.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void maddc(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 treg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 9) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 accm = dsp_get_acc_m(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(treg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply_add(accm, axh); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MSUBC $acS.m, $axT.h
 | 
					
						
							|  |  |  | // 1110 11st xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply middle part of accumulator $acS.m by high part of secondary
 | 
					
						
							|  |  |  | // accumulator $axT.h (treat them both as signed) and subtract result from
 | 
					
						
							|  |  |  | // product register.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void msubc(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 treg = (opc >> 8) & 0x1; | 
					
						
							|  |  |  | 	u8 sreg = (opc >> 9) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 accm = dsp_get_acc_m(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(treg); | 
					
						
							|  |  |  | 	s64 prod = dsp_multiply_sub(accm, axh); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MADD $axS.l, $axS.h
 | 
					
						
							|  |  |  | // 1111 001s xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply low part $axS.l of secondary accumulator $axS by high part
 | 
					
						
							|  |  |  | // $axS.h of secondary accumulator $axS (treat them both as signed) and add
 | 
					
						
							|  |  |  | // result to product register.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void madd(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 sreg = (opc >> 8) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 axl = dsp_get_ax_l(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(sreg); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_multiply_add(axl, axh); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 												 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MSUB $axS.l, $axS.h
 | 
					
						
							|  |  |  | // 1111 011s xxxx xxxx
 | 
					
						
							|  |  |  | // Multiply low part $axS.l of secondary accumulator $axS by high part
 | 
					
						
							|  |  |  | // $axS.h of secondary accumulator $axS (treat them both as signed) and
 | 
					
						
							|  |  |  | // subtract result from product register.
 | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | void msub(const UDSPInstruction opc) | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-24 05:05:25 +00:00
										 |  |  | 	u8 sreg = (opc >> 8) & 0x1; | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 	u16 axl = dsp_get_ax_l(sreg); | 
					
						
							|  |  |  | 	u16 axh = dsp_get_ax_h(sreg); | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	s64 prod = dsp_multiply_sub(axl, axh); | 
					
						
							| 
									
										
										
										
											2009-08-19 21:37:24 +00:00
										 |  |  | 												 | 
					
						
							|  |  |  | 	zeroWriteBackLog(); | 
					
						
							| 
									
										
										
										
											2010-03-08 21:25:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-20 15:11:07 +00:00
										 |  |  | 	dsp_set_long_prod(prod); | 
					
						
							| 
									
										
										
										
											2009-07-06 02:10:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace
 |