#include #include #include #include #include #include #include #include #include "memarray.h" //--- // Utilities //--- /* Code of exception that occurs during a memory access */ static uint32_t exception = 0; /* Exception-catching function */ static int catch_exc(uint32_t code) { if(code == 0x100 || code == 0x0e0) { exception = code; gint_exc_skip(1); return 0; } return 1; } /* memory_protected_call(): Wrapper that protects against access errors */ static int memory_protected_call(gint_call_t function) { exception = 0; gint_exc_catch(catch_exc); int rc = gint_call(function); gint_exc_catch(NULL); return rc || (exception != 0); } //--- // Public API //--- void memarray_set(uint8_t *rc, int position, int value) { int index = 1 + (position >> 3); uint8_t byte = 0x80 >> (position & 7); if(index >= rc[0]) return; if(value) rc[index] |= byte; else rc[index] &= ~byte; } int memarray_get(uint8_t *rc, int position) { int index = 1 + (position >> 3); uint8_t byte = 0x80 >> (position & 7); if(index >= rc[0]) return -1; return (rc[index] & byte) != 0; } void memarray_assert(uint8_t *rc, ft_test *test) { for(int i = 0; true; i++) { int v = memarray_get(rc, i); if(v < 0) return; ft_assert(test, v == 0); } } void memarray_single(uint8_t *rc, memarray_func_t f) { uint8_t buf1[128], buf2[128]; int counter = 0; rc[0] = MEMARRAY_RC_SINGLE; memarray_args_t args = { .full_buf1 = buf1, .full_buf2 = buf2, .full_size = 128, }; gint_call_t call = GINT_CALL(f, (void *)&args); for(int buf_al = 0; buf_al < 4; buf_al++) for(int len_al = 0; len_al < 4; len_al++) { args.buf1 = buf1 + 8 + buf_al; args.buf2 = buf2 + 8 + buf_al; args.size = 12 + len_al; memarray_set(rc, counter++, memory_protected_call(call)); args.buf1 = buf1 + 8 + buf_al; args.buf2 = buf2 + 8 + buf_al; args.size = 92 + len_al; memarray_set(rc, counter++, memory_protected_call(call)); } } void memarray_double(uint8_t *rc, bool overlap, memarray_func_t f) { uint8_t left1[128], left2[128], right1[128], right2[128]; int counter = 0; rc[0] = overlap ? MEMARRAY_RC_DOUBLE_OVERLAP : MEMARRAY_RC_DOUBLE; memarray_args_t args = { .full_left1 = left1, .full_left2 = left2, .full_right1 = right1, .full_right2 = right2, .full_size = 128, }; gint_call_t call = GINT_CALL(f, (void *)&args); for(int left_al = 0; left_al < 4; left_al++) for(int right_al = 0; right_al < 4; right_al++) for(int len_al = 0; len_al < 4; len_al++) { args.left1 = left1 + 8 + left_al; args.left2 = left2 + 8 + left_al; args.right1 = right1 + 8 + right_al; args.right2 = right2 + 8 + right_al; args.size = 12 + len_al; memarray_set(rc, counter++, memory_protected_call(call)); args.left1 = left1 + 8 + left_al; args.left2 = left2 + 8 + left_al; args.right1 = right1 + 8 + right_al; args.right2 = right2 + 8 + right_al; args.size = 92 + len_al; memarray_set(rc, counter++, memory_protected_call(call)); if(!overlap) continue; /* In overlap mode, only use left1 and left2 to create an overlap */ args.left1 = left1 + left_al; args.left2 = left2 + left_al; args.right1 = left1 + 28 + right_al; args.right2 = left2 + 28 + right_al; args.size = 92 + len_al; memarray_set(rc, counter++, memory_protected_call(call)); args.left1 = left1 + 28 + left_al; args.left2 = left2 + 28 + left_al; args.right1 = left1 + right_al; args.right2 = left2 + right_al; args.size = 92 + len_al; memarray_set(rc, counter++, memory_protected_call(call)); } } //--- // Visualization widget //--- static void paint_results(int x, int y, uint8_t *rc) { dprint_opt(x+222, y, C_BLACK, C_NONE, DTEXT_CENTER, DTEXT_TOP, "Source align and destination align"); for(int i = 0; i < 16; i++) dprint(x + 74 + 18*i + 3*(i/4), y+12, C_BLACK, "%d%d", i/4, i & 3); int sizes = 0; if(rc[0] == MEMARRAY_RC_SINGLE) sizes = 2; if(rc[0] == MEMARRAY_RC_DOUBLE) sizes = 2; if(rc[0] == MEMARRAY_RC_DOUBLE_OVERLAP) sizes = 4; char const *size_names[4] = { "Small", "Large", "Over-L", "Over-R" }; for(int i = 0; i < 4; i++) { dprint_opt(x+55, y + 43 + 42*i, C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_MIDDLE, "%s", size_names[i]); } for(int i = 0; i < 16; i++) dprint_opt(x+64, y + 25 + 10*i + 2*(i/4), C_BLACK, C_NONE, DTEXT_CENTER, DTEXT_TOP, "%d", i & 3); for(int row = 0; row < 16; row++) for(int col = 0; col < 16; col++) { int x1 = x + 72 + 18*col + 3*(col/4); int y1 = y + 24 + 10*row + 2*(row/4); int value = -1; if(row < 4*sizes) value = memarray_get(rc, 4*sizes * col + row); int fg = (value == -1) ? C_WHITE : (value == 0) ? C_GREEN : C_RED; drect_border(x1, y1, x1+19, y1+10, fg, 1, C_BLACK); } } jwidget *memarray_widget(uint8_t *rc) { jpainted *p = jpainted_create(paint_results, rc, 377, 185, NULL); if(!p) return NULL; jwidget_set_margin(p, 4, 4, 4, 4); return &p->widget; }