Updated APF dissembler to support WRITE/EWRITE opcodes.

Added support for WRITE opcode, which writes 1, 2, or 4 bytes from an
immediate value to the output buffer. Added support for EWRITE opcode,
which writes 1, 2, or 4 bytes from a register to the output buffer.

Bug: 293811969
Test: TH
Change-Id: Iee36500669e16e027dc8e6d3743767521ca39c66
diff --git a/disassembler.c b/disassembler.c
index 091ff9e..6db8d7d 100644
--- a/disassembler.c
+++ b/disassembler.c
@@ -55,6 +55,7 @@
     [JNEBS_OPCODE] = "jnebs",
     [LDDW_OPCODE] = "lddw",
     [STDW_OPCODE] = "stdw",
+    [WRITE_OPCODE] = "write",
 };
 
 static int print_jump_target(uint32_t target, uint32_t program_len,
@@ -366,6 +367,20 @@
                     ASSERT_RET_INBOUND(ret);
                     offset += ret;
                     break;
+                case EWRITE1_EXT_OPCODE:
+                case EWRITE2_EXT_OPCODE:
+                case EWRITE4_EXT_OPCODE: {
+                    ret = print_opcode("write", output_buffer,
+                                       output_buffer_len, offset);
+                    ASSERT_RET_INBOUND(ret);
+                    offset += ret;
+                    ret = snprintf(output_buffer + offset,
+                                   output_buffer_len - offset, "r%d, %d",
+                                   reg_num, 1 << (imm - EWRITE1_EXT_OPCODE));
+                    ASSERT_RET_INBOUND(ret);
+                    offset += ret;
+                    break;
+                }
                 default:
                     ret = snprintf(output_buffer + offset,
                                    output_buffer_len - offset, "unknown_ext %u",
@@ -400,7 +415,28 @@
                 offset += ret;
             }
             break;
+        case WRITE_OPCODE: {
+            ret = PRINT_OPCODE();
+            ASSERT_RET_INBOUND(ret);
+            offset += ret;
+            uint32_t write_len = 1 << (len_field - 1);
+            if (write_len > 0) {
+                ret = snprintf(output_buffer + offset,
+                               output_buffer_len - offset, "0x");
+                ASSERT_RET_INBOUND(ret);
+                offset += ret;
+            }
+            for (uint32_t i = 0; i < write_len; ++i) {
+                uint8_t byte =
+                    (uint8_t) ((imm >> (write_len - 1 - i) * 8) & 0xff);
+                ret = snprintf(output_buffer + offset,
+                               output_buffer_len - offset, "%02x", byte);
+                ASSERT_RET_INBOUND(ret);
+                offset += ret;
 
+            }
+            break;
+        }
         // Unknown opcode
         default:
             ret = snprintf(output_buffer + offset, output_buffer_len - offset,