diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 3a7dbb4a45..4a9e173133 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -700,6 +700,100 @@ macro extendedResultFlags(result) { ZF = (result == 0) && (ZF == 1); } +macro arithmeticShiftLeft(count, register, width) { + local modcount = count % 64; + CF = 0; + resflags(register); + if (count == 0) goto inst_next; + local msbBefore:4 = zext(register) >> (width - 1); + getbit(CF, register, width - modcount); + register = register << modcount; + resflags(register); + local msbAfter:4 = zext(register) >> (width - 1); + VF = (msbBefore ^ msbAfter) != 0; + XF = CF; +} + +macro arithmeticShiftRight(count, register, width) { + local modcount = count % 64; + CF = 0; + resflags(register); + if (count == 0) goto inst_next; + local msbBefore:4 = zext(register) >> (width - 1); + getbit(CF, register, modcount - 1); + register = register s>> modcount; + resflags(register); + local msbAfter:4 = zext(register) >> (width - 1); + VF = (msbBefore ^ msbAfter) != 0; + XF = CF; +} + +macro logicalShiftLeft(count, register, width) { + local modcount = count % 64; + CF = 0; + VF = 0; + resflags(register); + if (modcount == 0) goto inst_next; + getbit(CF, register, width - modcount); + register = register << modcount; + resflags(register); + XF = CF; +} + +macro logicalShiftRight(count, register, width) { + local modcount = count % 64; + CF = 0; + VF = 0; + resflags(register); + if (modcount == 0) goto inst_next; + getbit(CF, register, width - modcount); + register = register >> modcount; + resflags(register); + XF = CF; +} + +macro rotateLeft(count, register, width) { + local modcount = (count % 64) % width; + VF = 0; + register = (register << modcount) | (register >> (width - modcount)); + getbit(CF, register, width - 1); + resflags(register); +} + +macro rotateRight(count, register, width) { + local modcount = (count % 64) % width; + VF = 0; + register = (register << (width - modcount)) | (register >> modcount); + getbit(CF, register, 0); + resflags(register); +} + +macro rotateLeftExtended(count, register, width) { + local modcount = (count % 64) % width; + CF = XF; + VF = 0; + resflags(register); + if (modcount == 0) goto inst_next; + local xflag = (register & (1 << (width - modcount))) != 0; + register = (register << modcount) | (zext(XF) << (modcount - 1)) | (register >> (width - modcount + 1)); + XF = xflag; + CF = XF; + resflags(register); +} + +macro rotateRightExtended(count, register, width) { + local modcount = (count % 64) % width; + CF = XF; + VF = 0; + resflags(register); + if (modcount == 0) goto inst_next; + local xflag = (register & (1 << (modcount - 1))) != 0; + register = (zext(XF) << (width - modcount)) | (register >> modcount) | (register << (width - modcount + 1)); + XF = xflag; + CF = XF; + resflags(register); +} + :^instruction is extGUARD=0 & mode2 & reg9an & mode & regan & instruction [ extGUARD=1; regtfan=regan; savmod1=mode; regtsan=reg9an; savmod2=mode2; ] {} @@ -751,15 +845,35 @@ with : extGUARD=1 { :andi const8,"CCR" is d16=0x23c; const8 { packflags(SR); SR = SR & zext(const8); unpackflags(SR); } :andi const16,SR is opbig=0x2 & d8base=0x7c; const16 & SR { packflags(SR); SR = SR & const16; unpackflags(SR); } -:asl.b cntreg,regdnb is op=14 & cntreg & op8=1 & op67=0 & op34=0 & regdnb { getbit(CF,regdnb,8-cntreg); regdnb=regdnb<>cntreg; resflags(regdnb);} -:asr.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=0 & regdnw { getbit(CF,regdnw,cntreg-1);regdnw=regdnw s>>cntreg; resflags(regdnw);} -:asr.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=0 & regdn { getbit(CF,regdn,cntreg-1); regdn=regdn s>>cntreg; resflags(regdn); } -:asr eaw is (opbig=0xe0 & op67=3 & $(MEM_ALTER_ADDR_MODES))... & eaw { getbit(CF,eaw,0); eaw=eaw s>>1; resflags(eaw); } +:asr.b cntreg,regdnb is op=14 & cntreg & op8=0 & op67=0 & op34=0 & regdnb { arithmeticShiftRight(cntreg, regdnb, 8); } +:asr.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=0 & regdnw { arithmeticShiftRight(cntreg, regdnw, 16); } +:asr.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=0 & regdn { arithmeticShiftRight(cntreg, regdn, 32); } +:asr eaw is (opbig=0xe0 & op67=3 & $(MEM_ALTER_ADDR_MODES)) ... & eaw { + local value:2 = eaw; + local msbBefore = value & 0x8000; + getbit(CF, value, 0); + value = value s>> 1; + resflags(value); + local msbAfter = value & 0x8000; + VF = (msbBefore ^ msbAfter) != 0; + eaw = value; + XF = CF; +} :b^cc^".b" addr8 is op=6 & cc & addr8 { if (cc) goto addr8; } :b^cc^".w" addr16 is op=6 & cc & d8base=0; addr16 { if (cc) goto addr16; } @@ -1173,15 +1287,31 @@ macro shiftCXFlags(cntreg) { XF = CF * (cntreg != 0) + XF * (cntreg == 0); } -:lsl.b cntreg,regdnb is op=14 & cntreg & op8=1 & op67=0 & op34=1 & regdnb { getbit(CF,regdnb,8-cntreg); shiftCXFlags(cntreg); regdnb=regdnb<>cntreg; resflags(regdnb);} -:lsr.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=1 & regdnw { getbit(CF,regdnw,cntreg-1); shiftCXFlags(cntreg); regdnw=regdnw >>cntreg; resflags(regdnw);} -:lsr.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=1 & regdn { getbit(CF,regdn,cntreg-1); shiftCXFlags(cntreg); regdn=regdn >>cntreg; resflags(regdn); } -:lsr eaw is (opbig=0xe2 & op67=3 & $(MEM_ALTER_ADDR_MODES))... & eaw { getbit(CF,eaw,0); shiftCXFlags(eaw); eaw=eaw >>1; resflags(eaw); } +:lsr.b cntreg,regdnb is op=14 & cntreg & op8=0 & op67=0 & op34=1 & regdnb { logicalShiftRight(cntreg, regdnb, 8); } +:lsr.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=1 & regdnw { logicalShiftRight(cntreg, regdnw, 16); } +:lsr.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=1 & regdn { logicalShiftRight(cntreg, regdn, 32); } +:lsr eaw is (opbig=0xe2 & op67=3 & $(MEM_ALTER_ADDR_MODES)) ... & eaw { + local value:2 = eaw; + getbit(CF, value, 0); + value = value >> 1; + resflags(value); + eaw = value; + VF = 0; + XF = CF; +} :move.b eab,e2b is (op=1 & $(DAT_ALTER_ADDR_MODES2))... & eab ; e2b { build eab; local tmp = eab; build e2b; e2b = tmp; resflags(tmp); logflags(); } :move.w eaw,e2w is (op=3 & $(DAT_ALTER_ADDR_MODES2))... & eaw ; e2w { build eaw; local tmp = eaw; build e2w; e2w = tmp; resflags(tmp); logflags(); } @@ -1677,37 +1807,57 @@ ptestLevel: "#"^mregn is mregn { export *[const]:1 mregn; } :reset is d16=0x4e70 { reset(); } -:rol.b cntreg,regdnb is op=14 & cntreg & op8=1 & op67=0 & op34=3 & regdnb { regdnb=(regdnb<>(8-cntreg)); - getbit(CF,regdnb,0); VF=0; resflags(regdnb); } -:rol.w cntreg,regdnw is op=14 & cntreg & op8=1 & op67=1 & op34=3 & regdnw { regdnw=(regdnw<>(16-cntreg)); - getbit(CF,regdnw,0); VF=0; resflags(regdnw); } -:rol.l cntreg,regdn is op=14 & cntreg & op8=1 & op67=2 & op34=3 & regdn { regdn=(regdn<>(32-cntreg)); - getbit(CF,regdn,0); VF=0; resflags(regdn); } -:rol eaw is (opbig=0xe7 & op67=3 & $(MEM_ALTER_ADDR_MODES))... & eaw { eaw = (eaw<<1)|(eaw>>15); getbit(CF,eaw,0); VF=0; resflags(eaw); } +:rol.b cntreg,regdnb is op=14 & cntreg & op8=1 & op67=0 & op34=3 & regdnb { rotateLeft(cntreg, regdnb, 8); } +:rol.w cntreg,regdnw is op=14 & cntreg & op8=1 & op67=1 & op34=3 & regdnw { rotateLeft(cntreg, regdnw, 16); } +:rol.l cntreg,regdn is op=14 & cntreg & op8=1 & op67=2 & op34=3 & regdn { rotateLeft(cntreg, regdn, 32); } +:rol eaw is (opbig=0xe7 & op67=3 & $(MEM_ALTER_ADDR_MODES)) ... & eaw { + local value:2 = eaw; + value = (value << 1) | (value >> 15); + getbit(CF, value, 0); + resflags(value); + eaw = value; + VF = 0; +} -:ror.b cntreg,regdnb is op=14 & cntreg & op8=0 & op67=0 & op34=3 & regdnb { regdnb=(regdnb<<(8-cntreg))|(regdnb>>cntreg); - getbit(CF,regdnb,7); VF=0; resflags(regdnb); } -:ror.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=3 & regdnw { regdnw=(regdnw<<(16-cntreg))|(regdnw>>cntreg); - getbit(CF,regdnw,15); VF=0; resflags(regdnw); } -:ror.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=3 & regdn { regdn=(regdn<<(32-cntreg))|(regdn>>cntreg); - getbit(CF,regdn,31); VF=0; resflags(regdn); } -:ror eaw is (opbig=0xe6 & op67=3 & $(MEM_ALTER_ADDR_MODES))... & eaw { eaw = (eaw<<15)|(eaw>>1); getbit(CF,eaw,15); VF=0; resflags(eaw); } +:ror.b cntreg,regdnb is op=14 & cntreg & op8=0 & op67=0 & op34=3 & regdnb { rotateRight(cntreg, regdnb, 8); } +:ror.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=3 & regdnw { rotateRight(cntreg, regdnw, 16); } +:ror.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=3 & regdn { rotateRight(cntreg, regdn, 32); } +:ror eaw is (opbig=0xe6 & op67=3 & $(MEM_ALTER_ADDR_MODES)) ... & eaw { + local value:2 = eaw; + value = (value << 15) | (value >> 1); + getbit(CF, value, 15); + resflags(value); + eaw = value; + VF = 0; +} -:roxl.b cntreg,regdnb is op=14 & cntreg & op8=1 & op67=0 & op34=2 & regdnb { CF=(regdnb&(1<<( 8-cntreg)))!=0; regdnb=(zext(XF)<<(cntreg-1))|(regdnb<>(9-cntreg)); - XF=CF; VF=0; resflags(regdnb); } -:roxl.w cntreg,regdnw is op=14 & cntreg & op8=1 & op67=1 & op34=2 & regdnw { CF=(regdnw&(1<<(16-cntreg)))!=0; regdnw=(zext(XF)<<(cntreg-1))|(regdnw<>(17-cntreg)); - XF=CF; VF=0; resflags(regdnw); } -:roxl.l cntreg,regdn is op=14 & cntreg & op8=1 & op67=2 & op34=2 & regdn { CF=(regdn &(1<<(32-cntreg)))!=0; regdn =(zext(XF)<<(cntreg-1))|(regdn <>(33-cntreg)); - XF=CF; VF=0; resflags(regdn ); } -:roxl eaw is (opbig=0xe5 & op67=3 & $(MEM_ALTER_ADDR_MODES))... & eaw { CF=(eaw&0x8000)!=0; eaw=zext(XF)|(eaw<<1)|(eaw>>16); XF=CF; VF=0; resflags(eaw); } +:roxl.b cntreg,regdnb is op=14 & cntreg & op8=1 & op67=0 & op34=2 & regdnb { rotateLeftExtended(cntreg, regdnb, 8); } +:roxl.w cntreg,regdnw is op=14 & cntreg & op8=1 & op67=1 & op34=2 & regdnw { rotateLeftExtended(cntreg, regdnw, 16); } +:roxl.l cntreg,regdn is op=14 & cntreg & op8=1 & op67=2 & op34=2 & regdn { rotateLeftExtended(cntreg, regdn, 32); } +:roxl eaw is (opbig=0xe5 & op67=3 & $(MEM_ALTER_ADDR_MODES)) ... & eaw { + local value:2 = eaw; + local xflag = (value & 0x8000) != 0; + value = (value << 1) | zext(XF); + resflags(value); + eaw = value; + VF = 0; + XF = xflag; + CF = XF; +} -:roxr.b cntreg,regdnb is op=14 & cntreg & op8=0 & op67=0 & op34=2 & regdnb { CF=(regdnb&(1<<(cntreg-1)))!=0; regdnb=(zext(XF)<<( 8-cntreg))|(regdnb>>cntreg)|(regdnb<<(9 -cntreg)); - XF=CF; VF=0; resflags(regdnb); } -:roxr.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=2 & regdnw { CF=(regdnw&(1<<(cntreg-1)))!=0; regdnw=(zext(XF)<<(16-cntreg))|(regdnw>>cntreg)|(regdnw<<(17-cntreg)); - XF=CF; VF=0; resflags(regdnw); } -:roxr.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=2 & regdn { CF=(regdn &(1<<(cntreg-1)))!=0; regdn =(zext(XF)<<(32-cntreg))|(regdn >>cntreg)|(regdn <<(33-cntreg)); - XF=CF; VF=0; resflags(regdn); } -:roxr eaw is (opbig=0xe4 & op67=3 & $(MEM_ALTER_ADDR_MODES))... & eaw { CF=(eaw&1)!=0; eaw=(zext(XF)<<15)|(eaw>>1); XF=CF; VF=0; resflags(eaw); } +:roxr.b cntreg,regdnb is op=14 & cntreg & op8=0 & op67=0 & op34=2 & regdnb { rotateRightExtended(cntreg, regdnb, 8); } +:roxr.w cntreg,regdnw is op=14 & cntreg & op8=0 & op67=1 & op34=2 & regdnw { rotateRightExtended(cntreg, regdnw, 16); } +:roxr.l cntreg,regdn is op=14 & cntreg & op8=0 & op67=2 & op34=2 & regdn { rotateRightExtended(cntreg, regdn, 32); } +:roxr eaw is (opbig=0xe4 & op67=3 & $(MEM_ALTER_ADDR_MODES)) ... & eaw { + local value:2 = eaw; + local xflag = (value & 0x0001) != 0; + value = (zext(XF) << 15) | (value >> 1); + resflags(value); + eaw = value; + VF = 0; + XF = xflag; + CF = XF; +} :rtd "#"^d16 is opbig=0x4e & op37=14 & op02=4; d16 { PC = *SP; SP = SP + 4 + d16; return [PC]; } :rte is d16=0x4e73 { tmp:4 = 0; return [tmp]; }