@@ -106,6 +106,7 @@ class Decoder {
106106 void PrintCondition (Instr* instr);
107107 void PrintShiftRm (Instr* instr);
108108 void PrintShiftImm (Instr* instr);
109+ void PrintShiftSat (Instr* instr);
109110 void PrintPU (Instr* instr);
110111 void PrintSoftwareInterrupt (SoftwareInterruptCodes swi);
111112
@@ -248,6 +249,18 @@ void Decoder::PrintShiftImm(Instr* instr) {
248249}
249250
250251
252+ // Print the optional shift and immediate used by saturating instructions.
253+ void Decoder::PrintShiftSat (Instr* instr) {
254+ int shift = instr->Bits (11 , 7 );
255+ if (shift > 0 ) {
256+ out_buffer_pos_ += v8i::OS::SNPrintF (out_buffer_ + out_buffer_pos_,
257+ " , %s #%d" ,
258+ shift_names[instr->Bit (6 ) * 2 ],
259+ instr->Bits (11 , 7 ));
260+ }
261+ }
262+
263+
251264// Print PU formatting to reduce complexity of FormatOption.
252265void Decoder::PrintPU (Instr* instr) {
253266 switch (instr->PUField ()) {
@@ -440,6 +453,20 @@ int Decoder::FormatOption(Instr* instr, const char* format) {
440453 }
441454 return 1 ;
442455 }
456+ case ' i' : { // 'i: immediate value from adjacent bits.
457+ // Expects tokens in the form imm%02d@%02d, ie. imm05@07, imm10@16
458+ int width = (format[3 ] - ' 0' ) * 10 + (format[4 ] - ' 0' );
459+ int lsb = (format[6 ] - ' 0' ) * 10 + (format[7 ] - ' 0' );
460+
461+ ASSERT ((width >= 1 ) && (width <= 32 ));
462+ ASSERT ((lsb >= 0 ) && (lsb <= 31 ));
463+ ASSERT ((width + lsb) <= 32 );
464+
465+ out_buffer_pos_ += v8i::OS::SNPrintF (out_buffer_ + out_buffer_pos_,
466+ " #%d" ,
467+ instr->Bits (width + lsb - 1 , lsb));
468+ return 8 ;
469+ }
443470 case ' l' : { // 'l: branch and link
444471 if (instr->HasLink ()) {
445472 Print (" l" );
@@ -507,7 +534,7 @@ int Decoder::FormatOption(Instr* instr, const char* format) {
507534 return FormatRegister (instr, format);
508535 }
509536 case ' s' : {
510- if (format[1 ] == ' h' ) { // 'shift_op or 'shift_rm
537+ if (format[1 ] == ' h' ) { // 'shift_op or 'shift_rm or 'shift_sat.
511538 if (format[6 ] == ' o' ) { // 'shift_op
512539 ASSERT (STRING_STARTS_WITH (format, " shift_op" ));
513540 if (instr->TypeField () == 0 ) {
@@ -517,6 +544,10 @@ int Decoder::FormatOption(Instr* instr, const char* format) {
517544 PrintShiftImm (instr);
518545 }
519546 return 8 ;
547+ } else if (format[6 ] == ' s' ) { // 'shift_sat.
548+ ASSERT (STRING_STARTS_WITH (format, " shift_sat" ));
549+ PrintShiftSat (instr);
550+ return 9 ;
520551 } else { // 'shift_rm
521552 ASSERT (STRING_STARTS_WITH (format, " shift_rm" ));
522553 PrintShiftRm (instr);
@@ -897,8 +928,16 @@ void Decoder::DecodeType3(Instr* instr) {
897928 break ;
898929 }
899930 case 1 : {
900- ASSERT (!instr->HasW ());
901- Format (instr, " 'memop'cond'b 'rd, ['rn], +'shift_rm" );
931+ if (instr->HasW ()) {
932+ ASSERT (instr->Bits (5 , 4 ) == 0x1 );
933+ if (instr->Bit (22 ) == 0x1 ) {
934+ Format (instr, " usat 'rd, 'imm05@16, 'rm'shift_sat" );
935+ } else {
936+ UNREACHABLE (); // SSAT.
937+ }
938+ } else {
939+ Format (instr, " 'memop'cond'b 'rd, ['rn], +'shift_rm" );
940+ }
902941 break ;
903942 }
904943 case 2 : {
0 commit comments