mirror of
https://github.com/RKX1209/nsemu.git
synced 2024-06-23 06:32:39 -04:00
Add support of 3src data proc(i.e MADD,SUB/MUL)
This commit is contained in:
parent
fce85f7a91
commit
b0e8996b59
|
@ -531,6 +531,61 @@ static void DisasAddSubReg(uint32_t insn, DisasCallback *cb) {
|
|||
}
|
||||
}
|
||||
|
||||
static void DisasDataProc3src(uint32_t insn, DisasCallback *cb) {
|
||||
unsigned int rd = extract32(insn, 0, 5);
|
||||
unsigned int rn = extract32(insn, 5, 5);
|
||||
unsigned int ra = extract32(insn, 10, 5);
|
||||
unsigned int rm = extract32(insn, 16, 5);
|
||||
unsigned int op_id = (extract32(insn, 29, 3) << 4) |
|
||||
(extract32(insn, 21, 3) << 1) | extract32(insn, 15, 1);
|
||||
bool sf = extract32(insn, 31, 1);
|
||||
bool is_sub = extract32(op_id, 0, 1);
|
||||
bool is_high = extract32(op_id, 2, 1);
|
||||
bool is_signed = false;
|
||||
bool src64 = false;
|
||||
|
||||
/* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
|
||||
switch (op_id) {
|
||||
case 0x42: /* SMADDL */
|
||||
case 0x43: /* SMSUBL */
|
||||
case 0x44: /* SMULH */
|
||||
is_signed = true;
|
||||
break;
|
||||
case 0x0: /* MADD (32bit) */
|
||||
case 0x1: /* MSUB (32bit) */
|
||||
case 0x40: /* MADD (64bit) */
|
||||
case 0x41: /* MSUB (64bit) */
|
||||
case 0x4a: /* UMADDL */
|
||||
case 0x4b: /* UMSUBL */
|
||||
case 0x4c: /* UMULH */
|
||||
break;
|
||||
default:
|
||||
UnallocatedOp (insn);
|
||||
return;
|
||||
}
|
||||
if (is_high) {
|
||||
/* SMULH, UMULH ... [Multiply High] */
|
||||
cb->Mul2Reg (rd, GPR_DUMMY, rn, rm, is_signed);
|
||||
} else {
|
||||
/*
|
||||
* sf = 0: MADD(32bit), MSUB(32bit) ... Wd = Wa +/- Wn * Wm
|
||||
* sf = 1: (op_id < 0x42) MADD(64bit), MSUB(64bit) ... Xd = Xa +/- Xn * Xm
|
||||
(sign = 0) UMADDL(UMULL), UMSUBL(UMNEGL) ... [Multiply Long 32bit*32bit] Xd = Wa +/- Wn * Wm
|
||||
* (sign = 1) SMADDL(SMULL), SMSUBL(SMNEGL) ... [Multiply Long 32bit*32bit] Xd = Wa +/- Wn * Wm
|
||||
*/
|
||||
if (op_id < 0x42) {
|
||||
/* MADD(64bit), MSUB(64bit) */
|
||||
src64 = true;
|
||||
}
|
||||
cb->MulReg (rd, rn, rm, is_signed, sf, src64);
|
||||
if (is_sub)
|
||||
cb->SubReg (rd, ra, rd, false, src64);
|
||||
else
|
||||
cb->AddReg (rd, ra, rd, false, src64);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void DisasAddSubcReg(uint32_t insn, DisasCallback *cb) {
|
||||
unsigned int sf = extract32(insn, 31, 1);
|
||||
unsigned int sub_op = extract32(insn, 30, 1);
|
||||
|
@ -681,7 +736,7 @@ static void DisasDataProc2src(uint32_t insn, DisasCallback *cb) {
|
|||
static void DisasDataProcReg(uint32_t insn, DisasCallback *cb) {
|
||||
switch (extract32(insn, 24, 5)) {
|
||||
case 0x0a: /* Logical (shifted register) */
|
||||
DisasLogicReg(insn, cb);
|
||||
DisasLogicReg (insn, cb);
|
||||
break;
|
||||
case 0x0b: /* Add/subtract */
|
||||
if (insn & (1 << 21)) { /* (extended register) */
|
||||
|
@ -691,8 +746,7 @@ static void DisasDataProcReg(uint32_t insn, DisasCallback *cb) {
|
|||
}
|
||||
break;
|
||||
case 0x1b: /* Data-processing (3 source) */
|
||||
/* TODO */
|
||||
UnsupportedOp ("DataProc3src");
|
||||
DisasDataProc3src (insn, cb);
|
||||
break;
|
||||
case 0x1a:
|
||||
switch (extract32(insn, 21, 3)) {
|
||||
|
@ -793,7 +847,7 @@ static void DisasLdstRegRoffset(uint32_t insn, DisasCallback *cb,
|
|||
is_store = (opc == 0);
|
||||
is_signed = extract32(opc, 1, 1);
|
||||
//is_extended = (size < 3) && extract32(opc, 0, 1);
|
||||
is_extended = (size < 3); //TODO: treat other case, size = 0, 1(8bit-> or 16bit->)
|
||||
is_extended = (size < 3); //TODO: treat other case, size = 0, 1(8bit-> or 16bit->)
|
||||
}
|
||||
bool sf = DisasLdstCompute64bit (size, is_signed, opc);
|
||||
cb->ExtendReg (GPR_DUMMY, rm, opt, sf); //FIXME: When rm == GPR_ZERO, it should be handled as GPR_SP
|
||||
|
|
|
@ -17,11 +17,12 @@ int Interpreter::SingleStep() {
|
|||
void Interpreter::Run() {
|
||||
debug_print ("Running with Interpreter\n");
|
||||
static uint64_t counter = 0;
|
||||
uint64_t estimate = 3404800;
|
||||
uint64_t estimate = 3404800, mx = 1000;
|
||||
while (Cpu::GetState () == Cpu::State::Running) {
|
||||
char c;
|
||||
//scanf("%c", &c);
|
||||
if (counter >= estimate) {
|
||||
//if (counter >= estimate && counter <= estimate + mx){
|
||||
Cpu::DumpMachine ();
|
||||
}
|
||||
SingleStep ();
|
||||
|
@ -42,6 +43,7 @@ enum OpType{
|
|||
AL_TYPE_EOR,
|
||||
AL_TYPE_SDIV,
|
||||
AL_TYPE_UDIV,
|
||||
AL_TYPE_MUL,
|
||||
};
|
||||
|
||||
const char *OpStrs[] = { "<<", ">>", ">>", "ROR", "+", "-", "&", "|", "^" };
|
||||
|
@ -119,11 +121,53 @@ static int64_t Sdiv64(int64_t arg1, int64_t arg2) {
|
|||
return arg1 / arg2;
|
||||
}
|
||||
|
||||
static void Umul64(uint64_t *res_h, uint64_t *res_l, uint64_t arg1, uint64_t arg2) {
|
||||
typedef union {
|
||||
uint64_t ll;
|
||||
struct {
|
||||
uint32_t low, high;
|
||||
} l;
|
||||
} LL;
|
||||
LL rl, rm, rn, rh, a0, b0;
|
||||
uint64_t c;
|
||||
|
||||
a0.ll = arg1;
|
||||
b0.ll = arg2;
|
||||
|
||||
rl.ll = (uint64_t)a0.l.low * b0.l.low;
|
||||
rm.ll = (uint64_t)a0.l.low * b0.l.high;
|
||||
rn.ll = (uint64_t)a0.l.high * b0.l.low;
|
||||
rh.ll = (uint64_t)a0.l.high * b0.l.high;
|
||||
|
||||
c = (uint64_t)rl.l.high + rm.l.low + rn.l.low;
|
||||
rl.l.high = c;
|
||||
c >>= 32;
|
||||
c = c + rm.l.high + rn.l.high + rh.l.low;
|
||||
rh.l.low = c;
|
||||
rh.l.high += (uint32_t)(c >> 32);
|
||||
|
||||
*res_l = rl.ll;
|
||||
*res_h = rh.ll;
|
||||
}
|
||||
|
||||
static void Smul64(uint64_t *res_h, uint64_t *res_l, uint64_t arg1, uint64_t arg2) {
|
||||
uint64_t rh;
|
||||
|
||||
Umul64(res_l, &rh, arg1, arg2);
|
||||
|
||||
/* Adjust for signs. */
|
||||
if (arg2 < 0) {
|
||||
rh -= arg1;
|
||||
}
|
||||
if (arg1 < 0) {
|
||||
rh -= arg2;
|
||||
}
|
||||
*res_h = rh;
|
||||
}
|
||||
|
||||
static uint64_t ALCalc(uint64_t arg1, uint64_t arg2, OpType op) {
|
||||
if (op == AL_TYPE_ADD)
|
||||
return arg1 + arg2;
|
||||
// if (op == AL_TYPE_SUB)
|
||||
// return arg1 - arg2;
|
||||
if (op == AL_TYPE_AND)
|
||||
return arg1 & arg2;
|
||||
if (op == AL_TYPE_OR)
|
||||
|
@ -144,6 +188,9 @@ static uint64_t ALCalc(uint64_t arg1, uint64_t arg2, OpType op) {
|
|||
if (op == AL_TYPE_SDIV) {
|
||||
return Sdiv64 (arg1, arg2);
|
||||
}
|
||||
if (op == AL_TYPE_MUL) {
|
||||
return arg1 * arg2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -262,6 +309,32 @@ void IntprCallback::SubReg(unsigned int rd_idx, unsigned int rn_idx, unsigned in
|
|||
else
|
||||
ArithmeticLogic (rd_idx, W(rn_idx), W(rm_idx), setflags, bit64, AL_TYPE_SUB);
|
||||
}
|
||||
void IntprCallback::MulReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool dst64, bool src64) {
|
||||
char regdc = dst64? 'X': 'W';
|
||||
char regsc = src64? 'X': 'W';
|
||||
debug_print ("%cMUL: %c[%u] = %c[%u] * %c[%u] \n", sign?'S':'U', regdc, rd_idx, regsc, rn_idx, regsc, rm_idx);
|
||||
if (dst64) {
|
||||
if (src64) {
|
||||
X(rd_idx) = X(rn_idx) * X(rm_idx);
|
||||
} else {
|
||||
if (sign)
|
||||
X(rd_idx) = (int64_t)((int32_t)W(rn_idx) * (int32_t)W(rm_idx));
|
||||
else
|
||||
X(rd_idx) = W(rn_idx) * W(rm_idx);
|
||||
}
|
||||
} else {
|
||||
W(rd_idx) = W(rn_idx) * W(rm_idx);
|
||||
}
|
||||
}
|
||||
//64bit * 64bit
|
||||
void IntprCallback::Mul2Reg(unsigned int rh_idx, unsigned int rl_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign) {
|
||||
debug_print ("%cMUL2: X[%u], X[%u] = X[%u] * X[%u] \n", sign?'S':'U', rh_idx, rl_idx, rn_idx, rm_idx);
|
||||
if (sign)
|
||||
Smul64(&X(rh_idx), &X(rl_idx), X(rn_idx), X(rm_idx));
|
||||
else
|
||||
Umul64(&X(rh_idx), &X(rl_idx), X(rn_idx), X(rm_idx));
|
||||
}
|
||||
|
||||
void IntprCallback::DivReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool bit64) {
|
||||
char regc = bit64? 'X': 'W';
|
||||
debug_print ("%cDIV: %c[%u] = %c[%u] / %c[%u] \n", sign?'S':'U', regc, rd_idx, regc, rn_idx, regc, rm_idx);
|
||||
|
|
|
@ -22,9 +22,11 @@ virtual void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_
|
|||
virtual void AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) = 0;
|
||||
virtual void SubI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64) = 0;
|
||||
|
||||
/* Add/Sub/Div between registers */
|
||||
/* Add/Sub/Mul/Div between registers */
|
||||
virtual void AddReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0;
|
||||
virtual void SubReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64) = 0;
|
||||
virtual void MulReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool dst64, bool src64) = 0;
|
||||
virtual void Mul2Reg(unsigned int rh_idx, unsigned int rl_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign) = 0; //64bit * 64bit
|
||||
virtual void DivReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool bit64) = 0;
|
||||
virtual void ShiftReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, unsigned int shift_type, bool bit64) = 0;
|
||||
|
||||
|
|
|
@ -22,9 +22,11 @@ void CondMovReg(unsigned int cond, unsigned int rd_idx, unsigned int rn_idx, boo
|
|||
void AddI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64);
|
||||
void SubI64(unsigned int rd_idx, unsigned int rn_idx, uint64_t imm, bool setflags, bool bit64);
|
||||
|
||||
/* Add/Sub/Div between registers */
|
||||
/* Add/Sub/Mul/Div between registers */
|
||||
void AddReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64);
|
||||
void SubReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool setflags, bool bit64);
|
||||
void MulReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool dst64, bool src64);
|
||||
void Mul2Reg(unsigned int rh_idx, unsigned int rl_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign); //64bit * 64bit
|
||||
void DivReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, bool sign, bool bit64);
|
||||
void ShiftReg(unsigned int rd_idx, unsigned int rn_idx, unsigned int rm_idx, unsigned int shift_type, bool bit64) ;
|
||||
|
||||
|
|
Loading…
Reference in a new issue