summaryrefslogtreecommitdiffstats
path: root/pcm/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'pcm/pcm.c')
-rw-r--r--pcm/pcm.c157
1 files changed, 123 insertions, 34 deletions
diff --git a/pcm/pcm.c b/pcm/pcm.c
index 35a6faa..09ec0a8 100644
--- a/pcm/pcm.c
+++ b/pcm/pcm.c
@@ -47,6 +47,37 @@ int binary_print(unsigned int value)
printf("(0x%x)\n", value);
}
+struct list_head *list_head_alloc(struct list_head *prev, struct list_head *next, void *data)
+{
+ struct list_head *list;
+
+ list = calloc(1, sizeof(struct list_head));
+ list->data = data;
+ list->prev = prev;
+ list->next = next;
+
+ if (prev != NULL)
+ prev->next = list;
+ if (next != NULL)
+ next->prev = list;
+
+ return list;
+}
+
+void list_head_free(struct list_head *list)
+{
+ if (list == NULL)
+ return;
+
+ if (list->next != NULL)
+ list->next->prev = list->prev;
+ if (list->prev != NULL)
+ list->prev->next = list->next;
+
+ memset(list, 0, sizeof(struct list_head));
+ free(list);
+}
+
/*
* PCM OPS
*/
@@ -63,6 +94,11 @@ int pcm_ops_register(struct pcm_ops *ops)
return 0;
}
+void pcm_ops_unregister(void)
+{
+ pcm_ops = NULL;
+}
+
int pcm_ops_asm_write(unsigned int value, char *mnemonic)
{
if (pcm_ops == NULL || pcm_ops->asm_write == NULL)
@@ -79,6 +115,22 @@ int pcm_ops_disasm_write(unsigned int value, char *mnemonic)
return pcm_ops->disasm_write(pcm_ops->data, value, mnemonic);
}
+int pcm_ops_func_address(char *func)
+{
+ if (pcm_ops == NULL || pcm_ops->func_address == NULL)
+ return -1;
+
+ return pcm_ops->func_address(pcm_ops->data, func);
+}
+
+int pcm_ops_label_address(char *func)
+{
+ if (pcm_ops == NULL || pcm_ops->label_address == NULL)
+ return -1;
+
+ return pcm_ops->label_address(pcm_ops->data, func);
+}
+
static int pcm_ops_asm_format(unsigned int value, const char *format, ...)
{
char *mnemonic = NULL;
@@ -139,38 +191,18 @@ complete:
* PCM OP codes
*/
-static int pcm_op_padding_asm(char *arguments[], unsigned int count, unsigned int padding)
+static int pcm_op_padding_asm(unsigned int padding)
{
- unsigned int value;
- unsigned int i;
int rc;
+ int i;
- if (arguments == NULL)
- return -1;
-
- i = 0;
-
- /* Grab padding from following nops first. */
- while (arguments[i] != NULL && count > 0 && padding > 0) {
- if (strncmp(arguments[i], "nop", 3) != 0)
- break;
-
- rc = pcm_ops_asm_write(PCM_OP_NOP_VALUE, "nop");
- if (rc < 0)
- return -1;
-
- padding--;
- i++;
- }
-
- /* Generate leftover padding. */
- while (padding-- > 0) {
+ for (i = 0; i < padding; i++) {
rc = pcm_ops_asm_write(PCM_OP_NOP_VALUE, "nop");
if (rc < 0)
return -1;
}
- return i;
+ return padding;
}
static int pcm_op_immediate_asm(char *arguments[], unsigned int count)
@@ -291,7 +323,7 @@ static int pcm_op_loadi_disasm(struct pcm_op_desc *desc, unsigned int *arguments
return 1;
}
-static int pcm_op_jump_call_asm(struct pcm_op_desc *desc, char *arguments[], unsigned int count)
+static int pcm_op_jump_asm(struct pcm_op_desc *desc, char *arguments[], unsigned int count)
{
unsigned int value;
unsigned int address;
@@ -301,7 +333,12 @@ static int pcm_op_jump_call_asm(struct pcm_op_desc *desc, char *arguments[], uns
return -1;
value = desc->value;
- address = strtol(arguments[1], NULL, 16);
+
+ rc = pcm_ops_label_address(arguments[1]);
+ if (rc < 0)
+ address = strtol(arguments[1], NULL, 16);
+ else
+ address = rc;
value |= (address & PCM_OP_JUMP_ADDRESS_MASK) << PCM_OP_JUMP_ADDRESS_SHIFT;
@@ -312,7 +349,7 @@ static int pcm_op_jump_call_asm(struct pcm_op_desc *desc, char *arguments[], uns
return 1;
}
-static int pcm_op_jump_call_disasm(struct pcm_op_desc *desc, unsigned int *arguments, unsigned int count)
+static int pcm_op_jump_disasm(struct pcm_op_desc *desc, unsigned int *arguments, unsigned int count)
{
unsigned int value;
unsigned int address;
@@ -331,6 +368,51 @@ static int pcm_op_jump_call_disasm(struct pcm_op_desc *desc, unsigned int *argum
return 0;
}
+static int pcm_op_call_asm(struct pcm_op_desc *desc, char *arguments[], unsigned int count)
+{
+ unsigned int value;
+ unsigned int address;
+ int rc;
+
+ if (desc == NULL || arguments == NULL || arguments[1] == NULL || count < 2)
+ return -1;
+
+ value = desc->value;
+
+ rc = pcm_ops_func_address(arguments[1]);
+ if (rc < 0)
+ address = strtol(arguments[1], NULL, 16);
+ else
+ address = rc;
+
+ value |= (address & PCM_OP_CALL_ADDRESS_MASK) << PCM_OP_CALL_ADDRESS_SHIFT;
+
+ rc = pcm_ops_asm_format(value, "%s 0x%04x", arguments[0], address);
+ if (rc < 0)
+ return -1;
+
+ return 1;
+}
+
+static int pcm_op_call_disasm(struct pcm_op_desc *desc, unsigned int *arguments, unsigned int count)
+{
+ unsigned int value;
+ unsigned int address;
+ int rc;
+
+ if (desc == NULL || arguments == NULL || count < 1)
+ return -1;
+
+ value = arguments[0];
+ address = (value >> PCM_OP_CALL_ADDRESS_SHIFT) & PCM_OP_CALL_ADDRESS_MASK;
+
+ rc = pcm_ops_disasm_format(arguments[0], "%s 0x%04x", desc->mnemonic, address);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
static struct pcm_op_desc pcm_op_descs[] = {
{
.mnemonic = "nop",
@@ -353,16 +435,16 @@ static struct pcm_op_desc pcm_op_descs[] = {
.mask = PCM_OP_JUMP_MASK,
.value = PCM_OP_JUMP_VALUE,
.padding = 1,
- .asm_callback = pcm_op_jump_call_asm,
- .disasm_callback = pcm_op_jump_call_disasm,
+ .asm_callback = pcm_op_jump_asm,
+ .disasm_callback = pcm_op_jump_disasm,
},
{
.mnemonic = "call",
.mask = PCM_OP_CALL_MASK,
.value = PCM_OP_CALL_VALUE,
.padding = 1,
- .asm_callback = pcm_op_jump_call_asm,
- .disasm_callback = pcm_op_jump_call_disasm,
+ .asm_callback = pcm_op_call_asm,
+ .disasm_callback = pcm_op_call_disasm,
},
{
.mnemonic = "ret",
@@ -440,11 +522,9 @@ int pcm_op_asm(char *arguments[], unsigned int count)
else
count = 0;
- rc = pcm_op_padding_asm(arguments, count, desc->padding);
+ rc = pcm_op_padding_asm(desc->padding);
if (rc < 0)
return -1;
-
- increment += rc;
}
return increment;
@@ -477,3 +557,12 @@ int pcm_op_disasm(unsigned int *arguments, unsigned int count)
return increment;
}
+
+/*
+ * PCM padding
+ */
+
+int pcm_padding_asm(unsigned int padding)
+{
+ return pcm_op_padding_asm(padding);
+}