Browse Source

libprcacl: initial development

Douglas A 4 years ago
parent
commit
596e68ccc4
5 changed files with 342 additions and 0 deletions
  1. 14 0
      libprcalc/Makefile
  2. 72 0
      libprcalc/check.c
  3. 27 0
      libprcalc/prc_bits.h
  4. 171 0
      libprcalc/prcalc.c
  5. 58 0
      libprcalc/prcalc.h

+ 14 - 0
libprcalc/Makefile

@@ -0,0 +1,14 @@
+OBJ=bin/obj
+OBJS=$(OBJ)/prc_calc.o
+
+all: $(OBJS)
+
+$(OBJ)/prc_calc.o: pre prcalc.c
+	$(CC) $(CFLAGS) -c prcalc.c -o $(OBJ)/prc_calc.o
+
+check:
+	$(CC) $(CFLAGS) $(OBJS) check.c -o bin/check -lm
+	./bin/check
+
+pre:
+	mkdir -p bin/obj

+ 72 - 0
libprcalc/check.c

@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include "prcalc.h"
+#include <inttypes.h>
+
+
+int main (int argc, char** argv) {
+
+    prc_context ctx; 
+    uint64_t op1=0, op2=0;
+
+    prc_init_context(&ctx);
+   
+
+    op1 = 10;
+    op2 = 10;
+    prc_push(&ctx, op1);
+    prc_push(&ctx, op2);
+    prc_add_stack(&ctx);
+    printf("ADD(%20." PRIi64 ", %20." PRIi64 ")\tuint64_t: %20." PRIu64 "\tint64_t: %20." PRIi64 "\tHex: %16.lx\tFlags: %d\n", op1, op2,  ctx.registers.A, ctx.registers.A, ctx.registers.A, ctx.registers.FLAGS);
+
+    op1 = -1;
+    op2 = 10;
+    prc_push(&ctx, op1);
+    prc_push(&ctx, op2);
+    prc_add_stack(&ctx);
+    printf("ADD(%20." PRIi64 ", %20." PRIi64 ")\tuint64_t: %20." PRIu64 "\tint64_t: %20." PRIi64 "\tHex: %16.lx\tFlags: %d\n", op1, op2,  ctx.registers.A, ctx.registers.A, ctx.registers.A, ctx.registers.FLAGS);
+
+    op1 = -1;
+    op2 = -10;
+    prc_push(&ctx, op1);
+    prc_push(&ctx, op2);
+    prc_add_stack(&ctx);
+    printf("ADD(%20." PRIi64 ", %20." PRIi64 ")\tuint64_t: %20." PRIu64 "\tint64_t: %20." PRIi64 "\tHex: %16.lx\tFlags: %d\n", op1, op2,  ctx.registers.A, ctx.registers.A, ctx.registers.A, ctx.registers.FLAGS);
+
+
+    op1 = 0b0111111111111111111111111111111111111111111111111111111111111111;
+    op2 = 1;
+    prc_push(&ctx, op1);
+    prc_push(&ctx, op2);
+    prc_add_stack(&ctx);
+    printf("ADD(%20." PRIi64 ", %20." PRIi64 ")\tuint64_t: %20." PRIu64 "\tint64_t: %20." PRIi64 "\tHex: %16.lx\tFlags: %d\n", op1, op2,  ctx.registers.A, ctx.registers.A, ctx.registers.A, ctx.registers.FLAGS);
+
+    op1 = 2;
+    op2 = 0b1111111111111111111111111111111111111111111111111111111111111111; 
+    prc_push(&ctx, op1);
+    prc_push(&ctx, op2);
+    prc_add_stack(&ctx);
+    printf("ADD(%20." PRIu64 ", %20." PRIu64 ")\tuint64_t: %20." PRIu64 "\tint64_t: %20." PRIi64 "\tHex: %16.lx\tFlags: %d\n", op1, op2,  ctx.registers.A, ctx.registers.A, ctx.registers.A, ctx.registers.FLAGS);
+
+
+
+    op1 = 4;
+    op2 = 25;
+    prc_push(&ctx, op1);
+    prc_push(&ctx, op2);
+    prc_mul_stack(&ctx);
+    printf("ADD(%20." PRIi64 ", %20." PRIi64 ")\tuint64_t: %20." PRIu64 "\tint64_t: %20." PRIi64 "\tHex: %16.lx\tFlags: %d\n", op1, op2,  ctx.registers.A, ctx.registers.A, ctx.registers.A, ctx.registers.FLAGS);
+
+
+    
+    
+    //prc_mul_stack(&ctx);
+
+    //printf("RESULT: %ld \nFLAGS: %d\n", ctx.registers.A, ctx.registers.FLAGS);
+
+    
+
+    
+    
+
+}
+

