summaryrefslogtreecommitdiff
path: root/masm/sectab.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-09-11 12:06:09 -0400
committerFreya Murphy <freya@freyacat.org>2024-09-11 12:06:09 -0400
commite3d2e31377030e84066bed4bbc04bf6c56206305 (patch)
treed5e7428212606a0f64d5b2e628b3f507948b8e2f /masm/sectab.c
parentjoe (diff)
downloadmips-e3d2e31377030e84066bed4bbc04bf6c56206305.tar.gz
mips-e3d2e31377030e84066bed4bbc04bf6c56206305.tar.bz2
mips-e3d2e31377030e84066bed4bbc04bf6c56206305.zip
refactor
Diffstat (limited to 'masm/sectab.c')
-rw-r--r--masm/sectab.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/masm/sectab.c b/masm/sectab.c
new file mode 100644
index 0000000..d07399f
--- /dev/null
+++ b/masm/sectab.c
@@ -0,0 +1,166 @@
+#include <string.h>
+#include <stdlib.h>
+#include <mips.h>
+#include <merror.h>
+#include <mlimits.h>
+
+#include "asm.h"
+
+#define SECTBL_INIT_LEN 8
+static const char inital_section[MAX_LEX_LENGTH] = "data";
+
+int sectab_init(struct section_table *sectab)
+{
+ sectab->size = SECTBL_INIT_LEN;
+ sectab->len = 0;
+ sectab->sections = malloc(sizeof(struct section) * SECTBL_INIT_LEN);
+
+ if (sectab->sections == NULL) {
+ ERROR("cannot alloc");
+ return M_ERROR;
+ }
+
+ if (sectab_alloc(sectab, &sectab->current, inital_section))
+ return M_ERROR;
+
+ return M_SUCCESS;
+}
+
+void sectab_free(struct section_table *sectab)
+{
+ for (size_t i = 0; i < sectab->len; i++) {
+ reltab_free(&sectab->sections[i].reltab);
+ free(sectab->sections[i].entries);
+ }
+ free(sectab->sections);
+}
+
+struct section_settings {
+ const char *name;
+ bool read;
+ bool write;
+ bool execute;
+ size_t align;
+};
+
+static struct section_settings default_section_settings[] = {
+ {"data", true, true, false, 1},
+ {"bss", true, true, false, 1},
+ {"rodata", true, false, false, 1},
+ {"text", true, false, true, 4},
+};
+
+int sectab_alloc(struct section_table *sectab, struct section **res,
+ const char name[MAX_LEX_LENGTH])
+{
+ if (sectab->len >= sectab->size) {
+ sectab->size *= 2;
+ sectab->sections = realloc(sectab->sections,
+ sizeof(struct section) * sectab->size);
+
+ if (sectab->sections == NULL) {
+ ERROR("cannot realloc");
+ return M_ERROR;
+ }
+ }
+
+ /* set the sectio defaults */
+ struct section *sec;
+ sec = &sectab->sections[sectab->len];
+ strcpy(sec->name,name);
+ sec->len = 0;
+ sec->size = SECTBL_INIT_LEN;
+ sec->alignment = 1;
+ sec->read = true;
+ sec->write = true;
+ sec->execute = false;
+ sec->index = sectab->len;
+ sec->entries = malloc(sizeof(struct section_entry) * SECTBL_INIT_LEN);
+
+ if (reltab_init(&sec->reltab))
+ return M_ERROR;
+
+ /* overwrite the default if the given name has their own
+ * defaults */
+ for (int i = 0; i < 4; i++) {
+ struct section_settings *set = &default_section_settings[i];
+ if (strcmp(set->name, name) == 0) {
+ sec->read = set->read;
+ sec->write = set->write;
+ sec->execute = set->execute;
+ sec->alignment = set->align;
+ break;
+ }
+ }
+
+ if (sec->entries == NULL) {
+ ERROR("cannot alloc");
+ return M_ERROR;
+ }
+
+ sectab->len++;
+
+ *res = sec;
+ return M_SUCCESS;
+}
+
+int sectab_get(struct section_table *sectab, struct section **sec,
+ const char name[MAX_LEX_LENGTH])
+{
+ for (size_t i = 0; i < sectab->len; i++) {
+ struct section *temp = &sectab->sections[i];
+ if (strcmp(name, temp->name) == 0) {
+ if (sec != NULL)
+ *sec = temp;
+ return M_SUCCESS;
+ }
+ }
+
+ return M_ERROR;
+}
+
+int sec_push(struct section *section, struct section_entry entry)
+{
+ if (section->len >= section->size) {
+ section->size *= 2;
+ void *new = realloc(section->entries,
+ sizeof(struct section_entry) * section->size);
+
+ if (new == NULL) {
+ ERROR("cannot realloc");
+ return M_ERROR;
+ }
+
+ section->entries = new;
+ }
+
+ section->entries[section->len++] = entry;
+
+ return M_SUCCESS;
+}
+
+size_t sec_size(struct section *sec)
+{
+ size_t n = 0;
+ for (size_t i = 0; i < sec->len; i++) {
+ size_t t = sec->entries[i].size;
+ size_t m = t % sec->alignment;
+ if (m)
+ t += sec->alignment - m;
+ n += t;
+ }
+ return n;
+}
+
+size_t sec_index(struct section *sec, size_t idx)
+{
+ size_t n = 0;
+ for (size_t i = 0; i < idx; i++) {
+ size_t t = sec->entries[i].size;
+ size_t m = t % sec->alignment;
+ if (m)
+ t += sec->alignment - m;
+ n += t;
+ }
+ return n;
+}