summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuyang Huang <yuyanghuang@google.com>2023-11-01 18:14:45 +0900
committerYuyang Huang <yuyanghuang@google.com>2023-11-05 11:33:28 +0900
commitaea452e1d72d4ff6fb4d5080a1c2e9995045c8fb (patch)
treefec62091f9e9c643bc673279ac74e5abcad3173e
parentf7f4461acfc5876b73c4d7917acebd6dc76a9c0a (diff)
downloadapf-aea452e1d72d4ff6fb4d5080a1c2e9995045c8fb.tar.gz
Update apf_disassemble to support MEMCOPY, EPKTCOPY, EDATACOPY opcode.
This commit updates the ApfGenerator class to support the MEMCOPY, EPKTCOPY, and EDATACOPY opcodes. These opcodes allow data to be copied from the input packet/data region to the output buffer. Bug: 293811969 Test: TH Change-Id: I72f6fe63a6350fc24893e868876edccedf3c9b92
-rw-r--r--disassembler.c60
-rw-r--r--v5/apf.h11
2 files changed, 65 insertions, 6 deletions
diff --git a/disassembler.c b/disassembler.c
index 6db8d7d..06a164b 100644
--- a/disassembler.c
+++ b/disassembler.c
@@ -113,6 +113,10 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len,
const uint32_t opcode = EXTRACT_OPCODE(bytecode);
#define PRINT_OPCODE() \
print_opcode(opcode_names[opcode], output_buffer, output_buffer_len, offset)
+#define DECODE_IMM(value, length) \
+ for (uint32_t i = 0; i < (length) && pc < program_len; i++) \
+ value = (value << 8) | program[pc++]
+
const uint32_t reg_num = EXTRACT_REGISTER(bytecode);
// All instructions have immediate fields, so load them now.
const uint32_t len_field = EXTRACT_IMM_LENGTH(bytecode);
@@ -120,8 +124,7 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len,
int32_t signed_imm = 0;
if (len_field != 0) {
const uint32_t imm_len = 1 << (len_field - 1);
- for (uint32_t i = 0; i < imm_len && pc < program_len; i++)
- imm = (imm << 8) | program[pc++];
+ DECODE_IMM(imm, imm_len);
// Sign extend imm into signed_imm.
signed_imm = imm << ((4 - imm_len) * 8);
signed_imm >>= (4 - imm_len) * 8;
@@ -193,10 +196,7 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len,
ASSERT_RET_INBOUND(ret);
offset += ret;
} else {
- uint32_t cmp_imm_len = 1 << (len_field - 1);
- uint32_t i;
- for (i = 0; i < cmp_imm_len && pc < program_len; i++)
- cmp_imm = (cmp_imm << 8) | program[pc++];
+ DECODE_IMM(cmp_imm, 1 << (len_field - 1));
ret = snprintf(output_buffer + offset,
output_buffer_len - offset, "0x%x, ", cmp_imm);
ASSERT_RET_INBOUND(ret);
@@ -381,6 +381,32 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len,
offset += ret;
break;
}
+ case EDATACOPY:
+ case EPKTCOPY: {
+ if (imm == EPKTCOPY) {
+ ret = print_opcode("pcopy", output_buffer,
+ output_buffer_len, offset);
+ } else {
+ ret = print_opcode("dcopy", output_buffer,
+ output_buffer_len, offset);
+ }
+ ASSERT_RET_INBOUND(ret);
+ offset += ret;
+ if (len_field > 0) {
+ const uint32_t imm_len = 1 << (len_field - 1);
+ uint32_t relative_offs = 0;
+ DECODE_IMM(relative_offs, imm_len);
+ uint32_t copy_len = 0;
+ DECODE_IMM(copy_len, 1);
+
+ ret = snprintf(
+ output_buffer + offset, output_buffer_len - offset,
+ "[r%u+%d], %d", reg_num, relative_offs, copy_len);
+ ASSERT_RET_INBOUND(ret);
+ offset += ret;
+ }
+ break;
+ }
default:
ret = snprintf(output_buffer + offset,
output_buffer_len - offset, "unknown_ext %u",
@@ -437,6 +463,28 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len,
}
break;
}
+ case MEMCOPY_OPCODE: {
+ if (reg_num == 0) {
+ ret = print_opcode("pcopy", output_buffer, output_buffer_len,
+ offset);
+ } else {
+ ret = print_opcode("dcopy", output_buffer, output_buffer_len,
+ offset);
+ }
+ ASSERT_RET_INBOUND(ret);
+ offset += ret;
+ if (len_field > 0) {
+ uint32_t src_offs = imm;
+ uint32_t copy_len = 0;
+ DECODE_IMM(copy_len, 1);
+ ret =
+ snprintf(output_buffer + offset, output_buffer_len - offset,
+ "%d, %d", src_offs, copy_len);
+ ASSERT_RET_INBOUND(ret);
+ offset += ret;
+ }
+ break;
+ }
// Unknown opcode
default:
ret = snprintf(output_buffer + offset, output_buffer_len - offset,
diff --git a/v5/apf.h b/v5/apf.h
index e981593..a75ab1b 100644
--- a/v5/apf.h
+++ b/v5/apf.h
@@ -159,6 +159,11 @@
#define LDDW_OPCODE 22 // Load 4 bytes from data address (register + simm): "lddw R0, [5+R1]"
#define STDW_OPCODE 23 // Store 4 bytes to data address (register + simm): "stdw R0, [5+R1]"
#define WRITE_OPCODE 24 // Write 1, 2 or 4 bytes imm to the output buffer, e.g. "WRITE 5"
+// Copy the data from input packet or APF data region to output buffer. Register bit is
+// used to specify the source of data copy: R=0 means copy from packet, R=1 means copy
+// from APF data region. The source offset is encoded in the first imm and the copy length
+// is encoded in the second imm. "e.g. MEMCOPY(R=0), 5, 5"
+#define MEMCOPY_OPCODE 25
// Extended opcodes. These all have an opcode of EXT_OPCODE
// and specify the actual opcode in the immediate field.
@@ -175,6 +180,12 @@
#define EWRITE1_EXT_OPCODE 38 // Write 1 byte from register to the output buffer, e.g. "EWRITE1 R0"
#define EWRITE2_EXT_OPCODE 39 // Write 2 bytes from register to the output buffer, e.g. "EWRITE2 R0"
#define EWRITE4_EXT_OPCODE 40 // Write 4 bytes from register to the output buffer, e.g. "EWRITE4 R0"
+// Copy the data from input packet to output buffer. The source offset is encoded as [Rx + second imm].
+// The copy length is encoded in the third imm. "e.g. EPKTCOPY [R0 + 5], 5"
+#define EPKTCOPY 41
+// Copy the data from APF data region to output buffer. The source offset is encoded as [Rx + second imm].
+// The copy length is encoded in the third imm. "e.g. EDATACOPY [R0 + 5], 5"
+#define EDATACOPY 42
#define EXTRACT_OPCODE(i) (((i) >> 3) & 31)
#define EXTRACT_REGISTER(i) ((i) & 1)