chiark / gitweb /
wagglers in hostside
[trains.git] / hostside / skelproto-pic.c
1 /* @skeleton@ @1@ @L@ */
2 /*
3  * definitions of
4  *  enco_pic_WHATEVER
5  *  on_pic_WHATEVER
6  * and the tables
7  * and related functions
8  */
9
10 #include <assert.h>
11
12 #include "common.h"
13 #include "auproto-pic.h"
14
15 static void enco_pic_any(PicInsn *out, int opcode, int argsbits, int argsval) {
16   unsigned long as= argsval;
17   int i;
18
19   assert(!(as & (~0UL << argsbits)));
20   out->l= 1 + argsbits/7;
21   for (i= out->l - 1;
22        i >= 0;
23        i--, as >>= 7)
24     out->d[i]= (as & 0x07fUL) | 0x080UL;
25   out->d[out->l - 1] &= ~0x080UL;
26   out->d[0] |= opcode;
27 }
28
29 static void enco_pic_anyobjv(PicInsn *out, int opcode, int argsbits, int vbits,
30                             int obj, int v) {
31   assert((unsigned)v < (1u << vbits));
32   enco_pic_any(out, opcode, argsbits, obj << vbits | v);
33 }
34
35 #define C ,
36
37 #define ENCO(w, xa, opcode, argsbits, obj)      \
38   extern void enco_pic_##w(PicInsn *out  xa) {  \
39     enco_pic_any(out, opcode, argsbits, obj);   \
40   }
41
42 #define ENCO2A(w, opcode, vbits, argsbits)                      \
43   extern void enco_pic_##w(PicInsn *out, int obj, int v) {      \
44     enco_pic_anyobjv(out, opcode, argsbits, vbits, obj, v);     \
45   }
46
47 ENCO(@cnameyn@,          , @opcodeyn@, 0,                0)   @h2p@ @nargs=0@
48 ENCO(@cnameyn@, C int obj, @opcodeyn@, @arglen@,         obj) @h2p@ @nargs=1@
49 ENCO2A(@cnameyn@,          @opcodeyn@, @arglen@, @vlen@)      @h2p@ @nargs=2@
50
51 extern void enco_pic_pii(PicInsn *out, const PicInsnInfo *pii,
52                          int obj, int v) {
53   enco_pic_anyobjv(out, pii->opcode, pii->argsbits, pii->vbits, obj, v);
54 }
55
56 const PicInsnInfo *lookup_byopcode(Byte byte0, const PicInsnInfo *table) {
57   const PicInsnInfo *pi;
58   for (pi= table;
59        pi->name;
60        pi++)
61     if ((byte0 & pi->mask) == pi->opcode)
62       return pi;
63   return 0;
64 }
65
66 void picinsn_decode(const PicInsn *pi, const PicInsnInfo *table,
67                     const PicInsnInfo **pii_r, int *objnum_r, int *v_r) {
68   const PicInsnInfo *pii;
69   unsigned val= 0;
70
71   pii= pi->l > 0 ? lookup_byopcode(pi->d[0], table) : 0;
72
73   if (pii) {
74     val= pi->d[0];
75     if (pii->argsbits <= 6) {
76       if (pi->l != 1) pii= 0;
77     } else {
78       if (pi->l == 2 && !(pi->d[1] & 0x80u)) { val <<= 7; val |= pi->d[1]; }
79       else pii= 0;
80     }
81   }
82
83   if (pii) {
84     if (objnum_r) *objnum_r= (val & ((1u << pii->argsbits) - 1)) >> pii->vbits;
85     if (v_r)      *v_r=       val & ((1u << pii->vbits) - 1);
86   }
87   *pii_r= pii;
88 }
89
90 const PicInsnInfo pic_command_infos[]= {
91   { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @argslen@, @vlen@, @noiselevel@, 0 }, @h2p@
92   { 0 }
93 };
94
95 const PicInsnInfo pic_reply_infos[]= {
96   { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @argslen@, @vlen@, @noiselevel@, on_pic_@cnameyn@ },@p2h@
97   { 0 }
98 };