diff options
Diffstat (limited to 'sim/v850/v850.igen')
-rw-r--r-- | sim/v850/v850.igen | 1407 |
1 files changed, 1407 insertions, 0 deletions
diff --git a/sim/v850/v850.igen b/sim/v850/v850.igen new file mode 100644 index 0000000..724b0be --- /dev/null +++ b/sim/v850/v850.igen @@ -0,0 +1,1407 @@ +: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 + + +:model:::v850:v850: + +:option:::multi-sim:true +:model:::v850e:v850e: + +:option:::multi-sim:true +:model:::v850ea:v850ea: + + + +// Cache macros + +:cache:::unsigned:reg1:RRRRR:(RRRRR) +:cache:::unsigned:reg2:rrrrr:(rrrrr) +:cache:::unsigned:reg3:wwwww:(wwwww) + +: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:disp22:dddddd,ddddddddddddddd: SEXT32 ((dddddd << 16) + (ddddddddddddddd << 1), 22 - 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 + + +// 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 ()); +} + + + +// 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 = condition_met (cccc); + if (cond) + nia = cia + disp9; + TRACE_BRANCH1 (cond); +} + + + +// BSH +rrrrr,11111100000 + wwwww,01101000010:XII:::bsh +*v850e +*v850ea +"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 == 0) PSW |= PSW_Z; + if (value & 0x80000000) PSW |= PSW_S; + if (((value & 0xff) == 0) || (value & 0x00ff) == 0) PSW |= PSW_CY; + + TRACE_ALU_RESULT (GR[reg3]); +} + +// BSW +rrrrr,11111100000 + wwwww,01101000000:XII:::bsw +*v850e +*v850ea +"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 +*v850ea +"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); +} + + +// CLR1 +10,bbb,111110,RRRRR + dddddddddddddddd:VIII:::clr1 +"clr1 <bit3>, <disp16>[r<reg1>]" +{ + COMPAT_2 (OP_87C0 ()); +} + +rrrrr,111111,RRRRR + 0000000011100100:IX:::clr1 +*v850e +*v850ea +"clr1 r<reg2>, [r<reg1>]" +{ + COMPAT_2 (OP_E407E0 ()); +} + + +// CTRET +0000011111100000 + 0000000101000100:X:::ctret +*v850e +*v850ea +"ctret" +{ + nia = (CTPC & ~1); + PSW = (CTPSW & (CPU)->psw_mask); + TRACE_BRANCH1 (PSW); +} + +// CMOV +rrrrr,111111,RRRRR + wwwww,011001,cccc,0:XI:::cmov +*v850e +*v850ea +"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 +*v850ea +"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 +*v850ea +"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 +"div r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_2C007E0 ()); +} + + +// DIVH +rrrrr!0,000010,RRRRR!0:I:::divh +"divh r<reg1>, r<reg2>" +{ + COMPAT_1 (OP_40 ()); +} + +rrrrr,111111,RRRRR + wwwww,01010000000:XI:::divh +*v850e +"divh r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_28007E0 ()); +} + + +// DIVHU +rrrrr,111111,RRRRR + wwwww,01010000010:XI:::divhu +*v850e +"divhu r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_28207E0 ()); +} + + +// DIVU +rrrrr,111111,RRRRR + wwwww,01011000010:XI:::divu +*v850e +"divu r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_2C207E0 ()); +} + + +// EI +1000011111100000 + 0000000101100000:X:::ei +"ei" +{ + COMPAT_2 (OP_16087E0 ()); +} + + + +// HALT +0000011111100000 + 0000000100100000:X:::halt +"halt" +{ + COMPAT_2 (OP_12007E0 ()); +} + + + +// HSW +rrrrr,11111100000 + wwwww,01101000100:XII:::hsw +*v850e +*v850ea +"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]); +} + + + +// JMP +00000000011,RRRRR:I:::jmp +"jmp [r<reg1>]" +{ + nia = GR[reg1] & ~1; + TRACE_BRANCH0 (); +} + + + +// JR +0000011110,dddddd + ddddddddddddddd,0:V:::jr +"jr <disp22>" +{ + nia = cia + disp22; + TRACE_BRANCH0 (); +} + + + +// LD +rrrrr,111000,RRRRR + dddddddddddddddd:VII:::ld.b +"ld.b <disp16>[r<reg1>], r<reg2>" +{ + COMPAT_2 (OP_700 ()); +} + +rrrrr,111001,RRRRR + ddddddddddddddd,0:VII:::ld.h +"ld.h <disp16>[r<reg1>], r<reg2>" +{ + COMPAT_2 (OP_720 ()); +} + +rrrrr,111001,RRRRR + ddddddddddddddd,1:VII:::ld.w +"ld.w <disp16>[r<reg1>], r<reg2>" +{ + COMPAT_2 (OP_10720 ()); +} + +rrrrr!0,11110,b,RRRRR + ddddddddddddddd,1:VII:::ld.bu +*v850e +*v850ea +"ld.bu <disp16>[r<reg1>], r<reg2>" +{ + COMPAT_2 (OP_10780 ()); +} + +rrrrr!0,111111,RRRRR + ddddddddddddddd,1:VII:::ld.hu +*v850e +*v850ea +"ld.hu <disp16>[r<reg1>], r<reg2>" +{ + COMPAT_2 (OP_107E0 ()); +} + + +// LDSR +regID,111111,RRRRR + 0000000000100000:IX:::ldsr +"ldsr r<reg1>, s<regID>" +{ + TRACE_ALU_INPUT1 (GR[reg1]); + + if (&PSW == &SR[regID]) + PSW = (GR[reg1] & (CPU)->psw_mask); + else + SR[regID] = GR[reg1]; + + TRACE_ALU_RESULT (SR[regID]); +} + + + +// 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 +*v850ea +"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 +*v850ea +"mul r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_22007E0 ()); +} + +rrrrr,111111,iiiii + wwwww,01001,IIII,00:XII:::mul +*v850e +*v850ea +"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 +*v850ea +"mulu r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_22207E0 ()); +} + +rrrrr,111111,iiiii + wwwww,01001,IIII,10:XII:::mulu +*v850e +*v850ea +"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 +*v850ea +"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 +*v850ea +"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 +*v850ea +"prepare <list12>, <imm5>, sp" +{ + COMPAT_2 (OP_30780 ()); +} + +0000011110,iiiii,L + LLLLLLLLLLL,01011 + iiiiiiiiiiiiiiii:XIII:::prepare01 +*v850e +*v850ea +"prepare <list12>, <imm5>, <uimm16>" +{ + COMPAT_2 (OP_B0780 ()); +} + +0000011110,iiiii,L + LLLLLLLLLLL,10011 + iiiiiiiiiiiiiiii:XIII:::prepare10 +*v850e +*v850ea +"prepare <list12>, <imm5>, <uimm16>" +{ + COMPAT_2 (OP_130780 ()); +} + +0000011110,iiiii,L + LLLLLLLLLLL,11011 + iiiiiiiiiiiiiiii + dddddddddddddddd:XIII:::prepare11 +*v850e +*v850ea +"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 ()); +} + + + +// SASF +rrrrr,1111110,cccc + 0000001000000000:IX:::sasf +*v850e +*v850ea +"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 ()); +} + + + +// SATSUB +rrrrr!0,000101,RRRRR:I:::satsub +"satsub r<reg1>, r<reg2>" +{ + COMPAT_1 (OP_A0 ()); +} + + + +// 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 ()); +} + + + +// 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 +*v850ea +"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 +*v850ea +"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 +*v850ea +"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 ()); +} + +rrrrr,111011,RRRRR + ddddddddddddddd,0:VII:::st.h +"st.h r<reg2>, <disp16>[r<reg1>]" +{ + COMPAT_2 (OP_760 ()); +} + +rrrrr,111011,RRRRR + ddddddddddddddd,1:VII:::st.w +"st.w r<reg2>, <disp16>[r<reg1>]" +{ + COMPAT_2 (OP_10760 ()); +} + + + +// STSR +rrrrr,111111,regID + 0000000001000000:IX:::stsr +"stsr s<regID>, r<reg2>" +{ + TRACE_ALU_INPUT1 (SR[regID]); + GR[reg2] = SR[regID]; + 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 +*v850ea +"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 +*v850ea +"sxb r<reg1>" +{ + TRACE_ALU_INPUT1 (GR[reg1]); + GR[reg1] = EXTEND8 (GR[reg1]); + TRACE_ALU_RESULT (GR[reg1]); +} + +// SXH +00000000111,RRRRR:I:::sxh +*v850e +*v850ea +"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 +*v850ea +"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 +*v850ea +"zxb r<reg1>" +{ + TRACE_ALU_INPUT1 (GR[reg1]); + GR[reg1] = GR[reg1] & 0xff; + TRACE_ALU_RESULT (GR[reg1]); +} + +// ZXH +00000000110,RRRRR:I:::zxh +*v850e +*v850ea +"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 +{ + sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP); +} + + + +// DIVHN +rrrrr,111111,RRRRR + wwwww,01010,iiii,00:XI:::divhn +*v850ea +"divhn <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + signed32 quotient; + signed32 remainder; + signed32 divide_by; + signed32 divide_this; + boolean overflow = false; + SAVE_2; + + trace_input ("divhn", OP_IMM_REG_REG_REG, 0); + + divide_by = EXTEND16 (State.regs[ reg1 ]); + divide_this = State.regs[ reg2 ]; + + divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ reg2 ] = quotient; + State.regs[ reg3 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); +} + + + +// DIVHUN +rrrrr,111111,RRRRR + wwwww,01010,iiii,10:XI:::divhun +*v850ea +"divhun <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + signed32 quotient; + signed32 remainder; + signed32 divide_by; + signed32 divide_this; + boolean overflow = false; + SAVE_2; + + trace_input ("divhun", OP_IMM_REG_REG_REG, 0); + + divide_by = State.regs[ reg1 ] & 0xffff; + divide_this = State.regs[ reg2 ]; + + divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ reg2 ] = quotient; + State.regs[ reg3 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); +} + + + +// DIVN +rrrrr,111111,RRRRR + wwwww,01011,iiii,00:XI:::divn +*v850ea +"divn <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + signed32 quotient; + signed32 remainder; + signed32 divide_by; + signed32 divide_this; + boolean overflow = false; + SAVE_2; + + trace_input ("divn", OP_IMM_REG_REG_REG, 0); + + divide_by = State.regs[ reg1 ]; + divide_this = State.regs[ reg2 ]; + + divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ reg2 ] = quotient; + State.regs[ reg3 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); +} + + + +// DIVUN +rrrrr,111111,RRRRR + wwwww,01011,iiii,10:XI:::divun +*v850ea +"divun <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + signed32 quotient; + signed32 remainder; + signed32 divide_by; + signed32 divide_this; + boolean overflow = false; + SAVE_2; + + trace_input ("divun", OP_IMM_REG_REG_REG, 0); + + divide_by = State.regs[ reg1 ]; + divide_this = State.regs[ reg2 ]; + + divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow); + + State.regs[ reg2 ] = quotient; + State.regs[ reg3 ] = remainder; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + + trace_output (OP_IMM_REG_REG_REG); +} + + + +// SDIVHN +rrrrr,111111,RRRRR + wwwww,00110,iiii,00:XI:::sdivhn +*v850ea +"sdivhn <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_18007E0 ()); +} + + + +// SDIVHUN +rrrrr,111111,RRRRR + wwwww,00110,iiii,10:XI:::sdivhun +*v850ea +"sdivhun <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_18207E0 ()); +} + + + +// SDIVN +rrrrr,111111,RRRRR + wwwww,00111,iiii,00:XI:::sdivn +*v850ea +"sdivn <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_1C007E0 ()); +} + + + +// SDIVUN +rrrrr,111111,RRRRR + wwwww,00111,iiii,10:XI:::sdivun +*v850ea +"sdivun <imm5>, r<reg1>, r<reg2>, r<reg3>" +{ + COMPAT_2 (OP_1C207E0 ()); +} + + + +// PUSHML +000001111110,LLLL + LLLLLLLLLLLL,S,001:XIV:::pushml +*v850ea +"pushml <list18>" +{ + int i; + SAVE_2; + + trace_input ("pushml", OP_PUSHPOP3, 0); + + /* Store the registers with lower number registers being placed at + higher addresses. */ + + for (i = 0; i < 15; i++) + if ((OP[3] & (1 << type3_regs[ i ]))) + { + SP -= 4; + store_mem (SP & ~ 3, 4, State.regs[ i + 1 ]); + } + + if (OP[3] & (1 << 3)) + { + SP -= 4; + + store_mem (SP & ~ 3, 4, PSW); + } + + if (OP[3] & (1 << 19)) + { + SP -= 8; + + if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0)) + { + store_mem ((SP + 4) & ~ 3, 4, FEPC); + store_mem ( SP & ~ 3, 4, FEPSW); + } + else + { + store_mem ((SP + 4) & ~ 3, 4, EIPC); + store_mem ( SP & ~ 3, 4, EIPSW); + } + } + + trace_output (OP_PUSHPOP2); +} + + + +// PUSHHML +000001111110,LLLL + LLLLLLLLLLLL,S,011:XIV:::pushmh +*v850ea +"pushhml <list18>" +{ + COMPAT_2 (OP_307E0 ()); +} + + + +// POPML +000001111111,LLLL + LLLLLLLLLLLL,S,001:XIV:::popml +*v850ea +"popml <list18>" +{ + COMPAT_2 (OP_107F0 ()); +} + + + +// POPMH +000001111111,LLLL + LLLLLLLLLLLL,S,011:XIV:::popmh +*v850ea +"popmh <list18>" +{ + COMPAT_2 (OP_307F0 ()); +} + |