pc.c (3508B)
1 #include <stdlib.h> 2 #include <stdio.h> 3 4 #include "pc.h" 5 6 #include "is.h" 7 #include "fh.h" 8 #include "bc.h" 9 #include "helper.h" 10 11 /* Initalizes program counter, returns pc_t* instance 12 * char* - filename of file containing bytecode 13 */ 14 pc_t* pc_new(char* fname) 15 { 16 N_ASSERT(fname, "pc_new\n"); 17 18 pc_t* pc = (pc_t*)malloc(sizeof(pc_t)); 19 M_ASSERT(pc); 20 // Make a new address stack and set its inital address to 0 21 pc->stk = pc_addr_stk_new(0); 22 // Make sure the inital address is 0 23 pc_branch(pc, 0); 24 // Read the program specified 25 pc->bc = bc_init(fname); 26 // Update the program counter. 27 pc_update(pc); 28 29 N_ASSERT(pc->line, "Error in creating new program counter\n"); 30 31 return pc; 32 } 33 34 /* Creates a new address stack. 35 * ns_addr - inital address 36 */ 37 pc_addr_stk* pc_addr_stk_new(ns_addr address) 38 { 39 pc_addr_stk* new = (pc_addr_stk*)malloc(sizeof(pc_addr_stk)); 40 M_ASSERT(new); 41 42 new->addresses = (pc_addr*)malloc(sizeof(pc_addr)*PC_RETURN_DEPTH); 43 M_ASSERT(new->addresses); 44 45 new->ptr = 0; 46 new->size = PC_RETURN_DEPTH; 47 new->addresses[new->ptr] = address; 48 49 return new; 50 } 51 52 /* Frees memory assosiated with pc_t* instance 53 */ 54 void pc_del(pc_t* pc) 55 { 56 N_ASSERT(pc, "pc_del\n"); 57 N_ASSERT(pc->stk, "pc_del\n"); 58 N_ASSERT(pc->bc, "pc_del\n"); 59 60 // Free the address stack 61 pc_addr_stk_del(pc->stk); 62 // Free the program 63 bc_del(pc->bc); 64 65 free(pc); 66 } 67 68 /* Frees memory assosiated with pc_addr_stk* instance 69 */ 70 void pc_addr_stk_del(pc_addr_stk* stk) 71 { 72 N_ASSERT(stk, "pc_addr_stk_del\n"); 73 N_ASSERT(stk->addresses, "pc_addr_stk_del\n"); 74 75 free(stk->addresses); 76 free(stk); 77 } 78 79 /* Updates current insturction 80 * 81 * When called, pc_t->line will reflect pc_t->bc[pc_t->address] 82 */ 83 void pc_update(pc_t* pc) 84 { 85 N_ASSERT(pc, "pc_update\n"); 86 ASSERT((pc->address < (pc->bc->size + 1)), "Address out of range\n"); 87 // Update the pointer 88 pc->line = &pc->bc->heap[pc->address]; 89 } 90 91 /* Increment program counter by +-addr 92 * pc_t* - Program counter instance 93 * pc_addr - Address to increment by 94 */ 95 void pc_inc(pc_t* pc, pc_addr addr) 96 { 97 N_ASSERT(pc, "pc_inc\n"); 98 // Increment pc->address by addr 99 pc->address = pc->address + addr; 100 } 101 102 /* Branch to specified address. 103 * pc_t* - Program counter instance 104 * pc_addr - Address to branch to 105 */ 106 void pc_branch(pc_t* pc, pc_addr address) 107 { 108 N_ASSERT(pc, "pc_branch\n"); 109 // Is there space in the address stack? 110 ASSERT(((pc->stk->ptr + 1) < pc->stk->size), "Address Stack Overflow\n"); 111 112 // Push the current address on to the stack 113 pc->stk->addresses[pc->stk->ptr] = pc->address; 114 115 // Increment the stack pointer 116 pc->stk->ptr = pc->stk->ptr + 1; 117 118 // Set the current address to the branching address 119 pc->address = address; 120 } 121 122 /* Return from previous branch. 123 * pc_t* - Program counter instance 124 */ 125 void pc_return(pc_t* pc) 126 { 127 N_ASSERT(pc, "pc_return\n"); 128 // Is the stack pointer in range? 129 ASSERT(((pc->stk->ptr - 1) > 0), "Address Stack Underflow\n"); 130 131 // Decrement the stack pointer 132 pc->stk->ptr = pc->stk->ptr - 1; 133 134 // Pop the stack to pc->address 135 pc->address = pc->stk->addresses[pc->stk->ptr]; 136 } 137 138 /* Simply goto that address 139 * pc_t - Program counter instance 140 * pc_addr - Address to branch to 141 */ 142 void pc_goto(pc_t* pc, pc_addr addr) 143 { 144 N_ASSERT(pc, "pc_goto\n"); 145 // Do I really need to comment? 146 pc->address = addr; 147 } 148 149 /* For now, a simple function that tests if the address is in range 150 */ 151 int pc_safe(pc_t* pc) 152 { 153 // If the address is in range return true, if out of range return false 154 int rv = (pc->address >= pc->bc->size) ? 0 : 1; 155 return rv; 156 } 157