## This file was generated by running: ## cat functions/exit.c functions/file.c functions/file_print.c functions/malloc.c functions/calloc.c functions/match.c functions/numerate_number.c functions/string.c test/test23/M1-macro.c >| ../stage0/stage3/M1-macro_x86.c ## inside the M2-Planet repo ## Copyright (C) 2016 Jeremiah Orians ## This file is part of stage0. ## ## stage0 is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## stage0 is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with stage0. If not, see . // CONSTANT EXIT_FAILURE 1 // CONSTANT EXIT_SUCCESS 0 void exit(int value) { asm("POP_ebx" "POP_ebx" "LOAD_IMMEDIATE_eax %1" "INT_80"); } /* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * stage0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ // CONSTANT stdin 0 // CONSTANT stdout 1 // CONSTANT stderr 2 // CONSTANT EOF 0xFFFFFFFF int fgetc(FILE* f) { asm("LOAD_IMMEDIATE_eax %3" "LOAD_EFFECTIVE_ADDRESS_ebx %4" "LOAD_INTEGER_ebx" "PUSH_ebx" "COPY_esp_to_ecx" "LOAD_IMMEDIATE_edx %1" "INT_80" "TEST" "POP_eax" "JUMP_NE8 !FUNCTION_fgetc_Done" "LOAD_IMMEDIATE_eax %-1" ":FUNCTION_fgetc_Done"); } void fputc(char s, FILE* f) { asm("LOAD_IMMEDIATE_eax %4" "LOAD_EFFECTIVE_ADDRESS_ebx %4" "LOAD_INTEGER_ebx" "LOAD_EFFECTIVE_ADDRESS_ecx %8" "LOAD_IMMEDIATE_edx %1" "INT_80"); } /* Important values needed for open * O_RDONLY => 0 * O_WRONLY => 1 * O_RDWR => 2 * O_CREAT => 64 * O_TRUNC => 512 * S_IRWXU => 00700 * S_IXUSR => 00100 * S_IWUSR => 00200 * S_IRUSR => 00400 */ FILE* open(char* name, int flag, int mode) { asm("LOAD_EFFECTIVE_ADDRESS_ebx %12" "LOAD_INTEGER_ebx" "LOAD_EFFECTIVE_ADDRESS_ecx %8" "LOAD_INTEGER_ecx" "LOAD_EFFECTIVE_ADDRESS_edx %4" "LOAD_INTEGER_edx" "LOAD_IMMEDIATE_eax %5" "INT_80"); } FILE* fopen(char* filename, char* mode) { FILE* f; if('w' == mode[0]) { /* 577 is O_WRONLY|O_CREAT|O_TRUNC, 384 is 600 in octal */ f = open(filename, 577 , 384); } else { /* Everything else is a read */ f = open(filename, 0, 0); } /* Negative numbers are error codes */ if(0 > f) { return 0; } return f; } int close(int fd) { asm("LOAD_EFFECTIVE_ADDRESS_ebx %4" "LOAD_IMMEDIATE_eax %6" "INT_80"); } int fclose(FILE* stream) { int error = close(stream); return error; } /* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * stage0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ #include // void fputc(char s, FILE* f); void file_print(char* s, FILE* f) { while(0 != s[0]) { fputc(s[0], f); s = s + 1; } } ## Copyright (C) 2016 Jeremiah Orians ## This file is part of stage0. ## ## stage0 is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## stage0 is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with stage0. If not, see . // CONSTANT NULL 0 void* malloc(int size) { asm("STORE_eax_into_ESP_IMMEDIATE8 !4" "PUSH_eax" "LOAD_IMMEDIATE_eax %45" "LOAD_IMMEDIATE_ebx %0" "INT_80" "POP_ebx" "ADD_eax_to_ebx" "PUSH_eax" "PUSH_ebx" "LOAD_IMMEDIATE_eax %45" "INT_80" "POP_ebx" "CMP" "POP_eax" "JUMP_EQ8 !FUNCTION_malloc_Done" "LOAD_IMMEDIATE_eax %-1" ":FUNCTION_malloc_Done"); } /* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * stage0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ // void* malloc(int size); void* memset(void* ptr, int value, int num) { char* s; for(s = ptr; 0 < num; num = num - 1) { s[0] = value; s = s + 1; } } void* calloc(int count, int size) { void* ret = malloc(count * size); memset(ret, 0, (count * size)); return ret; } void free(void* l) { return; } /* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * stage0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ #define FALSE 0 // CONSTANT FALSE 0 #define TRUE 1 // CONSTANT TRUE 1 int match(char* a, char* b) { int i = -1; do { i = i + 1; if(a[i] != b[i]) { return FALSE; } } while((0 != a[i]) && (0 !=b[i])); return TRUE; } /* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * stage0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ #include #include // void* calloc(int count, int size); #define TRUE 1 //CONSTANT TRUE 1 #define FALSE 0 //CONSTANT FALSE 0 char* numerate_number(int a) { char* result = calloc(16, sizeof(char)); int i = 0; /* Deal with Zero case */ if(0 == a) { result[0] = '0'; return result; } /* Deal with negatives */ if(0 > a) { result[0] = '-'; i = 1; a = a * -1; } /* Using the largest 10^n number possible in 32bits */ int divisor = 0x3B9ACA00; /* Skip leading Zeros */ while(0 == (a / divisor)) divisor = divisor / 10; /* Now simply collect numbers until divisor is gone */ while(0 < divisor) { result[i] = ((a / divisor) + 48); a = a % divisor; divisor = divisor / 10; i = i + 1; } return result; } int char2hex(int c) { if (c >= '0' && c <= '9') return (c - 48); else if (c >= 'a' && c <= 'f') return (c - 87); else if (c >= 'A' && c <= 'F') return (c - 55); else return -1; } int hex2char(int c) { if((c >= 0) && (c <= 9)) return (c + 48); else if((c >= 10) && (c <= 15)) return (c + 55); else return -1; } int char2dec(int c) { if (c >= '0' && c <= '9') return (c - 48); else return -1; } int dec2char(int c) { if((c >= 0) && (c <= 9)) return (c + 48); else return -1; } int numerate_string(char *a) { int count = 0; int index; int negative; /* If NULL string */ if(0 == a[0]) { return 0; } /* Deal with hex */ else if (a[0] == '0' && a[1] == 'x') { if('-' == a[2]) { negative = TRUE; index = 3; } else { negative = FALSE; index = 2; } while(0 != a[index]) { if(-1 == char2hex(a[index])) return 0; count = (16 * count) + char2hex(a[index]); index = index + 1; } } /* Deal with decimal */ else { if('-' == a[0]) { negative = TRUE; index = 1; } else { negative = FALSE; index = 0; } while(0 != a[index]) { if(-1 == char2dec(a[index])) return 0; count = (10 * count) + char2dec(a[index]); index = index + 1; } } if(negative) { count = count * -1; } return count; } /* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * stage0 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with stage0. If not, see . */ #include #define MAX_STRING 4096 //CONSTANT MAX_STRING 4096 // void* calloc(int count, int size); char* copy_string(char* target, char* source) { while(0 != source[0]) { target[0] = source[0]; target = target + 1; source = source + 1; } return target; } char* postpend_char(char* s, char a) { char* ret = calloc(MAX_STRING, sizeof(char)); char* hold = copy_string(ret, s); hold[0] = a; return ret; } char* prepend_char(char a, char* s) { char* ret = calloc(MAX_STRING, sizeof(char)); ret[0] = a; copy_string((ret+1), s); return ret; } char* prepend_string(char* add, char* base) { char* ret = calloc(MAX_STRING, sizeof(char)); copy_string(copy_string(ret, add), base); return ret; } int string_length(char* a) { int i = 0; while(0 != a[i]) i = i + 1; return i; } /* -*- c-file-style: "linux";indent-tabs-mode:t -*- */ /* Copyright (C) 2016 Jeremiah Orians * Copyright (C) 2017 Jan Nieuwenhuizen * This file is part of mescc-tools. * * mescc-tools is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * mescc-tools is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with mescc-tools. If not, see . */ #include #include #include #include #define max_string 4096 //CONSTANT max_string 4096 #define MACRO 1 //CONSTANT MACRO 1 #define STR 2 //CONSTANT STR 2 #define TRUE 1 //CONSTANT TRUE 1 #define FALSE 0 //CONSTANT FALSE 0 void file_print(char* s, FILE* f); int match(char* a, char* b); int string_length(char* a); char* numerate_number(int a); int numerate_string(char *a); int hex2char(int c); FILE* source_file; FILE* destination_file; int BigEndian; int BigBitEndian; int ByteMode; int Architecture; struct Token { struct Token* next; int type; char* Text; char* Expression; }; struct Token* newToken() { struct Token* p; p = calloc (1, sizeof (struct Token)); if (NULL == p) { file_print("calloc failed.\n", stderr); exit (EXIT_FAILURE); } return p; } struct Token* reverse_list(struct Token* head) { struct Token* root = NULL; while(NULL != head) { struct Token* next = head->next; head->next = root; root = head; head = next; } return root; } void purge_lineComment() { int c = fgetc(source_file); while((10 != c) && (13 != c)) { c = fgetc(source_file); } } char* store_atom(char c) { char* store = calloc(max_string + 1, sizeof(char)); if(NULL == store) { file_print("Exhusted available memory\n", stderr); exit(EXIT_FAILURE); } int ch = c; int i = 0; do { store[i] = ch; ch = fgetc(source_file); i = i + 1; } while ((9 != ch) && (10 != ch) && (32 != ch) && (i <= max_string)); return store; } char* store_string(char c) { char* store = calloc(max_string + 1, sizeof(char)); if(NULL == store) { file_print("Exhusted available memory\n", stderr); exit(EXIT_FAILURE); } int ch = c; int i = 0; do { store[i] = ch; i = i + 1; ch = fgetc(source_file); if(-1 == ch) { file_print("Unmatched \"!\n", stderr); exit(EXIT_FAILURE); } if(max_string == i) { file_print("String: ", stderr); file_print(store, stderr); file_print(" exceeds max string size\n", stderr); exit(EXIT_FAILURE); } } while(ch != c); return store; } struct Token* Tokenize_Line(struct Token* head) { int c; struct Token* p; do { restart: c = fgetc(source_file); if((35 == c) || (59 == c)) { purge_lineComment(); goto restart; } if((9 == c) || (10 == c) || (32 == c)) { goto restart; } if(-1 == c) { goto done; } p = newToken(); if((34 == c) || (39 == c)) { p->Text = store_string(c); p->type = STR; } else { p->Text = store_atom(c); } p->next = head; head = p; } while(TRUE); done: return head; } void setExpression(struct Token* p, char *c, char *Exp) { struct Token* i; for(i = p; NULL != i; i = i->next) { /* Leave macros alone */ if((i->type & MACRO)) { continue; } else if(match(i->Text, c)) { /* Only if there is an exact match replace */ i->Expression = Exp; } } } void identify_macros(struct Token* p) { struct Token* i; for(i = p; NULL != i; i = i->next) { if(match(i->Text, "DEFINE")) { i->type = MACRO; i->Text = i->next->Text; if(i->next->next->type & STR) { i->Expression = i->next->next->Text + 1; } else { i->Expression = i->next->next->Text; } i->next = i->next->next->next; } } } void line_macro(struct Token* p) { struct Token* i; for(i = p; NULL != i; i = i->next) { if(i->type & MACRO) { setExpression(i->next, i->Text, i->Expression); } } } void hexify_string(struct Token* p) { char* table = "0123456789ABCDEF"; int i = ((string_length(p->Text + 1)/4) + 1) * 8; char* d = calloc(max_string, sizeof(char)); p->Expression = d; while(0 < i) { i = i - 1; d[i] = 0x30; } while( i < max_string) { if(0 == p->Text[i+1]) { i = max_string; } else { d[2*i] = table[p->Text[i+1] / 16]; d[2*i + 1] = table[p->Text[i+1] % 16]; i = i + 1; } } } void process_string(struct Token* p) { struct Token* i; for(i = p; NULL != i; i = i->next) { if(i->type & STR) { if('\'' == i->Text[0]) { i->Expression = i->Text + 1; } else if('"' == i->Text[0]) { hexify_string(i); } } } } void preserve_other(struct Token* p) { struct Token* i; for(i = p; NULL != i; i = i->next) { if((NULL == i->Expression) && !(i->type & MACRO)) { char c = i->Text[0]; if(('!' == c) ||('@' == c) ||('$' == c) ||('%' == c) ||('&' == c) ||(':' == c)) { i->Expression = i->Text; } else { file_print("Received invalid other; ", stderr); file_print(i->Text, stderr); file_print("\n", stderr); exit(EXIT_FAILURE); } } } } void bound_values(int displacement, int number_of_bytes, int low, int high) { if((high < displacement) || (displacement < low)) { file_print("A displacement of ", stderr); file_print(numerate_number(displacement), stderr); file_print(" does not fit in ", stderr); file_print(numerate_number(number_of_bytes), stderr); file_print(" bytes\n", stderr); exit(EXIT_FAILURE); } } void range_check(int displacement, int number_of_bytes) { if(4 == number_of_bytes) return; else if(3 == number_of_bytes) { bound_values(displacement, number_of_bytes, -8388608, 16777216); return; } else if(2 == number_of_bytes) { bound_values(displacement, number_of_bytes, -32768, 65535); return; } else if(1 == number_of_bytes) { bound_values(displacement, number_of_bytes, -128, 255); return; } file_print("Received an invalid number of bytes in range_check\n", stderr); exit(EXIT_FAILURE); } void reverseBitOrder(char* c) { if(NULL == c) return; if(0 == c[1]) return; int hold = c[0]; if(16 == ByteMode) { c[0] = c[1]; c[1] = hold; reverseBitOrder(c+2); } else if(8 == ByteMode) { c[0] = c[2]; c[2] = hold; reverseBitOrder(c+3); } else if(2 == ByteMode) { c[0] = c[7]; c[7] = hold; hold = c[1]; c[1] = c[6]; c[6] = hold; hold = c[2]; c[2] = c[5]; c[5] = hold; hold = c[3]; c[3] = c[4]; c[4] = hold; reverseBitOrder(c+8); } } void LittleEndian(char* start) { char* end = start; char* c = start; while(0 != end[0]) end = end + 1; int hold; for(end = end - 1; start < end; start = start + 1) { hold = start[0]; start[0] = end[0]; end[0] = hold; end = end - 1; } if(BigBitEndian) reverseBitOrder(c); } int stringify(char* s, int digits, int divisor, int value, int shift) { int i = value; if(digits > 1) { i = stringify(s+1, (digits - 1), divisor, value, shift); } s[0] = hex2char(i & (divisor - 1)); return (i >> shift); } char* express_number(int value, char c) { char* ch = calloc(42, sizeof(char)); int size; int number_of_bytes; int shift; if('!' == c) { number_of_bytes = 1; value = value & 0xFF; } else if('@' == c) { number_of_bytes = 2; value = value & 0xFFFF; } else if('%' == c) { number_of_bytes = 4; value = value & 0xFFFFFFFF; } else { file_print("Given symbol ", stderr); fputc(c, stderr); file_print(" to express immediate value ", stderr); file_print(numerate_number(value), stderr); fputc('\n', stderr); exit(EXIT_FAILURE); } range_check(value, number_of_bytes); if(16 == ByteMode) { size = number_of_bytes * 2; shift = 4; } else if(8 == ByteMode) { size = number_of_bytes * 3; shift = 3; } else if(2 == ByteMode) { size = number_of_bytes * 8; shift = 1; } else { file_print("Got invalid ByteMode in express_number\n", stderr); exit(EXIT_FAILURE); } stringify(ch, size, ByteMode, value, shift); if(!BigEndian) LittleEndian(ch); else if(!BigBitEndian) reverseBitOrder(ch); return ch; } void eval_immediates(struct Token* p) { struct Token* i; for(i = p; NULL != i; i = i->next) { if((NULL == i->Expression) && !(i->type & MACRO)) { int value; if((1 == Architecture) || (2 == Architecture) || (40 == Architecture)) { value = numerate_string(i->Text + 1); if(('0' == i->Text[1]) || (0 != value)) { i->Expression = express_number(value, i->Text[0]); } } else if(0 == Architecture) { value = numerate_string(i->Text); if(('0' == i->Text[0]) || (0 != value)) { i->Expression = express_number(value, '@'); } } else { file_print("Unknown architecture received in eval_immediates\n", stderr); exit(EXIT_FAILURE); } } } } void print_hex(struct Token* p) { struct Token* i; for(i = p; NULL != i; i = i->next) { if(i->type ^ MACRO) { fputc('\n', destination_file); file_print(i->Expression, destination_file); } } fputc('\n', destination_file); } /* Standard C main program */ int main(int argc, char **argv) { BigEndian = TRUE; struct Token* head = NULL; Architecture = 0; destination_file = stdout; BigBitEndian = TRUE; ByteMode = 16; int option_index = 1; while(option_index <= argc) { if(NULL == argv[option_index]) { option_index = option_index + 1; } else if(match(argv[option_index], "--BigEndian")) { BigEndian = TRUE; option_index = option_index + 1; } else if(match(argv[option_index], "--LittleEndian")) { BigEndian = FALSE; option_index = option_index + 1; } else if(match(argv[option_index], "-A") || match(argv[option_index], "--Architecture")) { Architecture = numerate_string(argv[option_index + 1]); option_index = option_index + 2; } else if(match(argv[option_index], "-b") || match(argv[option_index], "--binary")) { ByteMode = 2; option_index = option_index + 1; } else if(match(argv[option_index], "-h") || match(argv[option_index], "--help")) { file_print("Usage: ", stderr); file_print(argv[0], stderr); file_print(" -f FILENAME1 {-f FILENAME2} (--BigEndian|--LittleEndian) ", stderr); file_print("[--Architecture 12345]\nArchitecture 0: Knight; 1: x86; 2: AMD64; 40: armv7", stderr); exit(EXIT_SUCCESS); } else if(match(argv[option_index], "-f") || match(argv[option_index], "--file")) { source_file = fopen(argv[option_index + 1], "r"); if(NULL == source_file) { file_print("The file: ", stderr); file_print(argv[option_index + 1], stderr); file_print(" can not be opened!\n", stderr); exit(EXIT_FAILURE); } head = Tokenize_Line(head); option_index = option_index + 2; } else if(match(argv[option_index], "-o") || match(argv[option_index], "--output")) { destination_file = fopen(argv[option_index + 1], "w"); if(NULL == destination_file) { file_print("The file: ", stderr); file_print(argv[option_index + 1], stderr); file_print(" can not be opened!\n", stderr); exit(EXIT_FAILURE); } option_index = option_index + 2; } else if(match(argv[option_index], "-O") || match(argv[option_index], "--octal")) { ByteMode = 8; option_index = option_index + 1; } else if(match(argv[option_index], "-V") || match(argv[option_index], "--version")) { file_print("M1 0.3\n", stdout); exit(EXIT_SUCCESS); } else { file_print("Unknown option\n", stderr); exit(EXIT_FAILURE); } } if(NULL == head) { file_print("Either no input files were given or they were empty\n", stderr); exit(EXIT_FAILURE); } head = reverse_list(head); identify_macros(head); line_macro(head); process_string(head); eval_immediates(head); preserve_other(head); print_hex(head); return EXIT_SUCCESS; }