+ 27 - 0
libprcalc/prc_bits.h

@@ -0,0 +1,27 @@
+#include "prcalc.h"
+
+_PRC_BOOL __test_negative(uint64_t val) {
+    return (( val & 0b1000000000000000000000000000000000000000000000000000000000000000 ) == 0b1000000000000000000000000000000000000000000000000000000000000000) ;
+}
+
+_PRC_BOOL __test_overflow(uint64_t val1, uint64_t val2, uint64_t res, __PRC_OPERATION op) {
+    if (op == ADD) {
+        if ( __test_negative(val1) && __test_negative(val2) )
+            return !__test_negative( res );
+        else if ( (!__test_negative(val1)) && (!__test_negative(val2)) ) {
+            return  __test_negative( res ) ;
+        }
+    
+    }
+    else if (op == MUL) {
+        if ( __test_negative(val1) && __test_negative(val2) )
+            return !( __test_negative( res ) );
+        else if ( (!__test_negative(val1)) && (!__test_negative(val2)) )
+            return !( __test_negative( res ) );
+        
+    }
+    return FALSE;
+}
+
+
+

+ 171 - 0
libprcalc/prcalc.c

@@ -0,0 +1,171 @@
+#include "prcalc.h"
+#include "prc_bits.h"
+
+PRC_ERROR prc_init_context(prc_context *ctx) {
+    
+    ctx->registers.A = (uint64_t) 0;
+    ctx->registers.B = (uint64_t) 0;
+    ctx->registers.SP = (uint64_t) 0;
+    ctx->registers.FLAGS = (uint64_t) 0;
+    return OK;
+}
+
+PRC_ERROR prc_push(prc_context *ctx, uint64_t val) {
+    if ( (ctx->registers.SP + 1) > STACK_SIZE ) {
+        return STACK_OVERFLOW;
+    }
+    
+    
+    ctx->stack[ctx->registers.SP] = val;
+    ctx->registers.SP +=1 ;
+    return OK;
+}
+
+PRC_ERROR prc_pop(prc_context *ctx, uint64_t *val) {
+    if ( ctx->registers.SP < 0 ) {
+        return STACK_EMPTY;
+    }
+    
+    ctx->registers.SP -= 1;
+    *val = ctx->stack[ctx->registers.SP];
+    return OK;
+}
+
+PRC_ERROR prc_set_a(prc_context *ctx, uint64_t val) {
+    ctx->registers.A = val;
+    return OK;
+}
+
+PRC_ERROR prc_set_b(prc_context *ctx, uint64_t val) {
+    ctx->registers.B = val;
+    return OK;
+}
+
+PRC_ERROR prc_swap(prc_context *ctx) {
+    uint64_t *aux = malloc(sizeof( uint64_t));
+    *aux = ctx->registers.A;
+    if ( prc_push(ctx, ctx->registers.B) != OK ) {
+        return STACK_OVERFLOW;
+    }
+
+    prc_set_b(ctx, *aux);
+    if ( prc_pop(ctx, aux) != OK ) {
+        return STATE_UNDEFINED;
+    }
+    prc_set_a(ctx, *aux);
+
+    free(aux);
+    return OK;
+}
+
+/* Add two values in the stack and save to register A */
+PRC_ERROR prc_add_stack (prc_context *ctx) {
+    uint64_t *aux1 = malloc(sizeof( uint64_t));
+    uint64_t *aux2 = malloc(sizeof( uint64_t));
+    
+
+
+    if ( prc_pop(ctx, aux1) != OK ) 
+        return STACK_EMPTY;
+    
+    if ( prc_pop(ctx, aux2) != OK ) 
+        return STACK_EMPTY;
+
+
+    ctx->registers.FLAGS &= 0b11111001;
+    // 00100110
+    // 11111001
+    // 00000000
+
+    ctx->registers.A = *aux1 + *aux2;
+
+  if ( __test_overflow(*aux1, *aux2, ctx->registers.A, ADD) )
+        ctx->registers.FLAGS |= OVERFLOW; 
+
+  //ctx->registers.FLAGS = (__test_negative(ctx->registers.A) &  ~NEGATIVE) ;
+
+    if (__test_negative(ctx->registers.A)) {
+        ctx->registers.FLAGS |= NEGATIVE;
+    }
+  
+    free(aux1);
+    free(aux2);
+    return OK;
+}
+
+/* Multiply two values in the stack and save to register A */
+PRC_ERROR prc_mul_stack (prc_context *ctx) {
+    uint64_t *aux1 = malloc(sizeof( uint64_t));
+    uint64_t *aux2 = malloc(sizeof( uint64_t));
+
+    ctx->registers.FLAGS &= 0b11111001;
+
+    if ( prc_pop(ctx, aux1) != OK ) 
+        return STACK_EMPTY;
+     
+    if ( prc_pop(ctx, aux2) != OK ) 
+        return STACK_EMPTY;
+    
+    ctx->registers.A = *aux1 * *aux2;
+
+    /*if ( __test_overflow(*aux1, *aux2, ctx->registers.A, MUL) ) 
+        ctx->registers.FLAGS |= OVERFLOW;
+ */
+    if ( __test_negative(ctx->registers.A) )
+        ctx->registers.FLAGS |= NEGATIVE; 
+    
+    free(aux1);
+    free(aux2);
+    return OK;
+}
+
+/* Subtract two values in the stack and save to register A */
+PRC_ERROR SUB_STACK (prc_context *ctx) {
+    uint64_t *aux1 = malloc(sizeof( uint64_t));
+    uint64_t *aux2 = malloc(sizeof( uint64_t));
+
+    if ( prc_pop(ctx, aux1) != OK ) 
+        return STACK_EMPTY;
+    
+    if ( prc_pop(ctx, aux2) != OK ) 
+        return STACK_EMPTY;
+    ctx->registers.A = *aux1 - *aux2;
+
+    if ( __test_negative(ctx->registers.A) )
+        ctx->registers.FLAGS |= NEGATIVE;
+    
+    free(aux1);
+    free(aux2);
+    return OK;
+}
+
+/* Divide two values in the stack and save to register A */
+PRC_ERROR DIV_STACK (prc_context *ctx) {
+    uint64_t *aux = malloc(sizeof( uint64_t));
+    if ( prc_pop(ctx, aux) != OK ) 
+        return STACK_EMPTY;
+    ctx->registers.A = *aux;
+    if ( prc_pop(ctx, aux) != OK ) 
+        return STACK_EMPTY;
+    ctx->registers.A /= *aux;
+    
+    free(aux);
+    return OK;
+}
+
+/* Divide two values in the stack and save to register A */
+PRC_ERROR POW_STACK (prc_context *ctx) {
+    uint64_t *aux = malloc( sizeof( uint64_t ) );
+    uint64_t *power = malloc( sizeof( uint64_t ) );
+    if ( prc_pop(ctx, power) != OK ) 
+        return STACK_EMPTY;
+    ctx->registers.A = *aux;
+    
+    if ( prc_pop(ctx, aux) != OK ) 
+        return STACK_EMPTY;
+    ctx->registers.A = pow(*aux, *power);
+    
+    free(aux);
+    free(power);
+    return OK;
+}

