@@ -127,12 +127,31 @@ auto CPU::Recompiler::emitZeroClear(u32 n) -> void {
127
127
if (n == 0 ) mov64 (mem (IpuReg (r[0 ])), imm (0 ));
128
128
}
129
129
130
- auto CPU::Recompiler::emitEXECUTE (u32 instruction) -> bool {
130
+ auto CPU::Recompiler::emitOverflowCheck (reg temp) -> sljit_jump* {
131
+ // If overflow flag set: throw an exception, skip the instruction via the 'end' label.
132
+ mov32_f (temp, flag_o);
133
+ auto didntOverflow = cmp32_jump (temp, imm (0 ), flag_eq);
134
+ call (&CPU::Exception::arithmeticOverflow, &cpu.exception );
135
+ auto end = jump ();
136
+ setLabel (didntOverflow);
137
+ return end;
138
+ }
139
+
140
+ auto CPU::Recompiler::checkDualAllowed (const Context::JIT& ctx) -> bool {
141
+ if (ctx.mode != Context::Mode::Kernel && !ctx.is64bit ) {
142
+ call (&CPU::Exception::reservedInstruction, &self.exception );
143
+ return false ;
144
+ }
145
+
146
+ return true ;
147
+ }
148
+
149
+ auto CPU::Recompiler::emitEXECUTE (u32 instruction, Context::JIT ctx) -> bool {
131
150
switch (instruction >> 26 ) {
132
151
133
152
// SPECIAL
134
153
case 0x00 : {
135
- return emitSPECIAL (instruction);
154
+ return emitSPECIAL (instruction, ctx );
136
155
}
137
156
138
157
// REGIMM
@@ -308,21 +327,19 @@ auto CPU::Recompiler::emitEXECUTE(u32 instruction) -> bool {
308
327
309
328
// DADDI Rt,Rs,i16
310
329
case 0x18 : {
311
- lea ( reg ( 1 ), Rt) ;
312
- lea (reg (2 ), Rs );
313
- mov32 (reg (3 ), imm (i16 ));
314
- call (&CPU::DADDI );
315
- emitZeroClear (Rtn );
330
+ if (! checkDualAllowed (ctx)) return 1 ;
331
+ add64 (reg (0 ), mem (Rs), imm (i16), set_o );
332
+ auto skip = emitOverflowCheck (reg (2 ));
333
+ if (Rtn > 0 ) mov64 ( mem (Rt), reg ( 0 ) );
334
+ setLabel (skip );
316
335
return 0 ;
317
336
}
318
337
319
338
// DADDIU Rt,Rs,i16
320
339
case 0x19 : {
321
- lea (reg (1 ), Rt);
322
- lea (reg (2 ), Rs);
323
- mov32 (reg (3 ), imm (i16));
324
- call (&CPU::DADDIU);
325
- emitZeroClear (Rtn);
340
+ if (!checkDualAllowed (ctx)) return 1 ;
341
+ add64 (reg (0 ), mem (Rs), imm (i16), set_o);
342
+ if (Rtn > 0 ) mov64 (mem (Rt), reg (0 ));
326
343
return 0 ;
327
344
}
328
345
@@ -640,7 +657,7 @@ auto CPU::Recompiler::emitEXECUTE(u32 instruction) -> bool {
640
657
return 0 ;
641
658
}
642
659
643
- auto CPU::Recompiler::emitSPECIAL (u32 instruction) -> bool {
660
+ auto CPU::Recompiler::emitSPECIAL (u32 instruction, Context::JIT ctx ) -> bool {
644
661
switch (instruction & 0x3f ) {
645
662
646
663
// SLL Rd,Rt,Sa
@@ -784,11 +801,10 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool {
784
801
785
802
// DSLLV Rd,Rt,Rs
786
803
case 0x14 : {
787
- lea (reg (1 ), Rd);
788
- lea (reg (2 ), Rt);
789
- lea (reg (3 ), Rs);
790
- call (&CPU::DSLLV);
791
- emitZeroClear (Rdn);
804
+ if (!checkDualAllowed (ctx)) return 1 ;
805
+ if (Rdn == 0 ) return 0 ;
806
+ and64 (reg (0 ), mem (Rs32), imm (63 ));
807
+ shl64 (mem (Rd), mem (Rt), reg (0 ));
792
808
return 0 ;
793
809
}
794
810
@@ -800,21 +816,19 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool {
800
816
801
817
// DSRLV Rd,Rt,Rs
802
818
case 0x16 : {
803
- lea (reg (1 ), Rd);
804
- lea (reg (2 ), Rt);
805
- lea (reg (3 ), Rs);
806
- call (&CPU::DSRLV);
807
- emitZeroClear (Rdn);
819
+ if (!checkDualAllowed (ctx)) return 1 ;
820
+ if (Rdn == 0 ) return 0 ;
821
+ and64 (reg (0 ), mem (Rs32), imm (63 ));
822
+ lshr64 (mem (Rd), mem (Rt), reg (0 ));
808
823
return 0 ;
809
824
}
810
825
811
826
// DSRAV Rd,Rt,Rs
812
827
case 0x17 : {
813
- lea (reg (1 ), Rd);
814
- lea (reg (2 ), Rt);
815
- lea (reg (3 ), Rs);
816
- call (&CPU::DSRAV);
817
- emitZeroClear (Rdn);
828
+ if (!checkDualAllowed (ctx)) return 1 ;
829
+ if (Rdn == 0 ) return 0 ;
830
+ and64 (reg (0 ), mem (Rs32), imm (63 ));
831
+ ashr64 (mem (Rd), mem (Rt), reg (0 ));
818
832
return 0 ;
819
833
}
820
834
@@ -974,41 +988,42 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool {
974
988
975
989
// DADD Rd,Rs,Rt
976
990
case 0x2c : {
977
- lea ( reg ( 1 ), Rd) ;
978
- lea (reg (2 ), Rs );
979
- lea (reg (3 ), Rt );
980
- call (&CPU::DADD );
981
- emitZeroClear (Rdn );
991
+ if (! checkDualAllowed (ctx)) return 1 ;
992
+ add64 (reg (0 ), mem (Rs), mem (Rt), set_o );
993
+ auto skip = emitOverflowCheck (reg (2 ) );
994
+ if (Rdn > 0 ) mov64 ( mem (Rd), reg ( 0 ) );
995
+ setLabel (skip );
982
996
return 0 ;
983
997
}
984
998
985
999
// DADDU Rd,Rs,Rt
986
1000
case 0x2d : {
987
- lea (reg (1 ), Rd);
988
- lea (reg (2 ), Rs);
989
- lea (reg (3 ), Rt);
990
- call (&CPU::DADDU);
991
- emitZeroClear (Rdn);
1001
+ if (!checkDualAllowed (ctx)) {
1002
+ return 1 ;
1003
+ }
1004
+
1005
+ if (Rdn == 0 ) return 0 ;
1006
+
1007
+ add64 (reg (0 ), mem (Rs), mem (Rt));
1008
+ mov64 (mem (Rd), reg (0 ));
992
1009
return 0 ;
993
1010
}
994
1011
995
1012
// DSUB Rd,Rs,Rt
996
1013
case 0x2e : {
997
- lea ( reg ( 1 ), Rd) ;
998
- lea (reg (2 ), Rs );
999
- lea (reg (3 ), Rt );
1000
- call (&CPU::DSUB );
1001
- emitZeroClear (Rdn );
1014
+ if (! checkDualAllowed (ctx)) return 1 ;
1015
+ sub64 (reg (0 ), mem (Rs), mem (Rt), set_o );
1016
+ auto skip = emitOverflowCheck (reg (2 ) );
1017
+ if (Rdn > 0 ) mov64 ( mem (Rd), reg ( 0 ) );
1018
+ setLabel (skip );
1002
1019
return 0 ;
1003
1020
}
1004
1021
1005
1022
// DSUBU Rd,Rs,Rt
1006
1023
case 0x2f : {
1007
- lea (reg (1 ), Rd);
1008
- lea (reg (2 ), Rs);
1009
- lea (reg (3 ), Rt);
1010
- call (&CPU::DSUBU);
1011
- emitZeroClear (Rdn);
1024
+ if (!checkDualAllowed (ctx)) return 1 ;
1025
+ sub64 (reg (0 ), mem (Rs), mem (Rt), set_o);
1026
+ if (Rdn > 0 ) mov64 (mem (Rd), reg (0 ));
1012
1027
return 0 ;
1013
1028
}
1014
1029
@@ -1074,11 +1089,9 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool {
1074
1089
1075
1090
// DSLL Rd,Rt,Sa
1076
1091
case 0x38 : {
1077
- lea (reg (1 ), Rd);
1078
- lea (reg (2 ), Rt);
1079
- mov32 (reg (3 ), imm (Sa));
1080
- call (&CPU::DSLL);
1081
- emitZeroClear (Rdn);
1092
+ if (!checkDualAllowed (ctx)) return 1 ;
1093
+ if (Rdn == 0 ) return 0 ;
1094
+ shl64 (mem (Rd), mem (Rt), imm (Sa));
1082
1095
return 0 ;
1083
1096
}
1084
1097
@@ -1100,21 +1113,17 @@ auto CPU::Recompiler::emitSPECIAL(u32 instruction) -> bool {
1100
1113
1101
1114
// DSRA Rd,Rt,Sa
1102
1115
case 0x3b : {
1103
- lea (reg (1 ), Rd);
1104
- lea (reg (2 ), Rt);
1105
- mov32 (reg (3 ), imm (Sa));
1106
- call (&CPU::DSRA);
1107
- emitZeroClear (Rdn);
1116
+ if (!checkDualAllowed (ctx)) return 1 ;
1117
+ if (Rdn == 0 ) return 0 ;
1118
+ ashr64 (mem (Rd), mem (Rt), imm (Sa));
1108
1119
return 0 ;
1109
1120
}
1110
1121
1111
1122
// DSLL32 Rd,Rt,Sa
1112
1123
case 0x3c : {
1113
- lea (reg (1 ), Rd);
1114
- lea (reg (2 ), Rt);
1115
- mov32 (reg (3 ), imm (Sa+32 ));
1116
- call (&CPU::DSLL);
1117
- emitZeroClear (Rdn);
1124
+ if (!checkDualAllowed (ctx)) return 1 ;
1125
+ if (Rdn == 0 ) return 0 ;
1126
+ shl64 (mem (Rd), mem (Rt), imm (Sa+32 ));
1118
1127
return 0 ;
1119
1128
}
1120
1129
0 commit comments