~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to terps/nitfol/decode.c

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  Nitfol - z-machine interpreter using Glk for output.
 
2
    Copyright (C) 1999  Evin Robertson
 
3
 
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 
17
 
 
18
    The author can be reached at nitfol@deja.com
 
19
*/
 
20
#include "nitfol.h"
 
21
 
 
22
void decode(void)
 
23
{
 
24
  unsigned optypes;
 
25
  int maxoperands;
 
26
 
 
27
  while(!exit_decoder) {
 
28
    zbyte opcode = HIBYTE(PC);
 
29
 
 
30
    oldPC = PC;
 
31
 
 
32
#ifdef DEBUGGING
 
33
    if(do_check_watches)
 
34
      check_watches();
 
35
#endif
 
36
 
 
37
    PC++;
 
38
 
 
39
#ifndef NO_TICK
 
40
    glk_tick();  /* tick tock hickery dock the mouse ran up the clock */
 
41
#endif
 
42
    
 
43
    /* Top bits decide opcode/operand encoding */
 
44
    switch(opcode >> 4) {
 
45
    case 0: case 1:                         /* long 2OP */
 
46
      operand[0] = HIBYTE(PC);              /* small constant */
 
47
      operand[1] = HIBYTE(PC+1);            /* small constant */
 
48
      numoperands = 2; PC += 2;
 
49
      opcode += OFFSET_2OP - 0x00;
 
50
      break;
 
51
 
 
52
 
 
53
    case 2: case 3:                         /* long 2OP */
 
54
      operand[0] = HIBYTE(PC);              /* small constant */
 
55
      operand[1] = get_var(HIBYTE(PC+1));   /* variable */
 
56
      numoperands = 2; PC += 2;
 
57
      opcode += OFFSET_2OP - 0x20;
 
58
      break;
 
59
 
 
60
 
 
61
    case 4: case 5:                         /* long 2OP */
 
62
      operand[0] = get_var(HIBYTE(PC));     /* variable */
 
63
      operand[1] = HIBYTE(PC+1);            /* small constant */
 
64
      numoperands = 2; PC += 2;
 
65
      opcode += OFFSET_2OP - 0x40;
 
66
      break;
 
67
 
 
68
 
 
69
    case 6: case 7:                         /* long 2OP */
 
70
      operand[0] = get_var(HIBYTE(PC));     /* variable */
 
71
      operand[1] = get_var(HIBYTE(PC+1));   /* variable */
 
72
      numoperands = 2; PC += 2;
 
73
      opcode += OFFSET_2OP - 0x60;
 
74
      break;
 
75
 
 
76
 
 
77
    case 8:                                 /* short 1OP */
 
78
      operand[0] = HIWORD(PC);              /* large constant */
 
79
      numoperands = 1; PC += ZWORD_SIZE;
 
80
      opcode += OFFSET_1OP - 0x80;
 
81
      break;
 
82
 
 
83
 
 
84
    case 9:                                 /* short 1OP */
 
85
      operand[0] = HIBYTE(PC);              /* small constant */
 
86
      numoperands = 1; PC += 1;
 
87
      opcode += OFFSET_1OP - 0x90;
 
88
      break;
 
89
 
 
90
 
 
91
    case 10:                                /* short 1OP */
 
92
      operand[0] = get_var(HIBYTE(PC));     /* variable */
 
93
      numoperands = 1; PC += 1;
 
94
      opcode += OFFSET_1OP - 0xa0;
 
95
      break;
 
96
 
 
97
 
 
98
    case 11:                                /* short 0OP */
 
99
      if(opcode != 0xbe) {
 
100
        numoperands = 0;
 
101
        opcode += OFFSET_0OP - 0xb0;
 
102
        break;
 
103
      }
 
104
                                            /* EXTENDED */
 
105
      opcode  = HIBYTE(PC);   /* Get the extended opcode */
 
106
      optypes = HIBYTE(PC+1);
 
107
      PC += 2;
 
108
 
 
109
#ifndef FAST
 
110
      if(OFFSET_EXT + opcode > OFFSET_END) {
 
111
        n_show_error(E_INSTR, "unknown extended opcode", opcode);
 
112
        break;
 
113
      }
 
114
#endif
 
115
      
 
116
      for(numoperands = 0; numoperands < 4; numoperands++) {
 
117
        switch(optypes & (3 << 6)) {   /* Look at the highest two bits. */
 
118
        case 0 << 6:
 
119
          operand[numoperands] = HIWORD(PC); PC+=ZWORD_SIZE; break;
 
120
        case 1 << 6:
 
121
          operand[numoperands] = HIBYTE(PC); PC++; break;
 
122
        case 2 << 6:
 
123
          operand[numoperands] = get_var(HIBYTE(PC)); PC++; break;
 
124
        default:
 
125
          goto END_OF_EXTENDED;   /* inky says, "use the goto." */
 
126
        }
 
127
        optypes <<= 2;    /* Move the next two bits into position. */
 
128
      }
 
129
    END_OF_EXTENDED:
 
130
      opcode += OFFSET_EXT;
 
131
      break;
 
132
 
 
133
    case 12: case 13: case 14: case 15:     /* variable operand count */
 
134
      maxoperands = 4;
 
135
      optypes = ((unsigned) HIBYTE(PC)) << 8; /* Shift left so our loop will */
 
136
                                    /* be the same for both 4 and 8 operands */
 
137
      PC++;
 
138
  
 
139
      if(opcode == 0xec || opcode == 0xfa) {  /* call_vs2 and call_vn2 */
 
140
        maxoperands = 8;
 
141
        optypes |= HIBYTE(PC);  /* Fill the bottom 8 bits */
 
142
        PC++;
 
143
      }
 
144
      
 
145
      for(numoperands = 0; numoperands < maxoperands; numoperands++) {
 
146
        switch(optypes & (3 << 14)) {   /* Look at the highest two bits. */
 
147
        case 0 << 14:
 
148
          operand[numoperands] = HIWORD(PC); PC+=ZWORD_SIZE; break;
 
149
        case 1 << 14:
 
150
          operand[numoperands] = HIBYTE(PC); PC++; break;
 
151
        case 2 << 14:
 
152
          operand[numoperands] = get_var(HIBYTE(PC)); PC++; break;
 
153
        default:
 
154
          goto END_OF_VARIABLE;
 
155
        }
 
156
        optypes <<= 2;    /* Move the next two bits into position. */
 
157
      }
 
158
    END_OF_VARIABLE:
 
159
      opcode += OFFSET_2OP - 0xc0;
 
160
      break;
 
161
    }
 
162
    opcodetable[opcode]();
 
163
  }
 
164
}