blob: 41a9075a8e79448ee9bfb22422f5bb20bd1916a9 [file] [log] [blame]
:option:::insn-bit-size:16
:option:::hi-bit-nr:15
:option:::format-names:I,II,III,IV,V,VI,VII,VIII,IX,X
:option:::format-names:XI,XII,XIII
:option:::format-names:XIV,XV
:option:::format-names:Z
:option:::format-names:F_I
:option:::format-names:C
:model:::v850:v850:
:option:::multi-sim:true
:model:::v850e:v850e:
:option:::multi-sim:true
:model:::v850e1:v850e1:
:option:::multi-sim:true
:model:::v850e2:v850e2:
:option:::multi-sim:true
:model:::v850e2v3:v850e2v3:
:option:::multi-sim:true
:model:::v850e3v5:v850e3v5:
// Cache macros
:cache:::unsigned:reg1:RRRRR:(RRRRR)
:cache:::unsigned:reg2:rrrrr:(rrrrr)
:cache:::unsigned:reg3:wwwww:(wwwww)
:cache:::unsigned:reg4:W,WWWW:(W + (WWWW << 1))
:cache:::unsigned:vreg1:VVVVV:(VVVVV)
:cache:::unsigned:vreg1:VVVV:(VVVV << 1)
:cache:::unsigned:vreg2:vvvvv:(vvvvv)
:cache:::unsigned:vreg2:vvvv:(vvvv << 1)
:cache:::unsigned:vreg3:xxxx:(xxxx << 1)
:cache:::unsigned:vreg3:xxxxx:(xxxxx)
:cache:::unsigned:imm2:ii:(ii)
:cache:::unsigned:imm1:i:(i)
:cache:::unsigned:reg1e:RRRR:(RRRR << 1)
:cache:::unsigned:reg2e:rrrr:(rrrr << 1)
:cache:::unsigned:reg3e:wwww:(wwww << 1)
:cache:::unsigned:reg4e:mmmm:(mmmm << 1)
:cache:::unsigned:disp4:dddd:(dddd)
:cache:::unsigned:disp5:dddd:(dddd << 1)
:cache:::unsigned:disp7:ddddddd:ddddddd
:cache:::unsigned:disp8:ddddddd:(ddddddd << 1)
:cache:::unsigned:disp8:dddddd:(dddddd << 2)
:cache:::unsigned:disp9:ddddd,ddd:SEXT32 ((ddddd << 4) + (ddd << 1), 9 - 1)
:cache:::unsigned:disp16:dddddddddddddddd:EXTEND16 (dddddddddddddddd)
:cache:::unsigned:disp16:ddddddddddddddd: EXTEND16 (ddddddddddddddd << 1)
:cache:::unsigned:disp17:d,ddddddddddddddd:SEXT32 (((d <<16) + (ddddddddddddddd << 1)), 17 - 1)
:cache:::unsigned:disp22:dddddd,ddddddddddddddd: SEXT32 ((dddddd << 16) + (ddddddddddddddd << 1), 22 - 1)
:cache:::unsigned:disp23:ddddddd,dddddddddddddddd: SEXT32 ((ddddddd) + (dddddddddddddddd << 7), 23 - 1)
:cache:::unsigned:disp23:dddddd,dddddddddddddddd: SEXT32 ((dddddd << 1) + (dddddddddddddddd << 7), 23 - 1)
:cache:::unsigned:imm5:iiiii:SEXT32 (iiiii, 4)
:cache:::unsigned:imm6:iiiiii:iiiiii
:cache:::unsigned:imm9:iiiii,IIII:SEXT ((IIII << 5) + iiiii, 9 - 1)
:cache:::unsigned:imm5:iiii:(32 - (iiii << 1))
:cache:::unsigned:simm16:iiiiiiiiiiiiiiii:EXTEND16 (iiiiiiiiiiiiiiii)
:cache:::unsigned:uimm16:iiiiiiiiiiiiiiii:iiiiiiiiiiiiiiii
:cache:::unsigned:imm32:iiiiiiiiiiiiiiii,IIIIIIIIIIIIIIII:(iiiiiiiiiiiiiiii < 16 + IIIIIIIIIIIIIIII)
:cache:::unsigned:uimm32:iiiiiiiiiiiiiiii,dddddddddddddddd:((iiiiiiiiiiiiiiii << 16) + dddddddddddddddd)
:cache:::unsigned:vector:iiiii:iiiii
:cache:::unsigned:list12:L,LLLLLLLLLLL:((L << 11) + LLLLLLLLLLL)
:cache:::unsigned:list18:LLLL,LLLLLLLLLLLL:((LLLL << 12) + LLLLLLLLLLLL)
:cache:::unsigned:bit3:bbb:bbb
:cache:::unsigned:bit4:bbbb:bbbb
:cache:::unsigned:bit13:B,BBB:((B << 3) + BBB)
// What do we do with an illegal instruction?
:internal::::illegal:
{
sim_io_eprintf (SD, "Illegal instruction at address 0x%lx\n",
(unsigned long) cia);
sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIM_SIGILL);
}
// ADD
rrrrr,001110,RRRRR:I:::add
"add r<reg1>, r<reg2>"
{
COMPAT_1 (OP_1C0 ());
}
rrrrr,010010,iiiii:II:::add
"add <imm5>,r<reg2>"
{
COMPAT_1 (OP_240 ());
}
// ADDI
rrrrr,110000,RRRRR + iiiiiiiiiiiiiiii:VI:::addi
"addi <simm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_600 ());
}
// ADF
rrrrr,111111,RRRRR + wwwww,011101,cccc!13,0:XI:::adf
*v850e2
*v850e2v3
*v850e3v5
"adf %s<cccc>, r<reg1>, r<reg2>, r<reg3>"
{
int cond = condition_met (cccc);
TRACE_ALU_INPUT3 (cond, GR[reg1], GR[reg2]);
GR[reg3] = GR[reg1] + GR[reg2] + (cond ? 1 : 0);
TRACE_ALU_RESULT1 (GR[reg3]);
}
// AND
rrrrr,001010,RRRRR:I:::and
"and r<reg1>, r<reg2>"
{
COMPAT_1 (OP_140 ());
}
// ANDI
rrrrr,110110,RRRRR + iiiiiiiiiiiiiiii:VI:::andi
"andi <uimm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_6C0 ());
}
// Map condition code to a string
:%s::::cccc:int cccc
{
switch (cccc)
{
case 0xf: return "gt";
case 0xe: return "ge";
case 0x6: return "lt";
case 0x7: return "le";
case 0xb: return "h";
case 0x9: return "nl";
case 0x1: return "l";
case 0x3: return "nh";
case 0x2: return "e";
case 0xa: return "ne";
case 0x0: return "v";
case 0x8: return "nv";
case 0x4: return "n";
case 0xc: return "p";
/* case 0x1: return "c"; */
/* case 0x9: return "nc"; */
/* case 0x2: return "z"; */
/* case 0xa: return "nz"; */
case 0x5: return "r"; /* always */
case 0xd: return "sa";
}
return "(null)";
}
// Bcond
ddddd,1011,ddd,cccc:III:::Bcond
"b%s<cccc> <disp9>"
{
int cond;
if ((ddddd == 0x00) && (ddd == 0x00) && (cccc == 0x05)) {
// Special case - treat "br *" like illegal instruction
sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP);
} else {
cond = condition_met (cccc);
if (cond)
nia = cia + disp9;
TRACE_BRANCH1 (cond);
}
}
00000111111,d,cccc + ddddddddddddddd,1:VII:::Bcond
"breakpoint":((disp17 == 0) && (cccc == 0x05))
"b%s<cccc> <disp17>"
*v850e2v3
*v850e3v5
{
int cond;
cond = condition_met (cccc);
if (cond)
nia = cia + disp17;
TRACE_BRANCH_INPUT1 (cond);
TRACE_BRANCH_RESULT (nia);
}
// BSH
rrrrr,11111100000 + wwwww,01101000010:XII:::bsh
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"bsh r<reg2>, r<reg3>"
{
unsigned32 value;
TRACE_ALU_INPUT1 (GR[reg2]);
value = (MOVED32 (GR[reg2], 23, 16, 31, 24)
| MOVED32 (GR[reg2], 31, 24, 23, 16)
| MOVED32 (GR[reg2], 7, 0, 15, 8)
| MOVED32 (GR[reg2], 15, 8, 7, 0));
GR[reg3] = value;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
if ((value & 0xffff) == 0) PSW |= PSW_Z;
if (value & 0x80000000) PSW |= PSW_S;
if (((value & 0xff) == 0) || ((value & 0xff00) == 0)) PSW |= PSW_CY;
TRACE_ALU_RESULT (GR[reg3]);
}
// BSW
rrrrr,11111100000 + wwwww,01101000000:XII:::bsw
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"bsw r<reg2>, r<reg3>"
{
#define WORDHASNULLBYTE(x) (((x) - 0x01010101) & ~(x)&0x80808080)
unsigned32 value;
TRACE_ALU_INPUT1 (GR[reg2]);
value = GR[reg2];
value >>= 24;
value |= (GR[reg2] << 24);
value |= ((GR[reg2] << 8) & 0x00ff0000);
value |= ((GR[reg2] >> 8) & 0x0000ff00);
GR[reg3] = value;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
if (value == 0) PSW |= PSW_Z;
if (value & 0x80000000) PSW |= PSW_S;
if (WORDHASNULLBYTE (value)) PSW |= PSW_CY;
TRACE_ALU_RESULT (GR[reg3]);
}
// CALLT
0000001000,iiiiii:II:::callt
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"callt <imm6>"
{
unsigned32 adr;
unsigned32 off;
CTPC = cia + 2;
CTPSW = PSW;
adr = (CTBP & ~1) + (imm6 << 1);
off = load_mem (adr, 2) & ~1; /* Force alignment */
nia = (CTBP & ~1) + off;
TRACE_BRANCH3 (adr, CTBP, off);
}
// CAXI
rrrrr,111111,RRRRR + wwwww,00011101110:IX:::caxi
*v850e2
*v850e2v3
*v850e3v5
"caxi [reg1], reg2, reg3"
{
unsigned int z,s,cy,ov;
unsigned32 addr;
unsigned32 token,result;
addr = GR[reg1];
if (mpu_load_mem_test(sd, addr, 4, reg1)
&& mpu_store_mem_test(sd, addr, 4, reg1))
{
token = load_data_mem (sd, addr, 4);
TRACE_ALU_INPUT2 (token, GR[reg2]);
result = GR[reg2] - token;
z = (result == 0);
s = (result & 0x80000000);
cy = (GR[reg2] < token);
ov = ((GR[reg2] & 0x80000000) != (token & 0x80000000)
&& (GR[reg2] & 0x80000000) != (result & 0x80000000));
if (result == 0)
{
store_data_mem (sd, addr, 4, GR[reg3]);
GR[reg3] = token;
}
else
{
store_data_mem (sd, addr, 4, token);
GR[reg3] = token;
}
/* Set condition codes. */
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
| (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0));
TRACE_ALU_RESULT1 (GR[reg3]);
}
}
// CLR1
10,bbb,111110,RRRRR + dddddddddddddddd:VIII:::clr1
"clr1 <bit3>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_87C0 ());
}
rrrrr,111111,RRRRR + 0000000011100100:IX:::clr1
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"clr1 r<reg2>, [r<reg1>]"
{
COMPAT_2 (OP_E407E0 ());
}
// CTRET
0000011111100000 + 0000000101000100:X:::ctret
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"ctret"
{
nia = (CTPC & ~1);
PSW = (CTPSW & (CPU)->psw_mask);
TRACE_BRANCH1 (PSW);
}
// CMOV
rrrrr,111111,RRRRR + wwwww,011001,cccc,0:XI:::cmov
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"cmov %s<cccc>, r<reg1>, r<reg2>, r<reg3>"
{
int cond = condition_met (cccc);
TRACE_ALU_INPUT3 (cond, GR[reg1], GR[reg2]);
GR[reg3] = cond ? GR[reg1] : GR[reg2];
TRACE_ALU_RESULT (GR[reg3]);
}
rrrrr,111111,iiiii + wwwww,011000,cccc,0:XII:::cmov
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"cmov %s<cccc>, <imm5>, r<reg2>, r<reg3>"
{
int cond = condition_met (cccc);
TRACE_ALU_INPUT3 (cond, imm5, GR[reg2]);
GR[reg3] = cond ? imm5 : GR[reg2];
TRACE_ALU_RESULT (GR[reg3]);
}
// CMP
rrrrr,001111,RRRRR:I:::cmp
"cmp r<reg1>, r<reg2>"
{
COMPAT_1 (OP_1E0 ());
}
rrrrr,010011,iiiii:II:::cmp
"cmp <imm5>, r<reg2>"
{
COMPAT_1 (OP_260 ());
}
// DI
0000011111100000 + 0000000101100000:X:::di
"di"
{
COMPAT_2 (OP_16007E0 ());
}
// DISPOSE
// 0000011001,iiiii,L + LLLLLLLLLLL,00000:XIII:::dispose
// "dispose <imm5>, <list12>"
0000011001,iiiii,L + LLLLLLLLLLL,RRRRR:XIII:::dispose
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"dispose <imm5>, <list12>":RRRRR == 0
"dispose <imm5>, <list12>, [reg1]"
{
int i;
SAVE_2;
trace_input ("dispose", OP_PUSHPOP1, 0);
SP += (OP[3] & 0x3e) << 1;
/* Load the registers with lower number registers being retrieved
from higher addresses. */
for (i = 12; i--;)
if ((OP[3] & (1 << type1_regs[ i ])))
{
State.regs[ 20 + i ] = load_mem (SP, 4);
SP += 4;
}
if ((OP[3] & 0x1f0000) != 0)
{
nia = State.regs[ (OP[3] >> 16) & 0x1f];
}
trace_output (OP_PUSHPOP1);
}
// DIV
rrrrr,111111,RRRRR + wwwww,01011000000:XI:::div
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"div r<reg1>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_2C007E0 ());
}
// DIVH
rrrrr!0,000010,RRRRR!0:I:::divh
"divh r<reg1>, r<reg2>"
{
unsigned32 ov, s, z;
signed long int op0, op1, result;
trace_input ("divh", OP_REG_REG, 0);
PC = cia;
OP[0] = instruction_0 & 0x1f;
OP[1] = (instruction_0 >> 11) & 0x1f;
/* Compute the result. */
op0 = EXTEND16 (State.regs[OP[0]]);
op1 = State.regs[OP[1]];
if (op0 == -1 && op1 == 0x80000000)
{
PSW &= ~PSW_Z;
PSW |= PSW_OV | PSW_S;
State.regs[OP[1]] = 0x80000000;
}
else if (op0 == 0)
{
PSW |= PSW_OV;
}
else
{
result = (signed32) op1 / op0;
ov = 0;
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
PSW &= ~(PSW_Z | PSW_S | PSW_OV);
PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (ov ? PSW_OV : 0));
}
trace_output (OP_REG_REG);
PC += 2;
nia = PC;
}
rrrrr,111111,RRRRR + wwwww,01010000000:XI:::divh
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"divh r<reg1>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_28007E0 ());
}
// DIVHU
rrrrr,111111,RRRRR + wwwww,01010000010:XI:::divhu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"divhu r<reg1>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_28207E0 ());
}
// DIVU
rrrrr,111111,RRRRR + wwwww,01011000010:XI:::divu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"divu r<reg1>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_2C207E0 ());
}
// DIVQ
rrrrr,111111,RRRRR + wwwww,01011111100:XI:::divq
*v850e2
*v850e2v3
*v850e3v5
"divq r<reg1>, r<reg2>, r<reg3>"
{
unsigned int quotient;
unsigned int remainder;
unsigned int divide_by;
unsigned int divide_this;
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
divide_by = GR[reg1];
divide_this = GR[reg2];
v850_div (sd, divide_by, divide_this, &quotient, &remainder);
GR[reg2] = quotient;
GR[reg3] = remainder;
TRACE_ALU_RESULT2 (GR[reg2], GR[reg3]);
}
// DIVQU
rrrrr,111111,RRRRR + wwwww,01011111110:XI:::divqu
*v850e2
*v850e2v3
*v850e3v5
"divq r<reg1>, r<reg2>, r<reg3>"
{
unsigned int quotient;
unsigned int remainder;
unsigned int divide_by;
unsigned int divide_this;
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
divide_by = GR[reg1];
divide_this = GR[reg2];
v850_divu (sd, divide_by, divide_this, &quotient, &remainder);
GR[reg2] = quotient;
GR[reg3] = remainder;
TRACE_ALU_RESULT2 (GR[reg2], GR[reg3]);
}
// EI
1000011111100000 + 0000000101100000:X:::ei
"ei"
{
COMPAT_2 (OP_16087E0 ());
}
// EIRET
0000011111100000 + 0000000101001000:X:::eiret
"eiret"
*v850e2
*v850e2v3
*v850e3v5
{
TRACE_ALU_INPUT1 (MPM & MPM_AUE);
nia = EIPC; /* next PC */
if (MPM & MPM_AUE)
{
PSW = EIPSW;
}
else
{
PSW = (PSW & (PSW_NPV | PSW_DMP | PSW_IMP))
| (EIPSW & ~(PSW_NPV | PSW_DMP | PSW_IMP));
}
TRACE_ALU_RESULT1 (PSW);
TRACE_BRANCH_RESULT (nia);
}
// FERET
0000011111100000 + 0000000101001010:X:::feret
"feret"
*v850e2
*v850e2v3
*v850e3v5
{
TRACE_ALU_INPUT1 (MPM & MPM_AUE);
nia = FEPC; /* next PC */
if (MPM & MPM_AUE)
{
PSW = FEPSW;
}
else
{
PSW = (PSW & (PSW_NPV | PSW_DMP | PSW_IMP))
| (FEPSW & ~(PSW_NPV | PSW_DMP | PSW_IMP));
}
TRACE_ALU_RESULT1 (PSW);
TRACE_BRANCH_RESULT (nia);
}
// FETRAP
0,bbbb!0,00001000000:I:::fetrap
"fetrap"
*v850e2
*v850e2v3
*v850e3v5
{
TRACE_ALU_INPUT0 ();
FEPC = PC + 2;
FEPSW = PSW;
ECR &= ~ECR_FECC;
ECR |= (0x30 + bit4) << 16;
FEIC = 0x30 + bit4;
PSW |= PSW_EP | PSW_ID | PSW_NP;
nia = 0x30; /* next PC */
TRACE_ALU_RESULT1 (PSW);
TRACE_BRANCH_RESULT (nia);
}
// HALT
0000011111100000 + 0000000100100000:X:::halt
"halt"
{
COMPAT_2 (OP_12007E0 ());
}
// HSH
rrrrr,11111100000 + wwwww,01101000110:XII:::hsh
*v850e2
*v850e2v3
*v850e3v5
"hsh r<reg2>, r<reg3>"
{
unsigned32 value;
TRACE_ALU_INPUT1 (GR[reg2]);
value = 0xffff & GR[reg2];
GR[reg3] = GR[reg2];
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
if (value == 0) { PSW |= PSW_Z; PSW |= PSW_CY; }
if (value & 0x80000000) PSW |= PSW_S;
TRACE_ALU_RESULT1 (GR[reg3]);
}
// HSW
rrrrr,11111100000 + wwwww,01101000100:XII:::hsw
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"hsw r<reg2>, r<reg3>"
{
unsigned32 value;
TRACE_ALU_INPUT1 (GR[reg2]);
value = GR[reg2];
value >>= 16;
value |= (GR[reg2] << 16);
GR[reg3] = value;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
if (value == 0) PSW |= PSW_Z;
if (value & 0x80000000) PSW |= PSW_S;
if (((value & 0xffff) == 0) || (value & 0xffff0000) == 0) PSW |= PSW_CY;
TRACE_ALU_RESULT (GR[reg3]);
}
// JARL
rrrrr!0,11110,dddddd + ddddddddddddddd,0:V:::jarl
"jarl <disp22>, r<reg2>"
{
GR[reg2] = nia;
nia = cia + disp22;
TRACE_BRANCH1 (GR[reg2]);
}
00000010111,RRRRR!0 + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::jarl32
*v850e2
*v850e2v3
*v850e3v5
"jarl <imm32>, r<reg1>"
{
GR[reg1] = nia;
nia = (cia + imm32) & ~1;
TRACE_BRANCH_RESULT (nia);
}
11000111111,RRRRR + wwwww!0,00101100000:XI:::jarl_reg
*v850e3v5
"jarl [r<reg1>], r<reg3>"
{
GR[reg3] = nia;
nia = GR[reg1];
TRACE_BRANCH_RESULT (nia);
}
// JMP
00000000011,RRRRR:I:::jmp
"jmp [r<reg1>]"
{
nia = GR[reg1] & ~1;
TRACE_BRANCH0 ();
}
00000110111,RRRRR + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::jmp32
*v850e2
*v850e2v3
*v850e3v5
"jmp <imm32>[r<reg1>]"
{
nia = (GR[reg1] + imm32) & ~1;
TRACE_BRANCH_RESULT (nia);
}
// JR
0000011110,dddddd + ddddddddddddddd,0:V:::jr
"jr <disp22>"
{
nia = cia + disp22;
TRACE_BRANCH0 ();
}
// JR32
0000001011100000 + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::jr32
*v850e2
*v850e2v3
*v850e3v5
"jr <imm32>"
{
nia = (cia + imm32) & ~1;
TRACE_BRANCH_RESULT (nia);
}
// LD
rrrrr,111000,RRRRR + dddddddddddddddd:VII:::ld.b
"ld.b <disp16>[r<reg1>], r<reg2>"
{
COMPAT_2 (OP_700 ());
}
00000111100,RRRRR+wwwww,ddddddd,0101+dddddddddddddddd:XIV:::ld.b
"ld.b <disp23>[r<reg1>], r<reg3>"
*v850e2v3
*v850e3v5
{
unsigned32 addr = GR[reg1] + disp23;
unsigned32 result = EXTEND8 (load_data_mem (sd, addr, 1));
GR[reg3] = result;
TRACE_LD (addr, result);
}
rrrrr,111001,RRRRR + ddddddddddddddd,0:VII:::ld.h
"ld.h <disp16>[r<reg1>], r<reg2>"
{
COMPAT_2 (OP_720 ());
}
00000111100,RRRRR+wwwww,dddddd,00111+dddddddddddddddd:XIV:::ld.h
*v850e2v3
*v850e3v5
"ld.h <disp23>[r<reg1>], r<reg3>"
{
unsigned32 addr = GR[reg1] + disp23;
unsigned32 result = EXTEND16 (load_data_mem (sd, addr, 2));
GR[reg3] = result;
TRACE_LD (addr, result);
}
rrrrr,111001,RRRRR + ddddddddddddddd,1:VII:::ld.w
"ld.w <disp16>[r<reg1>], r<reg2>"
{
COMPAT_2 (OP_10720 ());
}
00000111100,RRRRR+wwwww,dddddd,01001+dddddddddddddddd:XIV:::ld.w
*v850e2v3
*v850e3v5
"ld.w <disp23>[r<reg1>], r<reg3>"
{
unsigned32 addr = GR[reg1] + disp23;
unsigned32 result = load_data_mem (sd, addr, 4);
GR[reg3] = result;
TRACE_LD (addr, result);
}
00000111101,RRRRR+wwwww,dddddd,01001+dddddddddddddddd:XIV:::ld.dw
*v850e3v5
"ld.dw <disp23>[r<reg1>], r<reg3>"
{
unsigned32 addr = GR[reg1] + disp23;
unsigned32 result = load_data_mem (sd, addr, 4);
GR[reg3] = result;
TRACE_LD (addr, result);
result = load_data_mem (sd, addr + 4, 4);
GR[reg3 + 1] = result;
TRACE_LD (addr + 4, result);
}
rrrrr!0,11110,b,RRRRR + ddddddddddddddd,1:VII:::ld.bu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"ld.bu <disp16>[r<reg1>], r<reg2>"
{
COMPAT_2 (OP_10780 ());
}
00000111101,RRRRR+wwwww,ddddddd,0101+dddddddddddddddd:XIV:::ld.bu
*v850e2v3
*v850e3v5
"ld.bu <disp23>[r<reg1>], r<reg3>"
{
unsigned32 addr = GR[reg1] + disp23;
unsigned32 result = load_data_mem (sd, addr, 1);
GR[reg3] = result;
TRACE_LD (addr, result);
}
rrrrr!0,111111,RRRRR + ddddddddddddddd,1:VII:::ld.hu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"ld.hu <disp16>[r<reg1>], r<reg2>"
{
COMPAT_2 (OP_107E0 ());
}
00000111101,RRRRR+wwwww,dddddd,00111+dddddddddddddddd:XIV:::ld.hu
*v850e2v3
*v850e3v5
"ld.hu <disp23>[r<reg1>], r<reg3>"
{
unsigned32 addr = GR[reg1] + disp23;
unsigned32 result = load_data_mem (sd, addr, 2);
GR[reg3] = result;
TRACE_LD (addr, result);
}
// LDSR
regID,111111,RRRRR + selID,00000100000:IX:::ldsr
"ldsr r<reg1>, s<regID>":(selID == 0)
"ldsr r<reg1>, s<regID>, <selID>"
{
uint32 sreg = GR[reg1];
TRACE_ALU_INPUT1 (GR[reg1]);
/* FIXME: For now we ignore the selID. */
if (idecode_issue == idecode_v850e3v5_issue && selID != 0)
{
(CPU)->reg.selID_sregs[selID][regID] = sreg;
}
else if (( idecode_issue == idecode_v850e2_issue
|| idecode_issue == idecode_v850e3v5_issue
|| idecode_issue == idecode_v850e2v3_issue)
&& regID < 28)
{
int protect_p = (PSW & PSW_NPV) ? 1 : 0;
switch (BSEL & 0xffff)
{
case 0x0000:
if ((PSW & PSW_NPV)
&& ((regID >= 8 && regID <= 12)
|| (regID >= 22 && regID <= 27)
|| regID == PSW_REGNO))
{
protect_p = 0;
}
break;
case 0x1000: /* MPU0 */
break;
case 0x1001: /* MPU1 */
break;
case 0x2000: /* FPU */
if ((PSW & PSW_NPV)
&& ((/* regID >= 0 && */ regID <= 5)
|| regID == 8
|| regID == 9
|| regID == 10
|| (regID >= 11 && regID <= 26)))
{
protect_p = 0;
}
break;
case 0xff00:
if ((PSW & PSW_NPV)
&& (regID == 6
|| regID == 7
|| regID == 8
|| regID == 9
|| regID == 10
|| (regID >= 11 && regID <= 15)
|| regID == 18
|| regID == 19
|| (regID >= 21 && regID <= 27)))
{
protect_p = 0;
}
break;
case 0xffff:
if ((PSW & PSW_NPV)
&& (regID == 6
|| regID == 7
|| regID == 8
|| regID == 9
|| regID == 10
|| regID == 11
|| regID == 12
|| regID == 15
|| regID == 18
|| regID == 19
|| (regID >= 21 && regID <= 27)))
{
protect_p = 0;
}
break;
}
if (!protect_p)
{
switch (BSEL & 0xffff)
{
case 0x0000:
case 0xff00: /* user0 bank */
case 0xffff: /* user1 bank */
if(regID == PSW_REGNO)
{
SR[regID] = sreg & ((PSW & PSW_NPV) ? 0xf : ~0);
}
else
{
SR[regID] = sreg;
}
break;
case 0x1000:
MPU0_SR[regID] = sreg;
break;
case 0x1001:
if (regID == MPC_REGNO)
{
PPC &= ~PPC_PPE;
SPAL &= ~SPAL_SPE;
IPA0L &= ~IPA_IPE;
IPA1L &= ~IPA_IPE;
IPA2L &= ~IPA_IPE;
IPA3L &= ~IPA_IPE;
DPA0L &= ~DPA_DPE;
DPA1L &= ~DPA_DPE;
DCC &= ~(DCC_DCE0 | DCC_DCE1);
}
else
{
MPU1_SR[regID] = sreg;
}
break;
case 0x2000: /* FPU */
if (regID == FPST_REGNO)
{
unsigned int val = FPSR & ~(FPSR_PR | FPSR_XC | FPSR_XP);
val |= ((sreg & FPST_PR) ? FPSR_PR : 0)
| ((sreg & FPST_XCE) ? FPSR_XCE : 0)
| ((sreg & FPST_XCV) ? FPSR_XCV : 0)
| ((sreg & FPST_XCZ) ? FPSR_XCZ : 0)
| ((sreg & FPST_XCO) ? FPSR_XCO : 0)
| ((sreg & FPST_XCU) ? FPSR_XCU : 0)
| ((sreg & FPST_XCI) ? FPSR_XCI : 0)
| ((sreg & FPST_XPV) ? FPSR_XPV : 0)
| ((sreg & FPST_XPZ) ? FPSR_XPZ : 0)
| ((sreg & FPST_XPO) ? FPSR_XPO : 0)
| ((sreg & FPST_XPU) ? FPSR_XPU : 0)
| ((sreg & FPST_XPI) ? FPSR_XPI : 0);
FPSR = val;
}
else if (regID == FPCFG_REGNO)
{
unsigned int val = FPSR & ~(FPSR_RM | FPSR_XE);
val |= (((sreg & FPCFG_RM) >> 7) << 18)
| ((sreg & FPCFG_XEV) ? FPSR_XEV : 0)
| ((sreg & FPCFG_XEZ) ? FPSR_XEZ : 0)
| ((sreg & FPCFG_XEO) ? FPSR_XEO : 0)
| ((sreg & FPCFG_XEU) ? FPSR_XEU : 0)
| ((sreg & FPCFG_XEI) ? FPSR_XEI : 0);
FPSR = val;
}
FPU_SR[regID] = sreg;
break;
}
}
}
else
{
SR[regID] = sreg;
}
TRACE_ALU_RESULT (sreg);
}
// MAC
rrrrr,111111,RRRRR + wwww,0011110,mmmm,0:XI:::mac
*v850e2
*v850e2v3
*v850e3v5
"mac r<reg1>, r<reg2>, r<reg3e>, r<reg4e>"
{
unsigned long op0;
unsigned long op1;
unsigned long op2;
unsigned long op2hi;
unsigned long lo;
unsigned long mid1;
unsigned long mid2;
unsigned long hi;
unsigned long RdLo;
unsigned long RdHi;
int carry;
bfd_boolean sign;
op0 = GR[reg1];
op1 = GR[reg2];
op2 = GR[reg3e];
op2hi = GR[reg3e+1];
TRACE_ALU_INPUT4 (op0, op1, op2, op2hi);
sign = (op0 ^ op1) & 0x80000000;
if (((signed long) op0) < 0)
op0 = - op0;
if (((signed long) op1) < 0)
op1 = - op1;
/* We can split the 32x32 into four 16x16 operations. This ensures
that we do not lose precision on 32bit only hosts: */
lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF));
mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF));
mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF));
hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF));
/* We now need to add all of these results together, taking care
to propogate the carries from the additions: */
RdLo = Add32 (lo, (mid1 << 16), & carry);
RdHi = carry;
RdLo = Add32 (RdLo, (mid2 << 16), & carry);
RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
if (sign)
{
RdLo = ~ RdLo;
RdHi = ~ RdHi;
if (RdLo == 0xFFFFFFFF)
{
RdLo = 0;
RdHi += 1;
}
else
RdLo += 1;
}
RdLo = Add32 (RdLo, op2, & carry);
RdHi += carry + op2hi;
/* Store the result and condition codes. */
GR[reg4e] = RdLo;
GR[reg4e + 1 ] = RdHi;
TRACE_ALU_RESULT2 (RdLo, RdHi);
}
// MACU
rrrrr,111111,RRRRR + wwww,0011111,mmmm,0:XI:::macu
*v850e2
*v850e2v3
*v850e3v5
"macu r<reg1>, r<reg2>, r<reg3e>, r<reg4e>"
{
unsigned long op0;
unsigned long op1;
unsigned long op2;
unsigned long op2hi;
unsigned long lo;
unsigned long mid1;
unsigned long mid2;
unsigned long hi;
unsigned long RdLo;
unsigned long RdHi;
int carry;
op0 = GR[reg1];
op1 = GR[reg2];
op2 = GR[reg3e];
op2hi = GR[reg3e + 1];
TRACE_ALU_INPUT4 (op0, op1, op2, op2hi);
/* We can split the 32x32 into four 16x16 operations. This ensures
that we do not lose precision on 32bit only hosts: */
lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF));
mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF));
mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF));
hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF));
/* We now need to add all of these results together, taking care
to propogate the carries from the additions: */
RdLo = Add32 (lo, (mid1 << 16), & carry);
RdHi = carry;
RdLo = Add32 (RdLo, (mid2 << 16), & carry);
RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
RdLo = Add32 (RdLo, op2, & carry);
RdHi += carry + op2hi;
/* Store the result and condition codes. */
GR[reg4e] = RdLo;
GR[reg4e+1] = RdHi;
TRACE_ALU_RESULT2 (RdLo, RdHi);
}
// MOV
rrrrr!0,000000,RRRRR:I:::mov
"mov r<reg1>, r<reg2>"
{
TRACE_ALU_INPUT0 ();
GR[reg2] = GR[reg1];
TRACE_ALU_RESULT (GR[reg2]);
}
rrrrr!0,010000,iiiii:II:::mov
"mov <imm5>, r<reg2>"
{
COMPAT_1 (OP_200 ());
}
00000110001,RRRRR + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::mov
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"mov <imm32>, r<reg1>"
{
SAVE_2;
trace_input ("mov", OP_IMM_REG, 4);
State.regs[ OP[0] ] = load_mem (PC + 2, 4);
trace_output (OP_IMM_REG);
}
// MOVEA
rrrrr!0,110001,RRRRR + iiiiiiiiiiiiiiii:VI:::movea
"movea <simm16>, r<reg1>, r<reg2>"
{
TRACE_ALU_INPUT2 (GR[reg1], simm16);
GR[reg2] = GR[reg1] + simm16;
TRACE_ALU_RESULT (GR[reg2]);
}
// MOVHI
rrrrr!0,110010,RRRRR + iiiiiiiiiiiiiiii:VI:::movhi
"movhi <uimm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_640 ());
}
// MUL
rrrrr,111111,RRRRR + wwwww,01000100000:XI:::mul
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"mul r<reg1>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_22007E0 ());
}
rrrrr,111111,iiiii + wwwww,01001,IIII,00:XII:::mul
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"mul <imm9>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_24007E0 ());
}
// MULH
rrrrr!0,000111,RRRRR:I:::mulh
"mulh r<reg1>, r<reg2>"
{
COMPAT_1 (OP_E0 ());
}
rrrrr!0,010111,iiiii:II:::mulh
"mulh <imm5>, r<reg2>"
{
COMPAT_1 (OP_2E0 ());
}
// MULHI
rrrrr!0,110111,RRRRR + iiiiiiiiiiiiiiii:VI:::mulhi
"mulhi <uimm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_6E0 ());
}
// MULU
rrrrr,111111,RRRRR + wwwww,01000100010:XI:::mulu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"mulu r<reg1>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_22207E0 ());
}
rrrrr,111111,iiiii + wwwww,01001,IIII,10:XII:::mulu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"mulu <imm9>, r<reg2>, r<reg3>"
{
COMPAT_2 (OP_24207E0 ());
}
// NOP
0000000000000000:I:::nop
"nop"
{
/* do nothing, trace nothing */
}
// NOT
rrrrr,000001,RRRRR:I:::not
"not r<reg1>, r<reg2>"
{
COMPAT_1 (OP_20 ());
}
// NOT1
01,bbb,111110,RRRRR + dddddddddddddddd:VIII:::not1
"not1 <bit3>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_47C0 ());
}
rrrrr,111111,RRRRR + 0000000011100010:IX:::not1
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"not1 r<reg2>, r<reg1>"
{
COMPAT_2 (OP_E207E0 ());
}
// OR
rrrrr,001000,RRRRR:I:::or
"or r<reg1>, r<reg2>"
{
COMPAT_1 (OP_100 ());
}
// ORI
rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori
"ori <uimm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_680 ());
}
// PREPARE
0000011110,iiiii,L + LLLLLLLLLLL,00001:XIII:::prepare
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"prepare <list12>, <imm5>"
{
int i;
SAVE_2;
trace_input ("prepare", OP_PUSHPOP1, 0);
/* Store the registers with lower number registers being placed at
higher addresses. */
for (i = 0; i < 12; i++)
if ((OP[3] & (1 << type1_regs[ i ])))
{
SP -= 4;
store_mem (SP, 4, State.regs[ 20 + i ]);
}
SP -= (OP[3] & 0x3e) << 1;
trace_output (OP_PUSHPOP1);
}
0000011110,iiiii,L + LLLLLLLLLLL,00011:XIII:::prepare00
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"prepare <list12>, <imm5>, sp"
{
COMPAT_2 (OP_30780 ());
}
0000011110,iiiii,L + LLLLLLLLLLL,01011 + iiiiiiiiiiiiiiii:XIII:::prepare01
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"prepare <list12>, <imm5>, <uimm16>"
{
COMPAT_2 (OP_B0780 ());
}
0000011110,iiiii,L + LLLLLLLLLLL,10011 + iiiiiiiiiiiiiiii:XIII:::prepare10
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"prepare <list12>, <imm5>, <uimm16>"
{
COMPAT_2 (OP_130780 ());
}
0000011110,iiiii,L + LLLLLLLLLLL,11011 + iiiiiiiiiiiiiiii + dddddddddddddddd:XIII:::prepare11
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"prepare <list12>, <imm5>, <uimm32>"
{
COMPAT_2 (OP_1B0780 ());
}
// RETI
0000011111100000 + 0000000101000000:X:::reti
"reti"
{
if ((PSW & PSW_EP))
{
nia = (EIPC & ~1);
PSW = EIPSW;
}
else if ((PSW & PSW_NP))
{
nia = (FEPC & ~1);
PSW = FEPSW;
}
else
{
nia = (EIPC & ~1);
PSW = EIPSW;
}
TRACE_BRANCH1 (PSW);
}
// SAR
rrrrr,111111,RRRRR + 0000000010100000:IX:::sar
"sar r<reg1>, r<reg2>"
{
COMPAT_2 (OP_A007E0 ());
}
rrrrr,010101,iiiii:II:::sar
"sar <imm5>, r<reg2>"
{
COMPAT_1 (OP_2A0 ());
}
rrrrr,111111,RRRRR + wwwww,00010100010:XI:::sar
*v850e2
*v850e2v3
*v850e3v5
"sar r<reg1>, r<reg2>, r<reg3>"
{
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
v850_sar(sd, GR[reg1], GR[reg2], &GR[reg3]);
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SASF
rrrrr,1111110,cccc+0000001000000000:IX:::sasf
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"sasf %s<cccc>, r<reg2>"
{
COMPAT_2 (OP_20007E0 ());
}
// SATADD
rrrrr!0,000110,RRRRR:I:::satadd
"satadd r<reg1>, r<reg2>"
{
COMPAT_1 (OP_C0 ());
}
rrrrr!0,010001,iiiii:II:::satadd
"satadd <imm5>, r<reg2>"
{
COMPAT_1 (OP_220 ());
}
rrrrr,111111,RRRRR + wwwww,01110111010:XI:::satadd
*v850e2
*v850e2v3
*v850e3v5
"satadd r<reg1>, r<reg2>, r<reg3>"
{
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
v850_satadd (sd, GR[reg1], GR[reg2], &GR[reg3]);
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SATSUB
rrrrr!0,000101,RRRRR:I:::satsub
"satsub r<reg1>, r<reg2>"
{
COMPAT_1 (OP_A0 ());
}
rrrrr,111111,RRRRR + wwwww,01110011010:XI:::satsub
*v850e2
*v850e2v3
*v850e3v5
"satsub r<reg1>, r<reg2>, r<reg3>"
{
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
v850_satsub (sd, GR[reg1], GR[reg2], &GR[reg3]);
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SATSUBI
rrrrr!0,110011,RRRRR + iiiiiiiiiiiiiiii:VI:::satsubi
"satsubi <simm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_660 ());
}
// SATSUBR
rrrrr!0,000100,RRRRR:I:::satsubr
"satsubr r<reg1>, r<reg2>"
{
COMPAT_1 (OP_80 ());
}
//SBF
rrrrr,111111,RRRRR + wwwww,011100,cccc!13,0:XI:::sbf
*v850e2
*v850e2v3
*v850e3v5
"sbf %s<cccc>, r<reg1>, r<reg2>, r<reg3>"
{
int cond = condition_met (cccc);
TRACE_ALU_INPUT3 (cond, GR[reg1], GR[reg2]);
GR[reg3] = GR[reg2] - GR[reg1] - (cond ? 1 : 0);
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SCH0L
rrrrr,11111100000 + wwwww,01101100100:IX:::sch0l
*v850e2
*v850e2v3
*v850e3v5
"sch0l r<reg2>, r<reg3>"
{
unsigned int pos, op0;
TRACE_ALU_INPUT1 (GR[reg2]);
op0 = GR[reg2];
if (op0 == 0xffffffff)
{
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW |= PSW_Z;
pos = 0;
}
else if (op0 == 0xfffffffe)
{
PSW |= PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
pos = 32;
}
else
{
pos = 1;
while (op0 & 0x80000000)
{
op0 <<= 1;
pos++;
}
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
}
GR[reg3] = pos;
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SCH0R
rrrrr,11111100000 + wwwww,01101100000:IX:::sch0r
*v850e2
*v850e2v3
*v850e3v5
"sch0r r<reg2>, r<reg3>"
{
unsigned int pos, op0;
TRACE_ALU_INPUT1 (GR[reg2]);
op0 = GR[reg2];
if (op0 == 0xffffffff)
{
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW |= PSW_Z;
pos = 0;
}
else if (op0 == 0x7fffffff)
{
PSW |= PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
pos = 32;
}
else
{
pos = 1;
while (op0 & 0x00000001)
{
op0 >>= 1;
pos++;
}
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
}
GR[reg3] = pos;
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SCH1L
rrrrr,11111100000 + wwwww,01101100110:IX:::sch1l
*v850e2
*v850e2v3
*v850e3v5
"sch1l r<reg2>, r<reg3>"
{
unsigned int pos, op0;
TRACE_ALU_INPUT1 (GR[reg2]);
op0 = GR[reg2];
if (op0 == 0x00000000)
{
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW |= PSW_Z;
pos = 0;
}
else if (op0 == 0x00000001)
{
PSW |= PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
pos = 32;
}
else
{
pos = 1;
while (!(op0 & 0x80000000))
{
op0 <<= 1;
pos++;
}
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
}
GR[reg3] = pos;
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SCH1R
rrrrr,11111100000 + wwwww,01101100010:IX:::sch1r
*v850e2
*v850e2v3
*v850e3v5
"sch1r r<reg2>, r<reg3>"
{
unsigned int pos, op0;
TRACE_ALU_INPUT1 (GR[reg2]);
op0 = GR[reg2];
if (op0 == 0x00000000)
{
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW |= PSW_Z;
pos = 0;
}
else if (op0 == 0x80000000)
{
PSW |= PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
pos = 32;
}
else
{
pos = 1;
while (!(op0 & 0x00000001))
{
op0 >>= 1;
pos++;
}
PSW &= ~PSW_CY;
PSW &= ~PSW_OV;
PSW &= ~PSW_S;
PSW &= ~PSW_Z;
}
GR[reg3] = pos;
TRACE_ALU_RESULT1 (GR[reg3]);
}
//SHL
rrrrr,111111,RRRRR + wwwww,00011000010:XI:::shl
*v850e2
*v850e2v3
*v850e3v5
"shl r<reg1>, r<reg2>, r<reg3>"
{
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
v850_shl(sd, GR[reg1], GR[reg2], &GR[reg3]);
TRACE_ALU_RESULT1 (GR[reg3]);
}
//SHR
rrrrr,111111,RRRRR + wwwww,00010000010:XI:::shr
*v850e2
*v850e2v3
*v850e3v5
"shr r<reg1>, r<reg2>, r<reg3>"
{
TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]);
v850_shr(sd, GR[reg1], GR[reg2], &GR[reg3]);
TRACE_ALU_RESULT1 (GR[reg3]);
}
// SETF
rrrrr,1111110,cccc + 0000000000000000:IX:::setf
"setf %s<cccc>, r<reg2>"
{
COMPAT_2 (OP_7E0 ());
}
// SET1
00,bbb,111110,RRRRR + dddddddddddddddd:VIII:::set1
"set1 <bit3>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_7C0 ());
}
rrrrr,111111,RRRRR + 0000000011100000:IX:::set1
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"set1 r<reg2>, [r<reg1>]"
{
COMPAT_2 (OP_E007E0 ());
}
// SHL
rrrrr,111111,RRRRR + 0000000011000000:IX:::shl
"shl r<reg1>, r<reg2>"
{
COMPAT_2 (OP_C007E0 ());
}
rrrrr,010110,iiiii:II:::shl
"shl <imm5>, r<reg2>"
{
COMPAT_1 (OP_2C0 ());
}
// SHR
rrrrr,111111,RRRRR + 0000000010000000:IX:::shr
"shr r<reg1>, r<reg2>"
{
COMPAT_2 (OP_8007E0 ());
}
rrrrr,010100,iiiii:II:::shr
"shr <imm5>, r<reg2>"
{
COMPAT_1 (OP_280 ());
}
// SLD
rrrrr,0110,ddddddd:IV:::sld.b
"sld.bu <disp7>[ep], r<reg2>":(PSW & PSW_US)
"sld.b <disp7>[ep], r<reg2>"
{
unsigned32 addr = EP + disp7;
unsigned32 result = load_mem (addr, 1);
if (PSW & PSW_US)
{
GR[reg2] = result;
TRACE_LD_NAME ("sld.bu", addr, result);
}
else
{
result = EXTEND8 (result);
GR[reg2] = result;
TRACE_LD (addr, result);
}
}
rrrrr,1000,ddddddd:IV:::sld.h
"sld.hu <disp8>[ep], r<reg2>":(PSW & PSW_US)
"sld.h <disp8>[ep], r<reg2>"
{
unsigned32 addr = EP + disp8;
unsigned32 result = load_mem (addr, 2);
if (PSW & PSW_US)
{
GR[reg2] = result;
TRACE_LD_NAME ("sld.hu", addr, result);
}
else
{
result = EXTEND16 (result);
GR[reg2] = result;
TRACE_LD (addr, result);
}
}
rrrrr,1010,dddddd,0:IV:::sld.w
"sld.w <disp8>[ep], r<reg2>"
{
unsigned32 addr = EP + disp8;
unsigned32 result = load_mem (addr, 4);
GR[reg2] = result;
TRACE_LD (addr, result);
}
rrrrr!0,0000110,dddd:IV:::sld.bu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"sld.b <disp4>[ep], r<reg2>":(PSW & PSW_US)
"sld.bu <disp4>[ep], r<reg2>"
{
unsigned32 addr = EP + disp4;
unsigned32 result = load_mem (addr, 1);
if (PSW & PSW_US)
{
result = EXTEND8 (result);
GR[reg2] = result;
TRACE_LD_NAME ("sld.b", addr, result);
}
else
{
GR[reg2] = result;
TRACE_LD (addr, result);
}
}
rrrrr!0,0000111,dddd:IV:::sld.hu
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"sld.h <disp5>[ep], r<reg2>":(PSW & PSW_US)
"sld.hu <disp5>[ep], r<reg2>"
{
unsigned32 addr = EP + disp5;
unsigned32 result = load_mem (addr, 2);
if (PSW & PSW_US)
{
result = EXTEND16 (result);
GR[reg2] = result;
TRACE_LD_NAME ("sld.h", addr, result);
}
else
{
GR[reg2] = result;
TRACE_LD (addr, result);
}
}
// SST
rrrrr,0111,ddddddd:IV:::sst.b
"sst.b r<reg2>, <disp7>[ep]"
{
COMPAT_1 (OP_380 ());
}
rrrrr,1001,ddddddd:IV:::sst.h
"sst.h r<reg2>, <disp8>[ep]"
{
COMPAT_1 (OP_480 ());
}
rrrrr,1010,dddddd,1:IV:::sst.w
"sst.w r<reg2>, <disp8>[ep]"
{
COMPAT_1 (OP_501 ());
}
// ST
rrrrr,111010,RRRRR + dddddddddddddddd:VII:::st.b
"st.b r<reg2>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_740 ());
}
00000111100,RRRRR + wwwww,ddddddd,1101 + dddddddddddddddd:XIV:::st.b
*v850e2v3
*v850e3v5
"st.b r<reg3>, <disp23>[r<reg1>]"
{
unsigned32 addr = GR[reg1] + disp23;
store_data_mem (sd, addr, 1, GR[reg3]);
TRACE_ST (addr, GR[reg3]);
}
rrrrr,111011,RRRRR + ddddddddddddddd,0:VII:::st.h
"st.h r<reg2>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_760 ());
}
00000111101,RRRRR+wwwww,dddddd,01101+dddddddddddddddd:XIV:::st.h
*v850e2v3
*v850e3v5
"st.h r<reg3>, <disp23>[r<reg1>]"
{
unsigned32 addr = GR[reg1] + disp23;
store_data_mem (sd, addr, 2, GR[reg3]);
TRACE_ST (addr, GR[reg3]);
}
rrrrr,111011,RRRRR + ddddddddddddddd,1:VII:::st.w
"st.w r<reg2>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_10760 ());
}
00000111100,RRRRR+wwwww,dddddd,01111+dddddddddddddddd:XIV:::st.w
*v850e2v3
*v850e3v5
"st.w r<reg3>, <disp23>[r<reg1>]"
{
unsigned32 addr = GR[reg1] + disp23;
store_data_mem (sd, addr, 4, GR[reg3]);
TRACE_ST (addr, GR[reg3]);
}
00000111101,RRRRR+wwwww,dddddd,01111+dddddddddddddddd:XIV:::st.dw
*v850e3v5
"st.dw r<reg3>, <disp23>[r<reg1>]"
{
unsigned32 addr = GR[reg1] + disp23;
store_data_mem (sd, addr, 4, GR[reg3]);
TRACE_ST (addr, GR[reg3]);
store_data_mem (sd, addr + 4, 4, GR[reg3 + 1]);
TRACE_ST (addr + 4, GR[reg3 + 1]);
}
// STSR
rrrrr,111111,regID + 0000000001000000:IX:::stsr
"stsr s<regID>, r<reg2>"
{
uint32 sreg = 0;
if ((idecode_issue == idecode_v850e2_issue
|| idecode_issue == idecode_v850e3v5_issue
|| idecode_issue == idecode_v850e2v3_issue)
&& regID < 28)
{
switch (BSEL & 0xffff)
{
case 0x0000:
case 0xff00: /* USER 0 */
case 0xffff: /* USER 1 */
sreg = SR[regID];
break;
case 0x1000:
sreg = MPU0_SR[regID];
break;
case 0x1001:
sreg = MPU1_SR[regID];
break;
case 0x2000:
if (regID == FPST_REGNO)
{
sreg = ((FPSR & FPSR_PR) ? FPST_PR : 0)
| ((FPSR & FPSR_XCE) ? FPST_XCE : 0)
| ((FPSR & FPSR_XCV) ? FPST_XCV : 0)
| ((FPSR & FPSR_XCZ) ? FPST_XCZ : 0)
| ((FPSR & FPSR_XCO) ? FPST_XCO : 0)
| ((FPSR & FPSR_XCU) ? FPST_XCU : 0)
| ((FPSR & FPSR_XCI) ? FPST_XCI : 0)
| ((FPSR & FPSR_XPV) ? FPST_XPV : 0)
| ((FPSR & FPSR_XPZ) ? FPST_XPZ : 0)
| ((FPSR & FPSR_XPO) ? FPST_XPO : 0)
| ((FPSR & FPSR_XPU) ? FPST_XPU : 0)
| ((FPSR & FPSR_XPI) ? FPST_XPI : 0);
}
else if (regID == FPCFG_REGNO)
{
sreg = (((FPSR & FPSR_RM) >> 18) << 7)
| ((FPSR & FPSR_XEV) ? FPCFG_XEV : 0)
| ((FPSR & FPSR_XEZ) ? FPCFG_XEZ : 0)
| ((FPSR & FPSR_XEO) ? FPCFG_XEO : 0)
| ((FPSR & FPSR_XEU) ? FPCFG_XEU : 0)
| ((FPSR & FPSR_XEI) ? FPCFG_XEI : 0);
}
else
{
sreg = FPU_SR[regID];
}
break;
}
}
else
{
sreg = SR[regID];
}
TRACE_ALU_INPUT1 (sreg);
GR[reg2] = sreg;
TRACE_ALU_RESULT (GR[reg2]);
}
// SUB
rrrrr,001101,RRRRR:I:::sub
"sub r<reg1>, r<reg2>"
{
COMPAT_1 (OP_1A0 ());
}
// SUBR
rrrrr,001100,RRRRR:I:::subr
"subr r<reg1>, r<reg2>"
{
COMPAT_1 (OP_180 ());
}
// SWITCH
00000000010,RRRRR:I:::switch
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"switch r<reg1>"
{
unsigned long adr;
SAVE_1;
trace_input ("switch", OP_REG, 0);
adr = (cia + 2) + (State.regs[ reg1 ] << 1);
nia = (cia + 2) + (EXTEND16 (load_mem (adr, 2)) << 1);
trace_output (OP_REG);
}
// SXB
00000000101,RRRRR:I:::sxb
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"sxb r<reg1>"
{
TRACE_ALU_INPUT1 (GR[reg1]);
GR[reg1] = EXTEND8 (GR[reg1]);
TRACE_ALU_RESULT (GR[reg1]);
}
// SXH
00000000111,RRRRR:I:::sxh
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"sxh r<reg1>"
{
TRACE_ALU_INPUT1 (GR[reg1]);
GR[reg1] = EXTEND16 (GR[reg1]);
TRACE_ALU_RESULT (GR[reg1]);
}
// TRAP
00000111111,iiiii + 0000000100000000:X:::trap
"trap <vector>"
{
COMPAT_2 (OP_10007E0 ());
}
// TST
rrrrr,001011,RRRRR:I:::tst
"tst r<reg1>, r<reg2>"
{
COMPAT_1 (OP_160 ());
}
// TST1
11,bbb,111110,RRRRR + dddddddddddddddd:VIII:::tst1
"tst1 <bit3>, <disp16>[r<reg1>]"
{
COMPAT_2 (OP_C7C0 ());
}
rrrrr,111111,RRRRR + 0000000011100110:IX:::tst1
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"tst1 r<reg2>, [r<reg1>]"
{
COMPAT_2 (OP_E607E0 ());
}
// XOR
rrrrr,001001,RRRRR:I:::xor
"xor r<reg1>, r<reg2>"
{
COMPAT_1 (OP_120 ());
}
// XORI
rrrrr,110101,RRRRR + iiiiiiiiiiiiiiii:VI:::xori
"xori <uimm16>, r<reg1>, r<reg2>"
{
COMPAT_2 (OP_6A0 ());
}
// ZXB
00000000100,RRRRR:I:::zxb
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"zxb r<reg1>"
{
TRACE_ALU_INPUT1 (GR[reg1]);
GR[reg1] = GR[reg1] & 0xff;
TRACE_ALU_RESULT (GR[reg1]);
}
// ZXH
00000000110,RRRRR:I:::zxh
*v850e
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"zxh r<reg1>"
{
TRACE_ALU_INPUT1 (GR[reg1]);
GR[reg1] = GR[reg1] & 0xffff;
TRACE_ALU_RESULT (GR[reg1]);
}
// Right field must be zero so that it doesn't clash with DIVH
// Left field must be non-zero so that it doesn't clash with SWITCH
11111,000010,00000:I:::break
*v850
*v850e
{
sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP);
}
11111,000010,00000:I:::dbtrap
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"dbtrap"
{
if (STATE_OPEN_KIND (SD) == SIM_OPEN_DEBUG)
{
sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP);
}
else
{
DBPC = cia + 2;
DBPSW = PSW;
PSW = PSW | (PSW_NP | PSW_EP | PSW_ID);
PC = 0x00000060;
nia = 0x00000060;
TRACE_BRANCH0 ();
}
}
// New breakpoint: 0x7E0 0x7E0
00000,111111,00000 + 00000,11111,100000:X:::ilgop
{
sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP);
}
// Return from debug trap: 0x146007e0
0000011111100000 + 0000000101000110:X:::dbret
*v850e1
*v850e2
*v850e2v3
*v850e3v5
"dbret"
{
nia = DBPC;
PSW = DBPSW;
TRACE_BRANCH1 (PSW);
}
//
// FLOAT
//
// Map condition code to a string
:%s::::FFFF:int FFFF
{
switch (FFFF)
{
case 0: return "f";
case 1: return "un";
case 2: return "eq";
case 3: return "ueq";
case 4: return "olt";
case 5: return "ult";
case 6: return "ole";
case 7: return "ule";
case 8: return "sf";
case 9: return "ngle";
case 10: return "seq";
case 11: return "ngl";
case 12: return "lt";
case 13: return "nge";
case 14: return "le";
case 15: return "ngt";
}
return "(null)";
}
// ABSF.D
rrrr,011111100000 + wwww,010001011000:F_I:::absf_d
*v850e2v3
*v850e3v5
"absf.d r<reg2e>, r<reg3e>"
{
sim_fpu ans, wop;
sim_fpu_status status;
sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_abs (&ans, &wop);
check_invalid_snan(sd, status, 1);
sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// ABSF.S
rrrrr,11111100000 + wwwww,10001001000:F_I:::absf_s
*v850e2v3
*v850e3v5
"absf.s r<reg2>, r<reg3>"
{
sim_fpu ans, wop;
sim_fpu_status status;
sim_fpu_32to (&wop, GR[reg2]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_abs (&ans, &wop);
check_invalid_snan(sd, status, 0);
sim_fpu_to32 (&GR[reg3], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// ADDF.D
rrrr,0111111,RRRR,0 + wwww,010001110000:F_I:::addf_d
*v850e2v3
*v850e3v5
"addf.d r<reg1e>, r<reg2e>, r<reg3e>"
{
sim_fpu ans, wop1, wop2;
sim_fpu_status status;
sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]);
sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU2 (&wop1, &wop2);
status = sim_fpu_add (&ans, &wop1, &wop2);
status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1);
sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// ADDF.S
rrrrr,111111,RRRRR + wwwww,10001100000:F_I:::addf_s
*v850e2v3
*v850e3v5
"addf.s r<reg1>, r<reg2>, r<reg3>"
{
sim_fpu ans, wop1, wop2;
sim_fpu_status status;
sim_fpu_32to (&wop1, GR[reg1]);
sim_fpu_32to (&wop2, GR[reg2]);
TRACE_FP_INPUT_FPU2 (&wop1, &wop2);
status = sim_fpu_add (&ans, &wop1, &wop2);
status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0);
sim_fpu_to32 (&GR[reg3], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// CMOVF.D
rrrr,0111111,RRRR,0 + wwww!0,01000001,bbb,0:F_I:::cmovf_d
*v850e2v3
*v850e3v5
"cmovf.d <bbb>, r<reg1e>, r<reg2e>, r<reg3e>"
{
unsigned int ophi,oplow;
sim_fpu ans, wop1, wop2;
sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]);
sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_BOOL1_FPU2 (TEST_FPCC(bbb), &wop1, &wop2);
if (TEST_FPCC(bbb))
{
ophi = GR[reg1e+1];
oplow = GR[reg1e];
ans = wop1;
}
else
{
ophi = GR[reg2e+1];
oplow = GR[reg2e];
ans = wop2;
}
GR[reg3e+1] = ophi;
GR[reg3e] = oplow;
TRACE_FP_RESULT_FPU1 (&ans);;
}
// CMOVF.S
rrrrr,111111,RRRRR!0 + wwwww!0,1000000,bbb,0:F_I:::cmovf_s
*v850e2v3
*v850e3v5
"cmovf.d <bbb>, r<reg1>, r<reg2>, r<reg3>"
{
unsigned int op;
sim_fpu ans, wop1, wop2;
sim_fpu_32to (&wop1, GR[reg1]);
sim_fpu_32to (&wop2, GR[reg2]);
TRACE_FP_INPUT_BOOL1_FPU2 (TEST_FPCC(bbb), &wop1, &wop2);
if (TEST_FPCC(bbb))
{
op = GR[reg1];
ans = wop1;
}
else
{
op = GR[reg2];
ans = wop2;
}
GR[reg3] = op;
TRACE_FP_RESULT_FPU1 (&ans);
}
// CMPF.D
rrrr,0111111,RRRR,0 + 0,FFFF,1000011,bbb,0:F_I:::cmpf_d
*v850e2v3
*v850e3v5
"cmpf.d %s<FFFF>, r<reg2e>, r<reg1e>":(bbb == 0)
"cmpf.d %s<FFFF>, r<reg2e>, r<reg1e>, <bbb>"
{
int result;
sim_fpu wop1;
sim_fpu wop2;
sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]);
sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU2 (&wop2, &wop1);
result = v850_float_compare(sd, FFFF, wop2, wop1, 1);
if (result)
SET_FPCC(bbb);
else
CLEAR_FPCC(bbb);
TRACE_FP_RESULT_BOOL (result);
}
// CMPF.S
rrrrr,111111,RRRRR + 0,FFFF,1000010,bbb,0:F_I:::cmpf_s
*v850e2v3
*v850e3v5
"cmpf.s %s<FFFF>, r<reg2>, r<reg1>":(bbb == 0)
"cmpf.s %s<FFFF>, r<reg2>, r<reg1>, <bbb>"
{
int result;
sim_fpu wop1;
sim_fpu wop2;
sim_fpu_32to( &wop1, GR[reg1] );
sim_fpu_32to( &wop2, GR[reg2] );
TRACE_FP_INPUT_FPU2 (&wop2, &wop1);
result = v850_float_compare(sd, FFFF, wop2, wop1, 0);
if (result)
SET_FPCC(bbb);
else
CLEAR_FPCC(bbb);
TRACE_FP_RESULT_BOOL (result);
}
// CVTF.DL
rrrr,011111100100 + wwww,010001010100:F_I:::cvtf_dl
*v850e2v3
*v850e3v5
"cvtf.dl r<reg2e>, r<reg3e>"
{
signed64 ans;
sim_fpu wop;
sim_fpu_status status;
sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
status |= sim_fpu_to64i (&ans, &wop, FPSR_GET_ROUND());
check_cvt_fi(sd, status, 1);
GR[reg3e] = ans;
GR[reg3e+1] = ans>>32L;
TRACE_FP_RESULT_WORD2 (GR[reg3e], GR[reg3e+1]);
}
// CVTF.DS
rrrr,011111100011 + wwwww,10001010010:F_I:::cvtf_ds
*v850e2v3
*v850e3v5
"cvtf.ds r<reg2e>, r<reg3>"
{
sim_fpu wop;
sim_fpu_status status;
sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
check_cvt_fi(sd, status, 0);
sim_fpu_to32 (&GR[reg3], &wop);
TRACE_FP_RESULT_FPU1 (&wop);
}
// CVTF.DW
rrrr,011111100100 + wwwww,10001010000:F_I:::cvtf_dw
*v850e2v3
*v850e3v5
"cvtf.dw r<reg2e>, r<reg3>"
{
int32 ans;
sim_fpu wop;
sim_fpu_status status;
sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
status |= sim_fpu_to32i (&ans, &wop, FPSR_GET_ROUND());
check_cvt_fi(sd, status, 1);
GR[reg3] = ans;
TRACE_FP_RESULT_WORD1 (ans);
}
// CVTF.LD
rrrr,011111100001 + wwww,010001010010:F_I:::cvtf_ld
*v850e2v3
*v850e3v5
"cvtf.ld r<reg2e>, r<reg3e>"
{
signed64 op;
sim_fpu wop;
sim_fpu_status status;
op = ((signed64)GR[reg2e+1] << 32L) | GR[reg2e];
TRACE_FP_INPUT_WORD2 (GR[reg2e], GR[reg2e+1]);
sim_fpu_i64to (&wop, op, FPSR_GET_ROUND());
status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
check_cvt_if(sd, status, 1);
sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &wop);
TRACE_FP_RESULT_FPU1 (&wop);
}
// CVTF.LS
rrrr,011111100001 + wwwww,10001000010:F_I:::cvtf_ls
*v850e2v3
*v850e3v5
"cvtf.ls r<reg2e>, r<reg3>"
{
signed64 op;
sim_fpu wop;
sim_fpu_status status;
op = ((signed64)GR[reg2e+1] << 32L) | GR[reg2e];
TRACE_FP_INPUT_WORD2 (GR[reg2e], GR[reg2e+1]);
sim_fpu_i64to (&wop, op, FPSR_GET_ROUND());
status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
check_cvt_if(sd, status, 0);
sim_fpu_to32 (&GR[reg3], &wop);
TRACE_FP_RESULT_FPU1 (&wop);
}
// CVTF.SD
rrrrr,11111100010 + wwww,010001010010:F_I:::cvtf_sd
*v850e2v3
*v850e3v5
"cvtf.sd r<reg2>, r<reg3e>"
{
sim_fpu wop;
sim_fpu_status status;
sim_fpu_32to (&wop, GR[reg2]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
check_cvt_ff(sd, status, 1);
sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &wop);
TRACE_FP_RESULT_FPU1 (&wop);
}
// CVTF.SL
rrrrr,11111100100 + wwww,010001000100:F_I:::cvtf_sl
*v850e2v3
*v850e3v5
"cvtf.sl r<reg2>, r<reg3e>"
{
signed64 ans;
sim_fpu wop;
sim_fpu_status status;
sim_fpu_32to (&wop, GR[reg2]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
status |= sim_fpu_to64i (&ans, &wop, FPSR_GET_ROUND());
check_cvt_fi(sd, status, 0);
GR[reg3e] = ans;
GR[reg3e+1] = ans >> 32L;
TRACE_FP_RESULT_WORD2 (GR[reg3e], GR[reg3e+1]);
}
// CVTF.SW
rrrrr,11111100100 + wwwww,10001000000:F_I:::cvtf_sw
*v850e2v3
*v850e3v5
"cvtf.sw r<reg2>, r<reg3>"
{
int32 ans;
sim_fpu wop;
sim_fpu_status status;
sim_fpu_32to (&wop, GR[reg2]);
TRACE_FP_INPUT_FPU1 (&wop);
status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
status |= sim_fpu_to32i (&ans, &wop, sim_fpu_round_zero);
check_cvt_fi(sd, status, 0);
GR[reg3] = ans;
TRACE_FP_RESULT_WORD1 (ans);
}
// CVTF.WD
rrrrr,11111100000 + wwww,010001010010:F_I:::cvtf_wd
*v850e2v3
*v850e3v5
"cvtf.wd r<reg2>, r<reg3e>"
{
sim_fpu wop;
sim_fpu_status status;
TRACE_FP_INPUT_WORD1 (GR[reg2]);
sim_fpu_i32to (&wop, GR[reg2], FPSR_GET_ROUND());
status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
check_cvt_if(sd, status, 1);
sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &wop);
TRACE_FP_RESULT_FPU1 (&wop);
}
// CVTF.WS
rrrrr,11111100000 + wwwww,10001000010:F_I:::cvtf_ws
*v850e2v3
*v850e3v5
"cvtf.ws r<reg2>, r<reg3>"
{
sim_fpu wop;
sim_fpu_status status;
TRACE_FP_INPUT_WORD1 (GR[reg2]);
sim_fpu_i32to (&wop, GR[reg2], FPSR_GET_ROUND());
status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero);
check_cvt_if(sd, status, 0);
sim_fpu_to32 (&GR[reg3], &wop);
TRACE_FP_RESULT_FPU1 (&wop);
}
// DIVF.D
rrrr,0111111,RRRR,0 + wwww,010001111110:F_I:::divf_d
*v850e2v3
*v850e3v5
"divf.d r<reg1e>, r<reg2e>, r<reg3e>"
{
sim_fpu ans, wop1, wop2;
sim_fpu_status status;
sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]);
sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU2 (&wop1, &wop2);
status = sim_fpu_div (&ans, &wop2, &wop1);
status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1);
sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// DIVF.S
rrrrr,111111,RRRRR + wwwww,10001101110:F_I:::divf_s
*v850e2v3
*v850e3v5
"divf.s r<reg1>, r<reg2>, r<reg3>"
{
sim_fpu ans, wop1, wop2;
sim_fpu_status status;
sim_fpu_32to (&wop1, GR[reg1]);
sim_fpu_32to (&wop2, GR[reg2]);
TRACE_FP_INPUT_FPU2 (&wop1, &wop2);
status = sim_fpu_div (&ans, &wop2, &wop1);
status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0);
sim_fpu_to32 (&GR[reg3], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// MADDF.S
rrrrr,111111,RRRRR + wwwww,101,W,00,WWWW,0:F_I:::maddf_s
*v850e2v3
"maddf.s r<reg1>, r<reg2>, r<reg3>, r<reg4>"
{
sim_fpu ans, wop1, wop2, wop3;
sim_fpu_status status;
sim_fpu_32to (&wop1, GR[reg1]);
sim_fpu_32to (&wop2, GR[reg2]);
sim_fpu_32to (&wop3, GR[reg3]);
TRACE_FP_INPUT_FPU3 (&wop1, &wop2, &wop3);
status = sim_fpu_mul (&ans, &wop1, &wop2);
wop1 = ans;
status |= sim_fpu_add (&ans, &wop1, &wop3);
status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0);
sim_fpu_to32 (&GR[reg4], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// FMAF.S
rrrrr,111111,RRRRR + wwwww,10011100000:F_I:::fmaf_s
*v850e3v5
"fmaf.s r<reg1>, r<reg2>, r<reg3>"
{
sim_fpu ans, wop1, wop2, wop3;
sim_fpu_status status;
sim_fpu_32to (&wop1, GR[reg1]);
sim_fpu_32to (&wop2, GR[reg2]);
sim_fpu_32to (&wop3, GR[reg3]);
TRACE_FP_INPUT_FPU3 (&wop1, &wop2, &wop3);
status = sim_fpu_mul (&ans, &wop1, &wop2);
wop1 = ans;
status |= sim_fpu_add (&ans, &wop1, &wop3);
status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact);
update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0);
sim_fpu_to32 (&GR[reg3], &ans);
TRACE_FP_RESULT_FPU1 (&ans);
}
// MAXF.D
rrrr,0111111,RRRR,0 + wwww,010001111000:F_I:::maxf_d
*v850e2v3
*v850e3v5
"maxf.d r<reg1e>, r<reg2e>, r<reg3e>"
{
sim_fpu ans, wop1, wop2;
sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]);
sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]);
TRACE_FP_INPUT_FPU2 (&wop1, &wop2);
if (sim_fpu_is_nan(&wop1) || sim_fpu_is_nan(&wop2))
{
if (FPSR & FPSR_XEV)
{
SignalExceptionFPE(sd, 1);
}
else