diff options
-rw-r--r-- | GNUmakefile | 5 | ||||
-rw-r--r-- | misc/radare2/asm_fspec.c | 13 | ||||
-rw-r--r-- | spec/ability.fspec | 30 | ||||
-rw-r--r-- | src/bin/fspec-dump.c | 22 | ||||
-rw-r--r-- | src/compiler/compiler.lm | 137 |
5 files changed, 67 insertions, 140 deletions
diff --git a/GNUmakefile b/GNUmakefile index a2be9ac..fd03496 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -13,7 +13,7 @@ override CPPFLAGS ?= -D_FORTIFY_SOURCE=2 override CPPFLAGS += -Isrc override COLMFLAGS += -Isrc/compiler -bins = fspec-info fspec-dump dec2bin xidec xi2path xils xifile uneaf +bins = fspec-info fspec-dump dec2bin xidec xi2path xils xifile uneaf uncws all: $(bins) %.c: %.lm @@ -49,6 +49,9 @@ xifile: src/bin/xi/xifile.c uneaf: private LDLIBS += $(shell pkg-config --libs-only-l zlib) uneaf: src/bin/fw/uneaf.c +uncws: private LDLIBS += $(shell pkg-config --libs-only-l zlib) +uncws: src/bin/bsw/uncws.c + install-bin: $(bins) install -Dm755 $^ -t "$(DESTDIR)$(PREFIX)$(bindir)" diff --git a/misc/radare2/asm_fspec.c b/misc/radare2/asm_fspec.c index 9eb28ea..b93450e 100644 --- a/misc/radare2/asm_fspec.c +++ b/misc/radare2/asm_fspec.c @@ -13,11 +13,9 @@ enum fspec_instruction { INS_PUSH, INS_PUSHR, INS_POP, - INS_INCR, INS_OP, INS_QUEUE, INS_IO, - INS_EXEC, INS_CALL, INS_JMP, INS_JMPIF @@ -55,12 +53,10 @@ ins_name_str(const enum fspec_instruction name) case INS_REG: return "reg"; case INS_PUSH: return "push"; case INS_PUSHR: return "pushr"; - case INS_INCR: return "incr"; case INS_POP: return "pop"; case INS_OP: return "op"; case INS_QUEUE: return "queue"; case INS_IO: return "io"; - case INS_EXEC: return "exec"; case INS_CALL: return "call"; case INS_JMP: return "jmp"; case INS_JMPIF: return "jmpif"; @@ -108,19 +104,20 @@ disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) } u = {0}; memcpy(u.v, buf, R_MIN(1, (size_t)len)); - const uint8_t insw = 1 << u.ins.n; + uint8_t insw = 1 << u.ins.n; memcpy(u.v, buf, R_MIN(insw, len)); const char *buf_asm = "invalid"; - const bool reg_arg = (u.ins.name == INS_PUSHR || u.ins.name == INS_INCR || u.ins.name == INS_POP || - u.ins.name == INS_EXEC || u.ins.name == INS_CALL); + const bool reg_arg = (u.ins.name == INS_PUSHR || u.ins.name == INS_POP || u.ins.name == INS_CALL); if (u.ins.name == INS_OP) buf_asm = sdb_fmt("%s %s", ins_name_str(u.ins.name), op_name_str(u.ins.v)); else if (reg_arg) buf_asm = sdb_fmt("%s r%" PRIu64, ins_name_str(u.ins.name), (uint64_t)u.ins.v); - else + else if (u.ins.v != ((uint64_t)1 << 57) - 1) buf_asm = sdb_fmt("%s %" PRIu64, ins_name_str(u.ins.name), (uint64_t)u.ins.v); + else + insw = 1; // ff invalid r_strbuf_set(&op->buf_asm, buf_asm); return (op->size = insw + (u.ins.name == INS_REG ? u.ins.v : 0)); diff --git a/spec/ability.fspec b/spec/ability.fspec index 5a695a0..fa1281b 100644 --- a/spec/ability.fspec +++ b/spec/ability.fspec @@ -42,30 +42,16 @@ struct dat { // PUSH<v> | 0x02 | Pushes `v` to the stack. // PUSHR<r?> | 0x03 | Pushes the contents of register `r?` to the stack. // POP<r?> [v] | 0x04 | Pops `v` into register `r?`. -// INCR<r?> | 0x05 | Increments the register `r?` by one. -// OP<op> [...] | 0x06 | Performs operation specified by the `op`, and pushes the result to the stack. -// QUEUE<len> (...) | 0x07 | Queues next `len` bytes for execution for the next `IO` instruction. +// OP<op> [...] | 0x05 | Performs operation specified by the `op`, and pushes the result to the stack. +// QUEUE<len> (...) | 0x06 | Queues next `len` bytes for execution for the next `IO` instruction. // * * The code is executed before or after `IO` instruction, depending whether VM is packing or unpacking. -// IO<sz> (...) | 0x08 | Unpacking: Reads data from external VM input (usually a file) to register pointed by `r1`. -// * * Packing: Writes data to external VM output (usually a file) from register pointed by `r1`. +// IO<sz> [r?] (...) | 0x07 | Unpacking: Reads data from external VM input (usually a file) to register `r?`. +// * * Packing: Writes data to external VM output (usually a file) from register `r?`. // * * `sz` is the size of the element in bits. // * * Rest of the stack is the number of elements, if empty, the elements to read/write is 1. -// EXEC<r?> [r??] (...) | 0x09 | Sets `r1` to `r??` and executes instructions stored in register `r?`. -// * * Rest of the stack is the number of times to execute, if empty, execution happens only once. -// * * `r1` will be saved and restored during this instruction. -// CALL<r?> (...) | 0x0A | Calls a function. The name of the function is stored in register `r?`. -// JMP<off> | 0x0B | Jumps to the `off` (in bytes). -// JMPIF<off> [v] | 0x0C | Performs `JMP`, if `v` is true. -// STRUCT<r?> [r??] | 0x0D | Describes register `r?` as struct structure. register `r??` contains the name of the struct. -// SELECT<r?> | 0x0E | Describes register `r?` as select structure. -// FIELD<r?> (...) | 0x0F | Links field to last structure. register `r?` contains the name of the field. -// * * Rest of the stack contains register indices for registers that are instances of this field. -// BSZ<s:1, v> [sz] | 0x10 | Describes last field as a primitive field. `s` describes whether the field is signed. `v` describes how the -// * * field should be represented. `sz` contains the size of field in bits. -// REF<r?> | 0x11 | Describes field as a substructure. register `r?` contains the structure definition. -// FDIMENSION<sz> | 0x12 | Adds fixed dimension to a field. `sz` indicates the size of the dimension. -// VDIMENSION | 0x13 | Adds variable length dimension to a field. -// ENUM<r?> | 0x14 | Links field to a enum +// CALL<r?> (...) | 0x08 | Calls a function. The name of the function is stored in register `r?`. +// JMP<off> | 0x09 | Jumps to the `off` (in bytes). +// JMPIF<off> [v] | 0x0A | Performs `JMP`, if `v` is true. // // List of operations for the `OP` instruction: // Name | Hex | Argc | Description @@ -91,7 +77,7 @@ struct dat { // CTERNARY | 0x13 | 3 | Conditional ternary operation `v1 ? v2 : v3` // SUBSCRIPT | 0x14 | 2 | Subscript operation `v1[v2]` // -// List of visuals for the `PIO` instruction: +// List of visuals: // Name | Hex | Representation // NUL | 0x00 | None // DEC | 0x01 | Decimal diff --git a/src/bin/fspec-dump.c b/src/bin/fspec-dump.c index e7993e6..5732018 100644 --- a/src/bin/fspec-dump.c +++ b/src/bin/fspec-dump.c @@ -164,11 +164,9 @@ enum fspec_instruction { INS_PUSH, INS_PUSHR, INS_POP, - INS_INCR, INS_OP, INS_QUEUE, INS_IO, - INS_EXEC, INS_CALL, INS_JMP, INS_JMPIF, @@ -415,10 +413,6 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co fprintf(stderr, "POP R: %lu\n", insv); stack_pop(&ctx->S, &ctx->R.value[insv]); break; - case INS_INCR: - fprintf(stderr, "INCR R: %lu\n", insv); - register_set_num(&ctx->R.value[insv], &ctx->mem, register_get_num(&ctx->R.value[insv], &ctx->mem) + 1); - break; case INS_OP: fprintf(stderr, "OP op: %lu\n", insv); do_op(ctx, insv); @@ -428,6 +422,7 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co break; case INS_IO: { const uint64_t R = stack_pop_num(&ctx->S, &ctx->mem); + assert(R > 0 && R < ARRAY_SIZE(ctx->R.value)); fprintf(stderr, "IO: sz: %lu, R: %lu\n", insv, R); ctx->R.value[R].off = ctx->mem.ptr; const uint64_t szb = DIV_ROUND_UP(insv, CHAR_BIT), bpe = (szb * CHAR_BIT) / insv; @@ -442,21 +437,6 @@ fspec_execute(struct fspec_ctx *ctx, const uint8_t *ir, const uint64_t irlen, co return true; } break; - case INS_EXEC: { - fprintf(stderr, "EXEC R: %lu\n", insv); - const struct fspec_register old_r1 = ctx->R.value[1]; - stack_pop(&ctx->S, &ctx->R.value[1]); - uint64_t nmemb = 1; - do { - nmemb *= (ctx->S.numv ? stack_pop_num(&ctx->S, &ctx->mem) : 1); - fprintf(stderr, "off: %lu len: %lu nmemb: %lu\n", ctx->R.value[insv].off, ctx->R.value[insv].len, nmemb); - for (uint64_t i = 0; i < nmemb; ++i) - if (fspec_execute(ctx, ctx->mem.data + ctx->R.value[insv].off, ctx->R.value[insv].len, ind + INDSTP)) - return true; - } while (ctx->S.numv); - ctx->R.value[1] = old_r1; - } - break; case INS_CALL: { fprintf(stderr, "CALL R: %lu\n", insv); ctx->S.numv = 0; diff --git a/src/compiler/compiler.lm b/src/compiler/compiler.lm index 502422d..28e7f96 100644 --- a/src/compiler/compiler.lm +++ b/src/compiler/compiler.lm @@ -241,7 +241,6 @@ lookup(type:str, name:str, s:scope) global g_cscope:map<any, scope> = new map<any, scope>() global g_regs:map<any, int> = new map<any, int>() -global g_offs:map<any, int> = new map<any, int>() global g_ops:map<str, int> = new map<str, int>() global g_visuals:map<str, int> = new map<str, int>() global g_types:map<str, int> = new map<str, int>() @@ -283,22 +282,19 @@ global INS_REG:int = 1 global INS_PUSH:int = 2 global INS_PUSHR:int = 3 global INS_POP:int = 4 -global INS_INCR:int = 5 -global INS_OP:int = 6 -global INS_QUEUE:int = 7 -global INS_IO:int = 8 -global INS_EXEC:int = 9 -global INS_CALL:int = 10 -global INS_JMP:int = 11 -global INS_JMPIF:int = 12 +global INS_OP:int = 5 +global INS_QUEUE:int = 6 +global INS_IO:int = 7 +global INS_CALL:int = 8 +global INS_JMP:int = 9 +global INS_JMPIF:int = 10 int insbuf_written() = c_insbuf_written str flush_insbuf() = c_flush_insbuf void write_ins(ins:int, num:int) = c_write_ins void write_ins_with_data(ins:int, data:str) = c_write_ins_with_data -global g_r1:int = 1 -global g_regc:int = g_r1 + 1 +global g_regc:int = 1 void new_reg(v:any, data:str) @@ -334,6 +330,11 @@ find_data_in(s:any) write_ins(INS_VERSION, 1) write_ins_with_data(INS_REG, '') +for d:fspec::declaration::type in source { + if (d.primitive) + new_reg(%d, nil) +} + for e:expr::paren::type in source find_data_in(e.collapsed) for e:expr::bracket::type in source @@ -343,12 +344,14 @@ for e:expr::arg::type in source for f:reference::function::type in source write_data_if_not_there($f.name) for d:fspec::declaration::type in source { - if (d.name) - write_data_if_not_there($d.name) if (d.container && d.container.data.name) write_data_if_not_there($d.container.data.name) + if (d.name) + write_data_if_not_there($d.name) } +print("ASD\n") + void write_expr(expr:collapser::reducer::collapsed) { @@ -377,12 +380,10 @@ write_expr(expr:collapser::reducer::collapsed) off:int = 0 for r:reference::variable::type in vop { d = lookup('variable', $r.name, s) - if (d.container) { + if (d.container) s = g_cscope->find(%d.container) - off = g_offs->find(%d.container) - } } - write_ins(INS_PUSHR, off + g_regs->find(%d) - off) + write_ins(INS_PUSHR, g_regs->find(%d)) } else { write_ins(INS_OP, g_ops->find($vop.op)) } @@ -418,9 +419,6 @@ write_declaration(d:fspec::declaration::type, index:int) c:fspec::container::type = d.container if (d.cref) c = lookup($d.cref, $d.parent, nil) - if (!c && index > 0) - write_ins(INS_INCR, g_r1) - locs:map<any, int> = new map<any, int>() if (d.extra) { for l:fspec::declaration::dimension in repeat(d.extra.dimension) { @@ -436,10 +434,19 @@ write_declaration(d:fspec::declaration::type, index:int) } if (!c) { + write_ins(INS_PUSH, index) write_ins(INS_IO, d.primitive.bits) } else { - write_ins(INS_PUSH, g_offs->find(%c)) - write_ins(INS_EXEC, g_regs->find(%c)) + for i:fspec::container::strukt::item in repeat(d.container.data.items) { + if (i.data.name) { + write_declaration(i.data, index) + index = index + 1 + } else if (i.data.function) { + for a:expr::arg::type in i.data.function + write_expr(a.collapsed.result) + write_ins(INS_CALL, g_regs->find($i.data.function.name)) + } + } } if (d.extra) { @@ -448,40 +455,8 @@ write_declaration(d:fspec::declaration::type, index:int) } } -void -walk1(d:fspec::declaration::type) -{ - c:fspec::container::type = d.container - if (d.cref) c = lookup($d.cref, $d.parent, nil) - - if (!c || !d.name) - return 0 - - for i:fspec::container::strukt::item in repeat(d.container.data.items) - walk1(i.data) - - for i:fspec::container::select::item in repeat(d.container.data.items) - walk1(i.data) - - g_offs->insert(%d, g_regc) - - for i:fspec::container::enum::item in repeat(d.container.data.items) { - # somehow need to get this constant time (not reg) - } - - for i:fspec::container::strukt::item in repeat(d.container.data.items) { - if (i.data.primitive) - new_reg(%i.data, nil) - } - - for i:fspec::container::select::item in repeat(d.container.data.items) { - if (i.data.primitive) - new_reg(%i.data, nil) - } -} - -void -walk2(d:fspec::declaration::type) +int +walk2(d:fspec::declaration::type, index:int) { if (!d.container) { print('something went wrong!\n') @@ -497,37 +472,22 @@ walk2(d:fspec::declaration::type) insert('variable', $i.decl.name, %i.decl) for i:fspec::container::strukt::item in repeat(d.container.data.items) { - if (i.data.container) - walk2(i.data) - if (i.data.name) - insert('variable', $i.data.name, %i.data) - } - - for i:fspec::container::select::item in repeat(d.container.data.items) { - if (i.data.container) - walk2(i.data) - if (i.data.name) - insert('variable', $i.data.name, %i.data) - } - - if (!d.name) { - write_ins(INS_PUSH, g_offs->find(%d.container)) - write_ins(INS_POP, g_r1) - } - - index:int = 0 - for i:fspec::container::strukt::item in repeat(d.container.data.items) if (i.data.name) { + insert('variable', $i.data.name, %i.data) write_declaration(i.data, index) index = index + 1 } else if (i.data.function) { for a:expr::arg::type in i.data.function write_expr(a.collapsed.result) write_ins(INS_CALL, g_regs->find($i.data.function.name)) + } else if (i.data.container) { + index = walk2(i.data, index) } + } for i:fspec::container::select::item in repeat(d.container.data.items) { if (i.data.name) { + insert('variable', $i.data.name, %i.data) if (i.expr) { write_expr(d.container.data.select.collapsed.result) write_expr(i.expr.collapsed.result) @@ -535,26 +495,27 @@ walk2(d:fspec::declaration::type) } write_declaration(i.data, index) index = index + 1 + } else if (i.data.container) { + index = walk2(i.data, index) } } - if (insbuf_written()) { - new_reg(%d.container, flush_insbuf()) - print(flush_insbuf()) - } - g_cscope->insert(%d, g_scopes->top) if ($d.container.data.type != 'enum') pop_scope() -} -for d:fspec::declaration::type in repeat(source.items) - walk1(d) + return index +} push_scope() -for d:fspec::declaration::type in repeat(source.items) - walk2(d) -pop_scope() +index:int = 1 +for d:fspec::declaration::type in repeat(source.items) { + walk2(d, index) -print(flush_insbuf()) + if (insbuf_written()) { + write_ins_with_data(INS_REG, flush_insbuf()) + print(flush_insbuf()) + } +} +pop_scope() |