From 453dad3f09f8961c7281dbe7b7183f861884445e Mon Sep 17 00:00:00 2001
From: litvin <litvindev@gmail.com>
Date: Mon, 12 Jan 2015 10:18:17 +0300
Subject: [PATCH] Add missed instructions: SLB,SRB,JAE,JAO,JXE,JXO (from volume 2, section 4.5.2)

---
 misc/mixal-mode.el              | 42 ++++++++++++++++++++++++++++++++++++++++-
 mixlib/mix_ins.c                |  3 +++
 mixlib/mix_ins.h                |  4 +++-
 mixlib/mix_types.c              | 34 +++++++++++++++++++++++++++++++++
 mixlib/mix_types.h              | 11 +++++++++--
 mixlib/testsuite/mix_vm_ins_t.c | 17 +++++++++++++++++
 mixlib/xmix_vm.c                | 14 ++++++++++++++
 7 files changed, 121 insertions(+), 4 deletions(-)

diff --git a/misc/mixal-mode.el b/misc/mixal-mode.el
index deb5f92..a2eaafb 100644
--- a/misc/mixal-mode.el
+++ b/misc/mixal-mode.el
@@ -101,7 +101,7 @@ value.")
 
 (defvar mixal-operation-codes
   '("NOP" "ADD" "FADD" "SUB" "FSUB" "MUL" "FMUL" "DIV" "FDIV" "NUM" "CHAR"
-    "HLT" "SLA" "SRA" "SLAX" "SRAX" "SLC" "SRC" "MOVE" "LDA" "LD1" "LD2" "LD3"
+    "HLT" "SLA" "SRA" "SLAX" "SRAX" "SLC" "SRC" "SLB" "SRB" "MOVE" "LDA" "LD1" "LD2" "LD3"
     "LD4" "LD5" "LD6" "LDX" "LDAN" "LD1N" "LD2N" "LD3N" "LD4N" "LD5N" "LD6N"
     "LDXN" "STA" "ST1" "ST2" "ST3" "ST4" "ST5" "ST6" "STX" "STJ" "STZ" "JBUS"
     "IOC" "IN" "OUT" "JRAD" "JMP" "JSJ" "JOV" "JNOV"
@@ -112,6 +112,8 @@ value.")
     "JANN" "J1NN" "J2NN" "J3NN" "J4NN" "J5NN" "J6NN" "JXNN"
     "JANZ" "J1NZ" "J2NZ" "J3NZ" "J4NZ" "J5NZ" "J6NZ" "JXNZ"
     "JANP" "J1NP" "J2NP" "J3NP" "J4NP" "J5NP" "J6NP" "JXNP"
+    "JAE"                                            "JXE"
+    "JAO"                                            "JXO"
     "INCA" "DECA" "ENTA" "ENNA" "INC1" "DEC1" "ENT1" "ENN1"
     "INC2" "DEC2" "ENT2" "ENN2" "INC3" "DEC3" "ENT3" "ENN3" "INC4" "DEC4"
     "ENT4" "ENN4" "INC5" "DEC5" "ENT5" "ENN5" "INC6" "DEC6" "ENT6" "ENN6"
@@ -824,6 +826,20 @@ been executed when there was no jump."
  1)
 
 (mixal-add-operation-code
+ 'JAE 'jump "jump A even" 40 6
+ "Jump if the content of rA is even.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+ 1)
+
+(mixal-add-operation-code
+ 'JAO 'jump "jump A odd" 40 7
+ "Jump if the content of rA is odd.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+ 1)
+
+(mixal-add-operation-code
  'JXN 'jump "jump X negative" 47 0
  "Jump if the content of rX is negative.
 Register J is set to the value of the next instruction that would have
@@ -871,6 +887,20 @@ been executed when there was no jump."
  1)
 
 (mixal-add-operation-code
+ 'JXE 'jump "jump X even" 47 6
+ "Jump if the content of rX is even.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+ 1)
+
+(mixal-add-operation-code
+ 'JXO 'jump "jump X odd" 47 7
+ "Jump if the content of rX is odd.
+Register J is set to the value of the next instruction that would have
+been executed when there was no jump."
+ 1)
+
+(mixal-add-operation-code
  'J1N 'jump "jump I1 negative" (+ 40 1) 0
  "Jump if the content of rI1 is negative.
 Register J is set to the value of the next instruction that would have
@@ -1199,6 +1229,16 @@ The bytes that fall off to the right will be added to the left."
  2)
 
 (mixal-add-operation-code
+ 'SLB 'miscellaneous "shift left AX binary" 6 6
+ "Shift AX, M binary places left."
+ 2)
+
+(mixal-add-operation-code
+ 'SRB 'miscellaneous "shift right AX binary" 6 7
+ "Shift AX, M binary places right."
+ 2)
+
+(mixal-add-operation-code
  'MOVE 'miscellaneous "move" 7 'number
  "Move MOD words from M to the location stored in rI1."
  '(+ 1 (* 2 number)))
diff --git a/mixlib/mix_ins.c b/mixlib/mix_ins.c
index 42cdafc..5838690 100644
--- a/mixlib/mix_ins.c
+++ b/mixlib/mix_ins.c
@@ -39,6 +39,7 @@ static const struct mix_ins_desc_ id_to_desc_[] =  {
   IDESX_(5,0,NUM), IDESX_(5,1,CHAR), IDESX_(5,2,HLT),
   IDESX_(6,0,SLA), IDESX_(6,1,SRA), IDESX_(6,2,SLAX), IDESX_(6,3,SRAX),
   IDESX_(6,4,SLC), IDESX_(6,5,SRC),
+  IDESX_(6,6,SLB), IDESX_(6,7,SRB),
   IDES_(7,1,MOVE), IDES_(8,5,LDA), IDES_(9,5,LD1), IDES_(10,5,LD2),
   IDES_(11,5,LD3), IDES_(12,5,LD4), IDES_(13,5,LD5),
   IDES_(14,5,LD6), IDES_(15,5,LDX), IDES_(16,5,LDAN), IDES_(17,5,LD1N),
@@ -53,6 +54,7 @@ static const struct mix_ins_desc_ id_to_desc_[] =  {
   IDESX_(39,8,JNE), IDESX_(39,9,JLE),
   IDESX_(40,0,JAN), IDESX_(40,1,JAZ), IDESX_(40,2,JAP), IDESX_(40,3,JANN),
   IDESX_(40,4,JANZ), IDESX_(40,5,JANP),
+  IDESX_(40,6,JAE), IDESX_(40,7,JAO),
   IDESX_(41,0,J1N), IDESX_(41,1,J1Z), IDESX_(41,2,J1P), IDESX_(41,3,J1NN),
   IDESX_(41,4,J1NZ), IDESX_(41,5,J1NP),
   IDESX_(42,0,J2N), IDESX_(42,1,J2Z), IDESX_(42,2,J2P), IDESX_(42,3,J2NN),
@@ -67,6 +69,7 @@ static const struct mix_ins_desc_ id_to_desc_[] =  {
   IDESX_(46,4,J6NZ), IDESX_(46,5,J6NP),
   IDESX_(47,0,JXN), IDESX_(47,1,JXZ), IDESX_(47,2,JXP), IDESX_(47,3,JXNN),
   IDESX_(47,4,JXNZ), IDESX_(47,5,JXNP),
+  IDESX_(47,6,JXE), IDESX_(47,7,JXO),
   IDESX_(48,0,INCA), IDESX_(48,1,DECA), IDESX_(48,2,ENTA), IDESX_(48,3,ENNA),
   IDESX_(49,0,INC1), IDESX_(49,1,DEC1), IDESX_(49,2,ENT1), IDESX_(49,3,ENN1),
   IDESX_(50,0,INC2), IDESX_(50,1,DEC2), IDESX_(50,2,ENT2), IDESX_(50,3,ENN2),
diff --git a/mixlib/mix_ins.h b/mixlib/mix_ins.h
index 1ea3f81..a9267ad 100644
--- a/mixlib/mix_ins.h
+++ b/mixlib/mix_ins.h
@@ -47,7 +47,7 @@ typedef enum {
 typedef enum {
   mix_NOP,  mix_ADD, mix_SUB, mix_MUL, mix_DIV,
   mix_NUM, mix_CHAR, mix_HLT,
-  mix_SLA, mix_SRA, mix_SLAX, mix_SRAX, mix_SLC, mix_SRC,
+  mix_SLA, mix_SRA, mix_SLAX, mix_SRAX, mix_SLC, mix_SRC, mix_SLB, mix_SRB,
   mix_MOVE, mix_LDA, mix_LD1, mix_LD2, mix_LD3, mix_LD4, mix_LD5,
   mix_LD6,  mix_LDX, mix_LDAN, mix_LD1N, mix_LD2N, mix_LD3N, mix_LD4N,
   mix_LD5N, mix_LD6N, mix_LDXN, mix_STA, mix_ST1, mix_ST2, mix_ST3, mix_ST4,
@@ -56,6 +56,7 @@ typedef enum {
   mix_JMP, mix_JSJ, mix_JOV, mix_JNOV, mix_JL, mix_JE, mix_JG, mix_JGE,
   mix_JNE, mix_JLE,
   mix_JAN, mix_JAZ, mix_JAP, mix_JANN, mix_JANZ, mix_JANP,
+  mix_JAE, mix_JAO,
   mix_J1N, mix_J1Z, mix_J1P, mix_J1NN, mix_J1NZ, mix_J1NP,
   mix_J2N, mix_J2Z, mix_J2P, mix_J2NN, mix_J2NZ, mix_J2NP,
   mix_J3N, mix_J3Z, mix_J3P, mix_J3NN, mix_J3NZ, mix_J3NP,
@@ -63,6 +64,7 @@ typedef enum {
   mix_J5N, mix_J5Z, mix_J5P, mix_J5NN, mix_J5NZ, mix_J5NP,
   mix_J6N, mix_J6Z, mix_J6P, mix_J6NN, mix_J6NZ, mix_J6NP,
   mix_JXN, mix_JXZ, mix_JXP, mix_JXNN, mix_JXNZ, mix_JXNP,
+  mix_JXE, mix_JXO,
   mix_INCA, mix_DECA, mix_ENTA, mix_ENNA,
   mix_INC1, mix_DEC1, mix_ENT1, mix_ENN1,
   mix_INC2, mix_DEC2, mix_ENT2, mix_ENN2,
diff --git a/mixlib/mix_types.c b/mixlib/mix_types.c
index 46e87a2..4dac3ba 100644
--- a/mixlib/mix_types.c
+++ b/mixlib/mix_types.c
@@ -463,6 +463,40 @@ mix_word_shift_right_circular (mix_word_t A, mix_word_t X, gulong count,
       | ( mix_word_magnitude (A1) >> c ) | ( MIX_WORD_MAX & (X1 << (30 - c)) );
 }
 
+void
+mix_word_shift_left_binary (mix_word_t A, mix_word_t X, gulong count,
+                            mix_word_t *pA, mix_word_t *pX)
+{
+  if ( pX != NULL ) *pX = mix_word_sign (X);
+  if ( pA != NULL ) *pA = mix_word_sign (A);
+  if (count < 30) {
+    if ( pX != NULL ) *pX |= MIX_WORD_MAX & (X << count);
+    if ( pA != NULL )
+      *pA |= MIX_WORD_MAX & ( (A << count) |
+			      (mix_word_magnitude (X) >> (30 - count)) );
+  } else if (count < 60 && pA != NULL)
+    *pA |= MIX_WORD_MAX & (X << (count - 30));
+  else
+    ;
+}
+
+void
+mix_word_shift_right_binary (mix_word_t A, mix_word_t X, gulong count,
+                             mix_word_t *pA, mix_word_t *pX)
+{
+  if ( pX != NULL ) *pX = mix_word_sign (X);
+  if ( pA != NULL ) *pA = mix_word_sign (A);
+  if (count < 30) {
+    if ( pA != NULL )
+      *pA |= mix_word_magnitude (A) >> count;
+    if ( pX != NULL )
+      *pX |= MIX_WORD_MAX & ( (mix_word_magnitude (X) >> count)
+			      | (A << (30 - count)) );
+  } else if (count < 60 && pX != NULL)
+    *pX |= mix_word_magnitude (A) >> (count - 30);
+  else
+    ;
+}
 
 /* Printable representation */
 void
diff --git a/mixlib/mix_types.h b/mixlib/mix_types.h
index 9473b00..8bea145 100644
--- a/mixlib/mix_types.h
+++ b/mixlib/mix_types.h
@@ -136,6 +136,8 @@ mix_word_set_byte(mix_word_t *into,   /* word to be modified */
 #define mix_word_magnitude(word)     ( (word) & (MIX_WORD_SIGN_BIT - 1) )
 #define mix_word_is_positive(word)   ( mix_word_sign(word) == 0 )
 #define mix_word_is_negative(word)   ( mix_word_sign(word) != 0 )
+#define mix_word_is_even(word)       ( ((word) & 1) == 0 )
+#define mix_word_is_odd(word)        ( ((word) & 1) == 1 )
 
 
 /* Arithmetic operations */
@@ -175,10 +177,15 @@ mix_word_shift_left_circular(mix_word_t A, mix_word_t X, gulong count,
 			     mix_word_t *pA, mix_word_t *pX);
 extern void
 mix_word_shift_right_circular(mix_word_t A, mix_word_t X, gulong count,
-			     mix_word_t *pA, mix_word_t *pX);
-
+                              mix_word_t *pA, mix_word_t *pX);
 
+extern void
+mix_word_shift_left_binary(mix_word_t A, mix_word_t X, gulong count,
+                           mix_word_t *pA, mix_word_t *pX);
 
+extern void
+mix_word_shift_right_binary(mix_word_t A, mix_word_t X, gulong count,
+                            mix_word_t *pA, mix_word_t *pX);
 
 /*
  * Fields within a word: a word containing the (L:R)
diff --git a/mixlib/testsuite/mix_vm_ins_t.c b/mixlib/testsuite/mix_vm_ins_t.c
index 458cbba..1d368a7 100644
--- a/mixlib/testsuite/mix_vm_ins_t.c
+++ b/mixlib/testsuite/mix_vm_ins_t.c
@@ -245,6 +245,23 @@ test_shift_(mix_vm_t *vm, mix_dump_context_t *dc)
   test.rA_a = mix_word_new_b(0,6,7,8,3);
   test.rX_a = mix_word_new_bn(4,0,0,5,0);
   run_test_(&test, vm, dc);
+
+  mix_ins_fill_from_id(ins, mix_SLB);
+  ins.index = 0;
+  ins.address = 3;
+  fill_test_desc_(&test, vm, &ins);
+  test.rA_b = mix_word_new(06543217654);
+  test.rX_b = mix_word_new(03217654321);
+  test.rA_a = mix_word_new(05432176543);
+  test.rX_a = mix_word_new(02176543210);
+  run_test_(&test, vm, dc);
+
+  mix_ins_fill_from_id(ins, mix_SRB);
+  ins.address = 6;
+  fill_test_desc_(&test, vm, &ins);
+  test.rA_a = mix_word_new(00054321765);
+  test.rX_a = mix_word_new(04321765432);
+  run_test_(&test, vm, dc);
 }
 
 static void
diff --git a/mixlib/xmix_vm.c b/mixlib/xmix_vm.c
index 0f1104a..cf20ee1 100644
--- a/mixlib/xmix_vm.c
+++ b/mixlib/xmix_vm.c
@@ -188,6 +188,14 @@ sla_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
     mix_word_shift_right_circular (get_rA_ (vm), get_rX_ (vm), n,
                                    &get_rA_ (vm), &get_rX_ (vm));
     break;
+  case mix_SLB:
+    mix_word_shift_left_binary (get_rA_ (vm), get_rX_ (vm), n,
+                                &get_rA_ (vm), &get_rX_ (vm));
+    break;
+  case mix_SRB:
+    mix_word_shift_right_binary (get_rA_ (vm), get_rX_ (vm), n,
+                                 &get_rA_ (vm), &get_rX_ (vm));
+    break;
   default:
     fail_unexpected_ (vm);
   }
@@ -481,6 +489,12 @@ jpx_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
     jump = mix_word_magnitude (val) == MIX_WORD_ZERO
       || mix_word_is_negative (val);
     break;
+  case mix_JAE: case mix_JXE:
+    jump = mix_word_is_even (val);
+    break;
+  case mix_JAO: case mix_JXO:
+    jump = mix_word_is_odd (val);
+    break;
   default:
     fail_unexpected_ (vm);
   }
-- 
2.0.5

