summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/c/sail.h297
1 files changed, 228 insertions, 69 deletions
diff --git a/test/c/sail.h b/test/c/sail.h
index abd86a71..2363c27e 100644
--- a/test/c/sail.h
+++ b/test/c/sail.h
@@ -363,46 +363,65 @@ void xor_bits(bv_t *rop, const bv_t op1, const bv_t op2) {
mpz_t eq_bits_test;
-bool eq_bits(const bv_t op1, const bv_t op2) {
- mpz_xor(eq_bits_test, *op1.bits, *op2.bits);
- return mpz_popcount(eq_bits_test) == 0;
+bool eq_bits(const bv_t op1, const bv_t op2)
+{
+ for (mp_bitcnt_t i = 0; i < op1.len; i++) {
+ if (mpz_tstbit(*op1.bits, i) != mpz_tstbit(*op2.bits, i)) return false;
+ }
+ return true;
}
+// These aren't very efficient, but they work. Question is how best to
+// do these given GMP uses a sign bit representation?
void sail_uint(mpz_t *rop, const bv_t op) {
- mpz_set(*rop, *op.bits);
+ mpz_set_ui(*rop, 0ul);
+ for (mp_bitcnt_t i = 0; i < op.len; ++i) {
+ if (mpz_tstbit(*op.bits, i)) {
+ mpz_setbit(*rop, i);
+ } else {
+ mpz_clrbit(*rop, i);
+ }
+ }
}
-void sint(mpz_t *rop, const bv_t op) {
+void sint(mpz_t *rop, const bv_t op)
+{
+ mpz_set_ui(*rop, 0ul);
if (mpz_tstbit(*op.bits, op.len - 1)) {
- mpz_set(*rop, *op.bits);
- mpz_clrbit(*rop, op.len - 1);
- mpz_t x;
- mpz_init(x);
- mpz_setbit(x, op.len - 1);
- mpz_neg(x, x);
- mpz_add(*rop, *rop, *op.bits);
- mpz_clear(x);
+ for (mp_bitcnt_t i = 0; i < op.len; ++i) {
+ if (mpz_tstbit(*op.bits, i)) {
+ mpz_clrbit(*rop, i);
+ } else {
+ mpz_setbit(*rop, i);
+ }
+ };
+ mpz_add_ui(*rop, *rop, 1ul);
+ mpz_neg(*rop, *rop);
} else {
- mpz_set(*rop, *op.bits);
+ for (mp_bitcnt_t i = 0; i < op.len; ++i) {
+ if (mpz_tstbit(*op.bits, i)) {
+ mpz_setbit(*rop, i);
+ } else {
+ mpz_clrbit(*rop, i);
+ }
+ }
}
}
void add_bits(bv_t *rop, const bv_t op1, const bv_t op2) {
rop->len = op1.len;
mpz_add(*rop->bits, *op1.bits, *op2.bits);
- mpz_clrbit(*rop->bits, op1.len);
}
void add_bits_int(bv_t *rop, const bv_t op1, const mpz_t op2) {
rop->len = op1.len;
mpz_add(*rop->bits, *op1.bits, op2);
- mask(rop);
}
void sub_bits_int(bv_t *rop, const bv_t op1, const mpz_t op2) {
+ printf("sub_bits_int\n");
rop->len = op1.len;
mpz_sub(*rop->bits, *op1.bits, op2);
- mask(rop);
}
// Takes a slice of the (two's complement) binary representation of
@@ -497,9 +516,12 @@ int bitvector_access(const bv_t op, const mpz_t n_mpz) {
return mpz_tstbit(*op.bits, n);
}
-void hex_slice (bv_t *rop, const sail_string hex, const mpz_t n, const mpz_t m) {
- fprintf(stderr, "hex_slice unimplemented");
- exit(1);
+// Like slice but slices from a hexadecimal string.
+void hex_slice (bv_t *rop, const sail_string hex, const mpz_t len_mpz, const mpz_t start_mpz) {
+ mpz_t op;
+ mpz_init_set_str(op, hex, 0);
+ get_slice_int(rop, len_mpz, op, start_mpz);
+ mpz_clear(op);
}
void set_slice (bv_t *rop,
@@ -579,6 +601,7 @@ void abs_real(real *rop, const real op) {
void round_up(mpz_t *rop, const real op) {
mpf_t x;
+ mpf_init(x);
mpf_ceil(x, op);
mpz_set_ui(*rop, mpf_get_ui(x));
mpf_clear(x);
@@ -586,6 +609,7 @@ void round_up(mpz_t *rop, const real op) {
void round_down(mpz_t *rop, const real op) {
mpf_t x;
+ mpf_init(x);
mpf_floor(x, op);
mpz_set_ui(*rop, mpf_get_ui(x));
mpf_clear(x);
@@ -629,70 +653,205 @@ void init_real_of_sail_string(real *rop, const sail_string op) {
#endif
-// ***** Memory *****
+/* ***** Sail memory builtins ***** */
-unit write_ram(const mpz_t m, const mpz_t n, const bv_t x, const bv_t y, const bv_t data) {
- fprintf(stderr, "write_ram unimplemented");
- exit(1);
+/* We organise memory available to the sail model into a linked list
+ of dynamically allocated MASK + 1 size blocks. The most recently
+ written block is moved to the front of the list, so contiguous
+ accesses should be as fast as possible. */
+
+struct block {
+ uint64_t block_id;
+ uint8_t *mem;
+ struct block *next;
+};
+
+struct block *sail_memory = NULL;
+
+/* Must be one less than a power of two. */
+uint64_t MASK = 0xFFFFul;
+
+// All sail vectors are at least 64-bits, but only the bottom 8 bits
+// are used in the second argument.
+void write_mem(uint64_t address, uint64_t byte)
+{
+ uint64_t mask = address & ~MASK;
+ uint64_t offset = address & MASK;
+
+ struct block *prev = NULL;
+ struct block *current = sail_memory;
+
+ while (current != NULL) {
+ if (current->block_id == mask) {
+ current->mem[offset] = (uint8_t) byte;
+
+ /* Move the accessed block to the front of the block list */
+ if (prev != NULL) {
+ prev->next = current->next;
+ }
+ current->next = sail_memory->next;
+ sail_memory = current;
+
+ return;
+ } else {
+ prev = current;
+ current = current->next;
+ }
+ }
+
+ /* If we couldn't find a block matching the mask, allocate a new
+ one, write the byte, and put it at the front of the block
+ list. */
+ struct block *new_block = malloc(sizeof(struct block));
+ new_block->block_id = mask;
+ new_block->mem = calloc(MASK + 1, sizeof(uint8_t));
+ new_block->mem[offset] = byte;
+ new_block->next = sail_memory;
+ sail_memory = new_block;
+}
+
+uint64_t read_mem(uint64_t address)
+{
+ uint64_t mask = address & ~MASK;
+ uint64_t offset = address & MASK;
+
+ struct block *current = sail_memory;
+
+ while (current != NULL) {
+ if (current->block_id == mask) {
+ return (uint64_t) current->mem[offset];
+ } else {
+ current = current->next;
+ }
+ }
+
+ return 0;
}
-void read_ram(bv_t *data, const mpz_t m, const mpz_t n, const bv_t x, const bv_t addr_bv) {
+void kill_mem()
+{
+ while (sail_memory != NULL) {
+ struct block *next = sail_memory->next;
+
+ free(sail_memory->mem);
+ free(sail_memory);
+
+ sail_memory = next;
+ }
+}
+
+// ***** ARM Memory builtins *****
+
+// These memory builtins are intended to match the semantics for the
+// __ReadRAM and __WriteRAM functions in ASL.
+
+unit write_ram(const mpz_t addr_size, // Either 32 or 64
+ const mpz_t data_size_mpz, // Number of bytes
+ const bv_t hex_ram, // Currently unused
+ const bv_t addr_bv,
+ const bv_t data)
+{
uint64_t addr = mpz_get_ui(*addr_bv.bits);
- uint32_t instr;
- switch (addr) {
- // print_char
- case 0x400110: instr = 0xd10043ffu; break;
- case 0x400114: instr = 0x39003fe0u; break;
- case 0x400118: instr = 0x39403fe0u; break;
- case 0x40011c: instr = 0x580003e1u; break;
- case 0x400120: instr = 0x39000020u; break;
- case 0x400124: instr = 0xd503201fu; break;
- case 0x400128: instr = 0x910043ffu; break;
- case 0x40012c: instr = 0xd65f03c0u; break;
- // _start
- case 0x400130: instr = 0xa9be7bfdu; break;
- case 0x400134: instr = 0x910003fdu; break;
- case 0x400138: instr = 0x94000007u; break;
- case 0x40013c: instr = 0xb9001fa0u; break;
- case 0x400140: instr = 0x52800080u; break;
- case 0x400144: instr = 0x97fffff3u; break;
- case 0x400148: instr = 0xd503201fu; break;
- case 0x40014c: instr = 0xa8c27bfdu; break;
- case 0x400150: instr = 0xd65f03c0u; break;
- // main
- case 0x400154: instr = 0xd10043ffu; break;
- case 0x400158: instr = 0xb9000fffu; break;
- case 0x40015c: instr = 0xb9000bffu; break;
- case 0x400160: instr = 0x14000007u; break;
- case 0x400164: instr = 0xb9400fe0u; break;
- case 0x400168: instr = 0x11000400u; break;
- case 0x40016c: instr = 0xb9000fe0u; break;
- case 0x400170: instr = 0xb9400be0u; break;
- case 0x400174: instr = 0x11000400u; break;
- case 0x400178: instr = 0xb9000be0u; break;
- case 0x40017c: instr = 0xb9400be0u; break;
- case 0x400180: instr = 0x710fa01fu; break;
- case 0x400184: instr = 0x54ffff0du; break;
- case 0x400188: instr = 0xb9400fe0u; break;
- case 0x40018c: instr = 0x910043ffu; break;
- case 0x400190: instr = 0xd65f03c0u; break;
- case 0x400194: instr = 0x00000000u; break;
- case 0x400198: instr = 0x13000000u; break;
- case 0x40019c: instr = 0x00000000u; break;
+ uint64_t data_size = mpz_get_ui(data_size_mpz);
+
+ mpz_t buf;
+ mpz_init_set(buf, *data.bits);
+
+ uint64_t byte;
+ for(uint64_t i = 0; i < data_size; ++i) {
+ // Take the 8 low bits of buf and write to addr.
+ byte = mpz_get_ui(buf) & 0xFF;
+ write_mem(addr + i, byte);
+
+ // Then shift buf 8 bits right, and increment addr.
+ mpz_fdiv_q_2exp(buf, buf, 8);
+ }
+
+ mpz_clear(buf);
+ return UNIT;
+}
+
+void read_ram(bv_t *data,
+ const mpz_t addr_size,
+ const mpz_t data_size_mpz,
+ const bv_t hex_ram,
+ const bv_t addr_bv)
+{
+ uint64_t addr = mpz_get_ui(*addr_bv.bits);
+ uint64_t data_size = mpz_get_ui(data_size_mpz);
+
+ mpz_set_ui(*data->bits, 0);
+ data->len = data_size * 8;
+
+ mpz_t byte;
+ mpz_init(byte);
+ for(uint64_t i = data_size; i > 0; --i) {
+ mpz_set_ui(byte, read_mem(addr + (i - 1)));
+ mpz_mul_2exp(*data->bits, *data->bits, 8);
+ mpz_add(*data->bits, *data->bits, byte);
}
- mpz_set_ui(*data->bits, instr);
- data->len = 32;
- // print_bits("instruction = ", *data);
+ mpz_clear(byte);
+}
+
+void load_instr(uint64_t addr, uint32_t instr) {
+ write_mem(addr, instr & 0xFF);
+ write_mem(addr + 1, instr >> 8 & 0xFF);
+ write_mem(addr + 2, instr >> 16 & 0xFF);
+ write_mem(addr + 3, instr >> 24 & 0xFF);
+}
+
+void elf_hack(void) {
+ // print_char
+ load_instr(0x400110ul, 0xd10043ffu);
+ load_instr(0x400114ul, 0x39003fe0u);
+ load_instr(0x400118ul, 0x39403fe0u);
+ load_instr(0x40011cul, 0x580003e1u);
+ load_instr(0x400120ul, 0x39000020u);
+ load_instr(0x400124ul, 0xd503201fu);
+ load_instr(0x400128ul, 0x910043ffu);
+ load_instr(0x40012cul, 0xd65f03c0u);
+ // _start
+ load_instr(0x400130ul, 0xa9be7bfdu);
+ load_instr(0x400134ul, 0x910003fdu);
+ load_instr(0x400138ul, 0x94000007u);
+ load_instr(0x40013cul, 0xb9001fa0u);
+ load_instr(0x400140ul, 0x52800080u);
+ load_instr(0x400144ul, 0x97fffff3u);
+ load_instr(0x400148ul, 0xd503201fu);
+ load_instr(0x40014cul, 0xa8c27bfdu);
+ load_instr(0x400150ul, 0xd65f03c0u);
+ // main
+ load_instr(0x400154ul, 0xd10043ffu);
+ load_instr(0x400158ul, 0xb9000fffu);
+ load_instr(0x40015cul, 0xb9000bffu);
+ load_instr(0x400160ul, 0x14000007u);
+ load_instr(0x400164ul, 0xb9400fe0u);
+ load_instr(0x400168ul, 0x11000400u);
+ load_instr(0x40016cul, 0xb9000fe0u);
+ load_instr(0x400170ul, 0xb9400be0u);
+ load_instr(0x400174ul, 0x11000400u);
+ load_instr(0x400178ul, 0xb9000be0u);
+ load_instr(0x40017cul, 0xb9400be0u);
+ load_instr(0x400180ul, 0x710fa01fu);
+ load_instr(0x400184ul, 0x54ffff0du);
+ load_instr(0x400188ul, 0xb9400fe0u);
+ load_instr(0x40018cul, 0x910043ffu);
+ load_instr(0x400190ul, 0xd65f03c0u);
+ load_instr(0x400194ul, 0x00000000u);
+ load_instr(0x400198ul, 0x13000000u);
+ load_instr(0x40019cul, 0x00000000u);
}
// ***** Setup and cleanup functions for library code *****
void setup_library(void) {
+ elf_hack();
mpf_set_default_prec(FLOAT_PRECISION);
mpz_init(eq_bits_test);
}
void cleanup_library(void) {
mpz_clear(eq_bits_test);
+ kill_mem();
}