+ 58 - 0
libprcalc/prcalc.h

@@ -0,0 +1,58 @@
+#ifndef _PRCALC_H
+#define _PRCALC_H
+#include <stdint.h>
+#include <math.h>
+#include <stdlib.h>
+
+#define STACK_SIZE 1024
+
+#define CARRY 1
+#define NEGATIVE 2
+#define OVERFLOW 4
+
+typedef enum BOOL {FALSE, TRUE} _PRC_BOOL;
+
+/*
+ * A -> general purpose register
+ * B -> general purpose register
+ * SP -> stack pointer. index where the stack is positioned
+ * FLAGS -> 8 bit operation result flags (LSB)
+ *  1 -> Carry bit
+ *  2 -> Negative
+ *  4 -> Overflow
+ *  8 -> 
+ *  16 -> 
+ *  32 -> 
+ *  64 -> 
+ *  128 -> 
+*/
+typedef struct prc_registers {
+    uint64_t A;
+    uint64_t B;
+    uint16_t SP;
+    uint8_t FLAGS; 
+} __prc_registers;
+
+typedef uint64_t __prc_stack[STACK_SIZE];
+
+typedef struct prc_context {
+    __prc_registers registers;
+    __prc_stack stack;
+} prc_context;
+
+typedef enum PRC_ERROR {OK, STACK_OVERFLOW, STACK_EMPTY, STATE_UNDEFINED} PRC_ERROR;
+
+typedef enum PRC_OPERATION {ADD, SUB, MUL, DIV} __PRC_OPERATION;
+
+PRC_ERROR prc_init_context(prc_context *ctx);
+PRC_ERROR prc_push(prc_context *ctx, uint64_t val);
+PRC_ERROR prc_pop(prc_context *ctx, uint64_t *val);
+PRC_ERROR prc_set_a(prc_context *ctx, uint64_t val);
+PRC_ERROR prc_set_b(prc_context *ctx, uint64_t val);
+PRC_ERROR prc_swap(prc_context *ctx);
+PRC_ERROR prc_add_stack (prc_context *ctx);
+PRC_ERROR prc_mul_stack (prc_context *ctx);
+
+
+
+#endif //_PRCALC_H