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