|
|
1.1 root 1: #include "../machine/alignment.h"
2: #define illegal(x) ((look_at->add_modes & x)==0)
3: #define legal(x) !illegal(x)
4:
5: struct oprnd *operand(infop, number)
6: register process_info *infop;
7: int number;
8: /*
9: * Enter with pc pointing to an operand descriptor
10: * in the 'text'. Decode the addressing mode, get
11: * the effective address and some data from there.
12: * Leave pc on the next oerand specifier or opcode.
13: * Returns a pointer to a 'decoded operand' structure,
14: * actually one of the 4 pre-allocated .
15: *
16: * This routine should be called in such a sequence
17: * that pc will not have to be backed up to get some
18: * operand. For example, operand(0) and then operand(1)
19: * and then operand(2) is OK. Even operand(0), operand(1),
20: * operand(1) is OK. The rule is that operand(N) should not
21: * be called before operand(N-1) was.
22: *
23: ***********************************************************/
24: {
25: register struct oprnd *next;
26: register struct operand_des *look_at;
27: register int header,reg_num,shift_count, displ;
28: register int keep_last;
29:
30: next = &decoded[number];
31: if (number <= last_operand) return(next);
32: if (number == last_operand+1) last_operand = number;
33: else
34: {
35: printf ("Wrong sequence of OPERAND calls (alignment code)\n");
36: return (&decoded[number]);
37: };
38: look_at = &Table[opCODE].operand[number];
39: next->data2 = 0; /* Prepare for quad fetch */
40: next->length = look_at->length;
41: if (look_at->add_modes == Brd)
42: {
43: next->mode = Add;
44: switch(look_at->length)
45: {
46: case 1:
47: displ = get_byte(infop, pc);
48: pc++;
49: break;
50: case 2:
51: displ = get_word(infop, pc);
52: pc +=2;
53: break;
54: default:
55: printf ("Wrong branch displacement(alignment code)\n");
56: };
57: next->address = pc+displ;
58: return(next);
59: };
60:
61: /* Not branch displacement, real operand */
62: header = get_byte(infop, pc) & 0xff;
63: pc++;
64: reg_num = header & 0xf;
65: switch (header >> 4 & 0xf) {
66: case 0: /* Short literals */
67: case 1:
68: case 2:
69: case 3:
70: if (illegal(Lit)) exception(infop, ILL_ADDRMOD);
71: next->mode = Imm;
72: next->data = header;
73: break;
74:
75: case 4: /* Indexed register */
76: if (illegal(Add) || reg_num==PCOUNTER || reg_num==SPOINTER)
77: exception (infop, ILL_ADDRMOD);
78: keep_last = last_operand;
79: last_operand = number - 1; /* To get real results */
80: next = operand(infop, number); /* Get base address (recursive) */
81: last_operand = keep_last;
82: if
83: (! (next->mode & Indx)) exception (infop, ILL_ADDRMOD);
84: switch (look_at->length)
85: {
86: case 1:
87: shift_count = 0;
88: break;
89: case 2:
90: shift_count = 1;
91: break;
92: case 4:
93: shift_count = 2;
94: break;
95: case 8:
96: shift_count = 3;
97: break;
98: default:
99: printf("Wrong data length in table(alignment code)\n");
100: };
101: next->address += (Register(infop,reg_num) << shift_count);
102: next->mode |= (look_at->add_modes & M); /* Set R/W bits */
103: trytoread (infop,next,number);
104: break;
105:
106: case 5: /* Direct register */
107: if (illegal (Dir) || reg_num==PCOUNTER ||
108: reg_num==SPOINTER && legal(R)) exception (infop, ILL_ADDRMOD);
109: next->mode = Dir;
110: next->data = Register(infop,reg_num);
111: next->mode |= (look_at->add_modes & M); /* Set R/W bits */
112: next->reg_number = reg_num;
113: if (look_at->length == 8)
114: {
115: if (reg_num >= SPOINTER-1 || (reg_num & 1)==1 )
116: exception (infop, ILL_ADDRMOD);
117: else next->data2 = Register(infop,reg_num+1);
118: };
119: break;
120:
121: case 6: /* Indirect register */
122: if (illegal(Add) || reg_num==PCOUNTER )
123: exception (infop, ILL_ADDRMOD);
124: next->mode = Add;
125: next->mode |= (look_at->add_modes & M); /* Set R/W bits */
126: if (reg_num != SPOINTER) next->mode |= Indx; /* (sp) not indexable*/
127: next->reg_number = reg_num;
128: next->address = Register(infop,reg_num);
129: trytoread (infop,next,number);
130: break;
131:
132: case 7: /* Autodecrement SP */
133: if (illegal(Add) || reg_num!=SPOINTER || look_at->length != 4 ||
134: legal(R)) exception (infop, ILL_ADDRMOD);
135: next->mode = SPmode; /* Implies Add */
136: next->mode |= W; /* Set R/W bits */
137: next->reg_number = SPOINTER;
138: next->length = 4; /* Regardless of big table */
139: sp -= 4;
140: next->address = sp;
141: break;
142:
143: case 8: /* Immediate or (sp)+ */
144: switch (reg_num) {
145: case 8: /* Immediate byte */
146: if (illegal(Imm)) exception (infop, ILL_ADDRMOD);
147: next->mode = Imm;
148: next->data = get_byte(infop, pc);
149: pc++;
150: break;
151: case 9: /* Immediate word */
152: if (illegal(Imm)) exception (infop, ILL_ADDRMOD);
153: next->mode = Imm;
154: next->data = get_word(infop, pc);
155: pc +=2;
156: break;
157: case 0xf : /* Immediate longword */
158: if (illegal(Imm)) exception (infop, ILL_ADDRMOD);
159: next->mode = Imm;
160: next->data = get_longword(infop, pc);
161: pc +=4;
162: break;
163: case 0xe: /* Autoincrement sp */
164: if (illegal(Add) || legal(W) ||
165: look_at->length != 4) exception (infop, ILL_ADDRMOD);
166: next->mode = SPmode; /* Implies Add */
167: next->reg_number = SPOINTER;
168: next->address = sp;
169: next->data = get_longword(infop, sp);
170: next->length = 4; /* Regardless of big table */
171: sp += 4;
172: break;
173: default:
174: exception (infop, ILL_ADDRMOD);
175: };
176: if (look_at -> length == 8) /* Quadword fetch,not (sp)+ */
177: {
178: next->data2 = next->data;
179: if (next->data2 >= 0) next->data = 0;
180: else next->data = -1;
181: }
182: break;
183:
184: case 9: /* Autoincrement deferred SP or PC */
185: if (reg_num !=PCOUNTER && reg_num !=SPOINTER )
186: exception (infop, ILL_ADDRMOD);
187: if (reg_num == PCOUNTER && illegal(Abs) ||
188: reg_num == SPOINTER && illegal(Add))
189: exception (infop, ILL_ADDRMOD);
190: next->mode = Add | (look_at->add_modes & M) | Indx;
191: next->address = get_longword (infop, (reg_num == PCOUNTER)?pc : sp );
192: Replace (infop,reg_num, Register(infop,reg_num)+4);
193: trytoread (infop,next,number);
194: break;
195:
196: case 0xa: /* Register or PC + byte displacement */
197: if (reg_num != PCOUNTER && illegal(Add) ||
198: reg_num == PCOUNTER && illegal(Pcrel) ) exception (infop, ILL_ADDRMOD);
199: next->mode = Add | (look_at->add_modes & M);
200: if (reg_num != SPOINTER &&
201: look_at->add_modes != PR) next->mode |= Indx;
202: displ = get_byte(infop,pc);
203: pc++;
204: next->address = Register(infop,reg_num)+displ;
205: trytoread (infop,next,number);
206: break;
207:
208: case 0xb: /* Same, indirect */
209: if (illegal(Add)) exception (infop, ILL_ADDRMOD);
210: next->mode = Add | (look_at->add_modes & M) | Indx;
211: displ = get_byte(infop,pc);
212: pc++;
213: next->address = get_longword(infop, Register(infop,reg_num)+displ);
214: trytoread (infop,next,number);
215: break;
216:
217: case 0xc: /* Register or PC + word displacement */
218: if (reg_num != PCOUNTER && illegal(Add) ||
219: reg_num == PCOUNTER && illegal(Pcrel) ) exception (infop, ILL_ADDRMOD);
220: next->mode = Add | (look_at->add_modes & M);
221: if (reg_num != SPOINTER &&
222: look_at->add_modes != PR) next->mode |= Indx;
223: displ = get_word(infop,pc);
224: pc +=2;
225: next->address = Register(infop,reg_num)+displ;
226: trytoread (infop,next,number);
227: break;
228:
229: case 0xd: /* Same, indirect */
230: if (illegal(Add)) exception (infop, ILL_ADDRMOD);
231: next->mode =Add | (look_at->add_modes & M) | Indx ;
232: displ = get_word(infop,pc);
233: pc +=2;
234: next->address = get_longword (infop,Register(infop,reg_num)+displ);
235: trytoread (infop,next,number);
236: break;
237:
238:
239: case 0xe: /* Register or PC + longword displacement */
240: if (reg_num != PCOUNTER && illegal(Add) ||
241: reg_num == PCOUNTER && illegal(Pcrel) ) exception (infop, ILL_ADDRMOD);
242: next->mode = Add | (look_at->add_modes & M);
243: if (reg_num != SPOINTER &&
244: look_at->add_modes != PR) next->mode |= Indx;
245: displ = get_longword(infop,pc);
246: pc += 4;
247: next->address = Register(infop,reg_num)+displ;
248: trytoread (infop,next,number);
249: break;
250:
251: case 0xf: /* Same, indirect */
252: if (illegal(Add)) exception (infop, ILL_ADDRMOD);
253: next->mode = Add | (look_at->add_modes & M) | Indx;
254: displ = get_longword(infop,pc);
255: pc +=4;
256: next->address = get_longword(infop, Register(infop,reg_num)+displ);
257: trytoread (infop,next,number);
258: };
259: return(next);
260: }
261:
262:
263: trytoread (infop,pointer,number)
264: process_info *infop;
265: struct oprnd *pointer;
266: int number;
267: /*
268: /* Receives the opcode operand number and a pointer
269: /* to the 'decoded' operand structure.
270: /* If it's defined as readable data in the big table,
271: /* it returns the data, sign extended.
272: /*
273: /**********************************************************/
274:
275: {
276: register struct operand_des *look_at;
277:
278:
279: look_at = &Table[opCODE].operand[number];
280: if (legal(R))
281: switch (look_at->length)
282: {
283: case 1:
284: pointer->data = get_byte (infop,pointer->address);
285: break;
286: case 2:
287: pointer->data = get_word (infop,pointer->address);
288: break;
289: case 4:
290: pointer->data = get_longword (infop,pointer->address);
291: break;
292: case 8:
293: pointer->data = get_longword (infop,pointer->address);
294: pointer->data2 = get_longword (infop,pointer->address+4);
295: break;
296: default:
297: printf ("Wrong data length in table (alignment code)\n");
298: };
299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.