|
|
1.1 root 1: /* $Id: sparc-execute.c,v 1.5 2007/03/29 01:06:59 fredette Exp $ */
2:
3: /* ic/sparc/sparc-execute.c - executes SPARC instructions: */
4:
5: /*
6: * Copyright (c) 2005 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: _TME_RCSID("$Id: sparc-execute.c,v 1.5 2007/03/29 01:06:59 fredette Exp $");
37:
38: /* includes: */
39: #include "sparc-auto.h"
40:
41: #if (TME_SPARC_VERSION(ic) < 9)
42: #define tme_sparc_ireg_t tme_uint32_t
43: #define tme_sparc_ireg(x) tme_sparc_ireg_uint32(x)
44: #define tme_sparc_idle_type_pc tme_sparc_idle_type_pc32
45: #else /* TME_SPARC_VERSION(ic) >= 9 */
46: #define tme_sparc_ireg_t tme_uint64_t
47: #define tme_sparc_ireg(x) tme_sparc_ireg_uint64(x)
48: #define tme_sparc_idle_type_pc tme_sparc_idle_type_pc64
49: #endif /* TME_SPARC_VERSION(ic) >= 9 */
50:
51: /* the sparc instruction executor: */
52: static void
53: _TME_SPARC_EXECUTE_NAME(struct tme_sparc *ic)
54: {
55: tme_uint32_t asi_mask_insn;
56: tme_uint32_t asi_mask_data;
57: struct tme_sparc_tlb *itlb_current;
58: struct tme_sparc_tlb itlb_invalid;
59: tme_sparc_ireg_t pc;
60: tme_uint32_t insn;
61: unsigned int opcode;
62: unsigned int reg_rs1;
63: unsigned int reg_rs2;
64: unsigned int reg_rd;
65: int annulled;
66: int rc;
67: tme_uint8_t conds_mask_icc;
68: tme_uint8_t conds_mask_fcc;
69: tme_uint16_t conds_mask;
70: unsigned int cond;
71:
72: /* get the default address space identifiers and masks: */
73: if (TME_SPARC_VERSION(ic) < 9) {
74: if (TME_SPARC_PRIV(ic)) {
75: asi_mask_insn = TME_SPARC32_ASI_MASK_SI;
76: asi_mask_data = TME_SPARC32_ASI_MASK_SD;
77: }
78: else {
79: asi_mask_insn = TME_SPARC32_ASI_MASK_UI;
80: asi_mask_data = TME_SPARC32_ASI_MASK_UD;
81: }
82: }
83: else {
84: asi_mask_data
85: = ((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_CLE)
86: ? TME_SPARC64_ASI_MASK_PRIMARY_LITTLE
87: : TME_SPARC64_ASI_MASK_PRIMARY);
88: asi_mask_insn = asi_mask_data;
89: }
90: ic->tme_sparc_asi_mask_insn = asi_mask_insn;
91: ic->tme_sparc_asi_mask_data = asi_mask_data;
92:
93: /* create an invalid instruction TLB entry, and use it as the initial
94: current instruction TLB entry: */
95: tme_bus_tlb_construct(&itlb_invalid.tme_sparc_tlb_bus_tlb);
96: itlb_invalid.tme_sparc_tlb_addr_first = 1;
97: itlb_invalid.tme_sparc_tlb_addr_last = 0;
98: itlb_current = &itlb_invalid;
99:
100: /* busy the invalid instruction TLB entry: */
101: assert (ic->_tme_sparc_itlb_busy == NULL);
102: tme_sparc_tlb_busy(itlb_current);
103: ic->_tme_sparc_itlb_busy = itlb_current;
104:
105: /* the first instruction will not be annulled: */
106: annulled = FALSE;
107:
108: for (;;) {
109:
110: /* if we have used up our instruction burst: */
111: if (__tme_predict_false(ic->_tme_sparc_instruction_burst_remaining == 0)) {
112:
113: /* try to acquire the external mutex and check for external
114: resets, halts, or interrupts, and process them: */
115: rc = tme_mutex_trylock(&ic->tme_sparc_external_mutex);
116: if (__tme_predict_true(TME_THREADS_ERRNO(rc) == TME_OK)) {
117: #if TME_SPARC_VERSION(ic) < 9
118: tme_sparc32_external_check(ic);
119: #else /* TME_SPARC_VERSION(ic) >= 9 */
120: tme_sparc64_external_check(ic);
121: #endif /* TME_SPARC_VERSION(ic) >= 9 */
122:
123: /* unlock the external mutex: */
124: tme_mutex_unlock(&ic->tme_sparc_external_mutex);
125: }
126:
127: /* start a new instruction burst: */
128: ic->_tme_sparc_instruction_burst_remaining
129: = ic->_tme_sparc_instruction_burst;
130:
131: /* if we are in the idle loop: */
132: if (__tme_predict_false((ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT)
133: == ic->tme_sparc_idle_type_pc)
134: && TME_SPARC_IDLE_TYPE_IS(ic,
135: (TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0)))) {
136: tme_sparc_do_idle(ic);
137: }
138:
139: /* if this is a cooperative threading system: */
140: #if TME_THREADS_COOPERATIVE
141:
142: /* unbusy the current instruction TLB entry: */
143: assert (ic->_tme_sparc_itlb_busy == itlb_current);
144: tme_sparc_tlb_unbusy(itlb_current);
145: ic->_tme_sparc_itlb_busy = NULL;
146:
147: /* yield: */
148: tme_thread_yield();
149: #endif /* TME_THREADS_COOPERATIVE */
150: }
151:
152: /* we are going to use one instruction in the burst: */
153: ic->_tme_sparc_instruction_burst_remaining--;
154: #ifdef _TME_SPARC_STATS
155: ic->tme_sparc_stats.tme_sparc_stats_insns_total++;
156: #endif /* _TME_SPARC_STATS */
157:
158: /* update the PCs and get the PC of the instruction to execute: */
159: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT);
160: ic->tme_sparc_ireg(TME_SPARC_IREG_PC) = pc;
161: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT);
162: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) += sizeof(tme_uint32_t);
163:
164: /* NB that we only save instruction TLB entries that allow fast
165: reading, and we also change tme_sparc_tlb_addr_last to be the
166: last PC covered by the entry (it's normally the last address
167: covered by the entry). this allows us to do minimal checking
168: of the current instruction TLB entry at itlb_current: */
169:
170: /* if the current instruction TLB entry covers this address: */
171: if (__tme_predict_true(itlb_current->tme_sparc_tlb_addr_first <= pc
172: && pc <= itlb_current->tme_sparc_tlb_addr_last)) {
173:
174: /* fetch the instruction: */
175: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc),
176: itlb_current->tme_sparc_tlb_bus_rwlock,
177: sizeof(tme_uint32_t),
178: sizeof(tme_sparc_ireg_t));
179: insn = tme_betoh_u32(insn);
180: }
181:
182: /* otherwise, our current TLB entry doesn't cover this address: */
183: else {
184:
185: /* unbusy the current instruction TLB entry: */
186: assert (ic->_tme_sparc_itlb_busy == itlb_current);
187: tme_sparc_tlb_unbusy(itlb_current);
188:
189: /* rehash the current instruction TLB entry: */
190: itlb_current = tme_memory_atomic_pointer_read(struct tme_sparc_tlb *,
191: ic->_tme_sparc_itlb_array,
192: &ic->_tme_sparc_tlb_rwlock);
193: itlb_current += (pc >> 10) % _TME_SPARC_ITLB_HASH_SIZE;
194:
195: /* busy the current instruction TLB entry: */
196: tme_sparc_tlb_busy(itlb_current);
197: ic->_tme_sparc_itlb_busy = itlb_current;
198:
199: /* if the new current instruction TLB entry is valid and covers
200: this address: */
201: if (tme_bus_tlb_is_valid(&itlb_current->tme_sparc_tlb_bus_tlb)
202: && __tme_predict_true(TME_SPARC_TLB_ASI_MASK_OK(itlb_current, asi_mask_insn)
203: && itlb_current->tme_sparc_tlb_addr_first <= pc
204: && pc <= itlb_current->tme_sparc_tlb_addr_last)) {
205:
206: /* fetch the instruction: */
207: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc),
208: itlb_current->tme_sparc_tlb_bus_rwlock,
209: sizeof(tme_uint32_t),
210: sizeof(tme_sparc_ireg_t));
211: insn = tme_betoh_u32(insn);
212: }
213:
214: /* otherwise, the new current instruction TLB entry is not valid
215: or does not cover this address: */
216: else {
217:
218: /* we never fill TLB entries on the stack because we never
219: callout multiple fills at the same time, so the global TLB
220: entry pointer always points back to the TLB entry. this
221: also means that we don't have to call tme_bus_tlb_back()
222: after the fill: */
223: itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_global = &itlb_current->tme_sparc_tlb_bus_tlb;
224:
225: /* loop until we can busy a valid TLB entry: */
226: do {
227:
228: /* unbusy the current instruction TLB entry for filling: */
229: tme_bus_tlb_unbusy_fill(&itlb_current->tme_sparc_tlb_bus_tlb);
230:
231: /* fill the current instruction TLB entry: */
232: #ifdef _TME_SPARC_STATS
233: ic->tme_sparc_stats.tme_sparc_stats_itlb_fill++;
234: #endif /* _TME_SPARC_STATS */
235: (*ic->_tme_sparc_bus_connection->tme_sparc_bus_tlb_fill)
236: (ic->_tme_sparc_bus_connection,
237: itlb_current,
238: asi_mask_insn,
239: ic->tme_sparc_ireg(TME_SPARC_IREG_PC),
240: TME_BUS_CYCLE_READ);
241:
242: /* busy the current instruction TLB entry: */
243: tme_sparc_tlb_busy(itlb_current);
244:
245: } while (tme_bus_tlb_is_invalid(&itlb_current->tme_sparc_tlb_bus_tlb));
246:
247: /* the current instruction TLB entry must now cover this
248: address and allow reading: */
249: /* NB that tme_sparc_tlb_addr_last has not been changed yet: */
250: assert (TME_SPARC_TLB_ASI_MASK_OK(itlb_current, asi_mask_insn)
251: && itlb_current->tme_sparc_tlb_addr_first <= pc
252: && pc <= itlb_current->tme_sparc_tlb_addr_last
253: && (itlb_current->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
254: || (itlb_current->tme_sparc_tlb_cycles_ok & TME_BUS_CYCLE_READ)));
255:
256: /* if this current instruction TLB entry covers the entire
257: instruction and allows fast reading: */
258: if (__tme_predict_true(itlb_current->tme_sparc_tlb_addr_last >= (pc + (sizeof(tme_uint32_t) - 1))
259: && itlb_current->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
260:
261: /* fetch the instruction: */
262: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc),
263: itlb_current->tme_sparc_tlb_bus_rwlock,
264: sizeof(tme_uint32_t),
265: sizeof(tme_sparc_ireg_t));
266: insn = tme_betoh_u32(insn);
267:
268: /* modify tme_sparc_tlb_addr_last of this first to represent the last valid
269: PC covered by the entry: */
270: itlb_current->tme_sparc_tlb_addr_last
271: &= (((tme_bus_addr_t) 0) - sizeof(tme_uint32_t));
272: }
273:
274: /* otherwise, this instruction TLB entry does not cover the
275: entire instruction and/or it does not allow fast reading.
276: fetching an instruction here may mean making multiple bus
277: cycles. exactly what happens in this case is
278: implementation-dependent, so we call an
279: implementation-specific function here to handle it: */
280: else {
281:
282: /* unbusy the current instruction TLB entry and poison it,
283: so we won't try to do any fast fetches with it: */
284: assert (ic->_tme_sparc_itlb_busy == itlb_current);
285: tme_sparc_tlb_unbusy(itlb_current);
286: itlb_current->tme_sparc_tlb_addr_first = 1;
287: itlb_current->tme_sparc_tlb_addr_last = 0;
288: ic->_tme_sparc_itlb_busy = NULL;
289:
290: /* NB that while annulled instructions are always fetched,
291: fetching an annulled instruction can never generate an
292: instruction_access exception, since the annul bit is not
293: part of the architected state. so we pass in the
294: annulled indication to the slow instruction fetcher: */
295: insn = (*ic->_tme_sparc_fetch_slow)(ic, annulled);
296: #ifdef _TME_SPARC_STATS
297: ic->tme_sparc_stats.tme_sparc_stats_insns_slow++;
298: #endif /* _TME_SPARC_STATS */
299:
300: /* busy the invalid instruction TLB entry: */
301: itlb_current = &itlb_invalid;
302: assert (ic->_tme_sparc_itlb_busy == NULL);
303: tme_sparc_tlb_busy(itlb_current);
304: ic->_tme_sparc_itlb_busy = itlb_current;
305: }
306: }
307:
308: /* if this instruction has been annulled: */
309: if (__tme_predict_false(annulled)) {
310:
311: /* the netbsd32-type-0 idle type is detected when an annulled
312: "wr %g1, PSR_PIL, %psr" or "wr %l1, (IPL_SCHED << 8), %psr"
313: instruction is found four instructions after (in
314: disassembly order, not execution order) a "wr %g1, 0, %psr"
315: or "wr %l1, 0, %psr" instruction that sets PIL to 0x0: */
316: if (__tme_predict_false((insn
317: & ~((31 << 25) /* rd (reserved) */
318: | (0x10 << 14) /* rs1 (mask %ln to %gn) */
319: | (0x4 << 8))) /* imm13 (mask PSR_PIL to (IPL_SCHED << 8)) */
320: == ((tme_uint32_t)
321: (2 << 30) /* format */
322: | (0x31 << 19) /* op3 (wrpsr) */
323: | (0x01 << 14) /* rs1 (%g1) */
324: | (1 << 13) /* i */
325: | 0x0b00))) { /* imm13 (IPL_SCHED << 8) */
326: if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0)) {
327: if (ic->tme_sparc_ireg(TME_SPARC_IREG_PC)
328: == (ic->tme_sparc_idle_type_pc
329: - TME_SPARC_IDLE_TYPE_PC_STATE(1)
330: + (sizeof(tme_uint32_t) * 4))) {
331: ic->tme_sparc_idle_type_pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC);
332: }
333: if (ic->tme_sparc_ireg(TME_SPARC_IREG_PC)
334: == ic->tme_sparc_idle_type_pc) {
335: tme_sparc_do_idle(ic);
336: }
337: }
338: }
339:
340: /* make this instruction a nop: */
341: insn = 0x01000000;
342: }
343:
344: /* the next instruction will not be annulled: */
345: annulled = FALSE;
346: }
347:
348: /* start this instruction: */
349: ic->_tme_sparc_insn = insn;
350: #ifdef _TME_SPARC_VERIFY
351: if (ic->tme_sparc_ireg(TME_SPARC_IREG_PC) == 0x6000) {
352: tme_sparc_verify_hook();
353: }
354: #endif
355:
356: /* set %g0 to zero: */
357: ic->tme_sparc_ireg(TME_SPARC_IREG_G0) = 0;
358:
359: /* if this is a format three instruction (op is two or three): */
360: if (__tme_predict_true(insn >= 0x80000000)) {
361:
362: /* if the i bit is zero: */
363: if (__tme_predict_true((insn & TME_BIT(13)) == 0)) {
364:
365: /* decode rs2: */
366: reg_rs2 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS2);
367: TME_SPARC_REG_INDEX(ic, reg_rs2);
368: }
369:
370: /* otherwise, the i bit is one: */
371: else {
372:
373: /* decode simm13: */
374: ic->tme_sparc_ireg(TME_SPARC_IREG_IMM) = TME_FIELD_MASK_EXTRACTS(insn, (tme_sparc_ireg_t) 0x1fff);
375: reg_rs2 = TME_SPARC_IREG_IMM;
376: }
377:
378: /* decode rs1: */
379: reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1);
380: TME_SPARC_REG_INDEX(ic, reg_rs1);
381:
382: /* decode rd: */
383: reg_rd = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RD);
384: TME_SPARC_REG_INDEX(ic, reg_rd);
385:
386: /* form the opcode index: */
387: opcode = TME_FIELD_MASK_EXTRACTU(insn, (0x3f << 19));
388: opcode += ((insn >> (30 - 6)) & 0x40);
389:
390: /* run the instruction: */
391: (*_TME_SPARC_EXECUTE_OPMAP[opcode])
392: (ic,
393: &ic->tme_sparc_ireg(reg_rs1),
394: &ic->tme_sparc_ireg(reg_rs2),
395: &ic->tme_sparc_ireg(reg_rd));
396: }
397:
398: /* otherwise, if this is a format two instruction: */
399: else if (__tme_predict_true(insn < 0x40000000)) {
400:
401: /* dispatch on op2: */
402: switch (TME_FIELD_MASK_EXTRACTU(insn, (0x7 << 22))) {
403: default:
404:
405: case 0: /* UNIMP: */
406: #if TME_SPARC_VERSION(ic) < 9
407: tme_sparc32_trap(ic, TME_SPARC_TRAP_illegal_instruction);
408: #else /* TME_SPARC_VERSION(ic) >= 9 */
409: tme_sparc64_trap(ic, TME_SPARC_TRAP_illegal_instruction);
410: #endif /* TME_SPARC_VERSION(ic) >= 9 */
411: continue;
412:
413: case 2: /* Bicc: */
414: conds_mask_icc = _tme_sparc_conds_icc[
415: #if TME_SPARC_VERSION(ic) < 9
416: TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_ICC)
417: #else /* TME_SPARC_VERSION(ic) >= 9 */
418: TME_FIELD_MASK_EXTRACTU(ic->tme_sparc64_ireg_ccr, TME_SPARC64_CCR_ICC)
419: #endif /* TME_SPARC_VERSION(ic) >= 9 */
420: ];
421:
422: /* add the not-conditions to the conditions mask: */
423: conds_mask = conds_mask_icc ^ 0xff;
424: conds_mask = (conds_mask << 8) | conds_mask_icc;
425: break;
426:
427: case 4: /* SETHI: */
428:
429: /* decode rd: */
430: reg_rd = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RD);
431: TME_SPARC_REG_INDEX(ic, reg_rd);
432: ic->tme_sparc_ireg(reg_rd) = (insn << 10);
433: continue;
434:
435: case 6: /* FBfcc: */
436: TME_SPARC_INSN_FPU;
437: conds_mask_fcc = _tme_sparc_conds_fcc[TME_FIELD_MASK_EXTRACTU(ic->tme_sparc_fpu_fsr, TME_SPARC_FSR_FCC)];
438:
439: /* add the not-conditions to the conditions mask: */
440: conds_mask = conds_mask_fcc ^ 0xff;
441: conds_mask = (conds_mask << 8) | conds_mask_fcc;
442: break;
443: }
444:
445: /* get the condition field: */
446: cond = TME_FIELD_MASK_EXTRACTU(insn, (0xf << 25));
447:
448: /* if this conditional branch is taken: */
449: if (conds_mask & TME_BIT(cond)) {
450:
451: /* do the delayed control transfer: */
452: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT)
453: = (ic->tme_sparc_ireg(TME_SPARC_IREG_PC)
454: + (TME_FIELD_MASK_EXTRACTS(insn, (tme_sparc_ireg_t) 0x003fffff) << 2));
455:
456: /* if this is a delayed control transfer to the idle loop: */
457: if (__tme_predict_false(ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT)
458: == ic->tme_sparc_idle_type_pc)) {
459: if (TME_SPARC_IDLE_TYPE_IS(ic, (TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0))) {
460:
461: /* reduce this instruction burst to include only the delay
462: instruction. before the next instruction burst begins
463: (on the first instruction of the idle loop) we will
464: detect that and go idle: */
465: ic->_tme_sparc_instruction_burst_remaining = 1;
466: }
467: }
468:
469: /* if this was a conditional branch, clear the annul bit in
470: the instruction image: */
471: if (cond & 7) {
472: insn &= ~TME_BIT(29);
473: }
474: }
475:
476: /* if the annul bit it set: */
477: if (insn & TME_BIT(29)) {
478:
479: /* the next instruction will be annulled. to get the
480: execution loop to pay attention to the annulled bit,
481: make the current instruction TLB entry invalid: */
482: annulled = TRUE;
483: assert (ic->_tme_sparc_itlb_busy == itlb_current);
484: tme_sparc_tlb_unbusy(itlb_current);
485: itlb_current = &itlb_invalid;
486: tme_sparc_tlb_busy(itlb_current);
487: ic->_tme_sparc_itlb_busy = itlb_current;
488: /* NB that we have to make sure the next instruction gets executed
489: in the immediate next iteration of the execution loop, since the
490: annulled bit is not part of the architected CPU state, and we also
491: want to do good emulation and actually fetch the instruction (as
492: opposed to just advancing the PCs now). to do this, we make sure
493: that there is at least one more instruction left in the burst: */
494: ic->_tme_sparc_instruction_burst_remaining += (ic->_tme_sparc_instruction_burst_remaining == 0);
495: }
496: }
497:
498: /* otherwise, this is a format one instruction: */
499: else {
500:
501: /* get the current PC: */
502: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC);
503:
504: /* write the PC of the CALL into r[15]: */
505: ic->tme_sparc_ireg(ic->tme_sparc_cwp_offset + 15) = pc;
506:
507: /* log the call: */
508: tme_sparc_log(ic, 250, TME_OK,
509: (TME_SPARC_LOG_HANDLE(ic),
510: _("call 0x%08x"),
511: pc + (insn << 2)));
512:
513: /* do the delayed control transfer: */
514: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) = pc + (insn << 2);
515: }
516: }
517:
518: /* NOTREACHED */
519: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.