|
@@ -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;
|
|
|
+}
|