static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) { int j, k, l, sb_x, sb_y; int coding_mode; int motion_x[6]; int motion_y[6]; int last_motion_x = 0; int last_motion_y = 0; int prior_last_motion_x = 0; int prior_last_motion_y = 0; int current_macroblock; int current_fragment; if (s->keyframe) return 0; memset(motion_x, 0, 6 * sizeof(int)); memset(motion_y, 0, 6 * sizeof(int)); /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme */ coding_mode = get_bits1(gb); /* iterate through all of the macroblocks that contain 1 or more * coded fragments */ for (sb_y = 0; sb_y < s->y_superblock_height; sb_y++) { for (sb_x = 0; sb_x < s->y_superblock_width; sb_x++) { for (j = 0; j < 4; j++) { int mb_x = 2*sb_x + (j>>1); int mb_y = 2*sb_y + (((j>>1)+j)&1); current_macroblock = mb_y * s->macroblock_width + mb_x; if (mb_x >= s->macroblock_width || mb_y >= s->macroblock_height || (s->macroblock_coding[current_macroblock] == MODE_COPY)) continue; switch (s->macroblock_coding[current_macroblock]) { case MODE_INTER_PLUS_MV: case MODE_GOLDEN_MV: /* all 6 fragments use the same motion vector */ if (coding_mode == 0) { motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; } else { motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)]; motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)]; } /* vector maintenance, only on MODE_INTER_PLUS_MV */ if (s->macroblock_coding[current_macroblock] == MODE_INTER_PLUS_MV) { prior_last_motion_x = last_motion_x; prior_last_motion_y = last_motion_y; last_motion_x = motion_x[0]; last_motion_y = motion_y[0]; } break; case MODE_INTER_FOURMV: /* vector maintenance */ prior_last_motion_x = last_motion_x; prior_last_motion_y = last_motion_y; /* fetch 4 vectors from the bitstream, one for each * Y fragment, then average for the C fragment vectors */ motion_x[4] = motion_y[4] = 0; for (k = 0; k < 4; k++) { current_fragment = BLOCK_Y*s->fragment_width + BLOCK_X; for (l = 0; l < s->coded_fragment_list_index; l++) if (s->coded_fragment_list[l] == current_fragment) break; if (l < s->coded_fragment_list_index) { if (coding_mode == 0) { motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; } else { motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)]; motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)]; } last_motion_x = motion_x[k]; last_motion_y = motion_y[k]; } else { motion_x[k] = 0; motion_y[k] = 0; } motion_x[4] += motion_x[k]; motion_y[4] += motion_y[k]; } motion_x[5]= motion_x[4]= RSHIFT(motion_x[4], 2); motion_y[5]= motion_y[4]= RSHIFT(motion_y[4], 2); break; case MODE_INTER_LAST_MV: /* all 6 fragments use the last motion vector */ motion_x[0] = last_motion_x; motion_y[0] = last_motion_y; /* no vector maintenance (last vector remains the * last vector) */ break; case MODE_INTER_PRIOR_LAST: /* all 6 fragments use the motion vector prior to the * last motion vector */ motion_x[0] = prior_last_motion_x; motion_y[0] = prior_last_motion_y; /* vector maintenance */ prior_last_motion_x = last_motion_x; prior_last_motion_y = last_motion_y; last_motion_x = motion_x[0]; last_motion_y = motion_y[0]; break; default: /* covers intra, inter without MV, golden without MV */ motion_x[0] = 0; motion_y[0] = 0; /* no vector maintenance */ break; } /* assign the motion vectors to the correct fragments */ for (k = 0; k < 4; k++) { current_fragment = BLOCK_Y*s->fragment_width + BLOCK_X; if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { s->all_fragments[current_fragment].motion_x = motion_x[k]; s->all_fragments[current_fragment].motion_y = motion_y[k]; } else { s->all_fragments[current_fragment].motion_x = motion_x[0]; s->all_fragments[current_fragment].motion_y = motion_y[0]; } } for (k = 0; k < 2; k++) { current_fragment = s->fragment_start[k+1] + mb_y*(s->fragment_width>>1) + mb_x; if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { s->all_fragments[current_fragment].motion_x = motion_x[k+4]; s->all_fragments[current_fragment].motion_y = motion_y[k+4]; } else { s->all_fragments[current_fragment].motion_x = motion_x[0]; s->all_fragments[current_fragment].motion_y = motion_y[0]; } } } } } return 0; }


void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp) { int64_t value; if (!error_is_set(errp)) { if (v->type_int32) { v->type_int32(v, obj, name, errp); } else { value = *obj; v->type_int(v, &value, name, errp); if (value < INT32_MIN || value > INT32_MAX) { error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", "int32_t"); return; } *obj = value; } } }


static inline void gen_bx_im(DisasContext *s, uint32_t addr) { TCGv tmp; s->is_jmp = DISAS_UPDATE; if (s->thumb != (addr & 1)) { tmp = new_tmp(); tcg_gen_movi_i32(tmp, addr & 1); tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); dead_tmp(tmp); } tcg_gen_movi_i32(cpu_R[15], addr & ~1); }


int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size) { int pending = size; int done = 0; while (pending > 0) { int res; res = qemu_peek_buffer(f, buf, pending, 0); if (res == 0) { return done; } qemu_file_skip(f, res); buf += res; pending -= res; done += res; } return done; }


static void buffer_append(Buffer *buffer, const void *data, size_t len) { memcpy(buffer->buffer + buffer->offset, data, len); buffer->offset += len; }


void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output) { int i; uint8_t *printed = av_mallocz(ic->nb_streams); if (ic->nb_streams && !printed) return; av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n", is_output ? "Output" : "Input", index, is_output ? ic->oformat->name : ic->iformat->name, is_output ? "to" : "from", url); dump_metadata(NULL, ic->metadata, " "); if (!is_output) { av_log(NULL, AV_LOG_INFO, " Duration: "); if (ic->duration != AV_NOPTS_VALUE) { int hours, mins, secs, us; secs = ic->duration / AV_TIME_BASE; us = ic->duration % AV_TIME_BASE; mins = secs / 60; secs %= 60; hours = mins / 60; mins %= 60; av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs, (100 * us) / AV_TIME_BASE); } else { av_log(NULL, AV_LOG_INFO, "N/A"); } if (ic->start_time != AV_NOPTS_VALUE) { int secs, us; av_log(NULL, AV_LOG_INFO, ", start: "); secs = ic->start_time / AV_TIME_BASE; us = abs(ic->start_time % AV_TIME_BASE); av_log(NULL, AV_LOG_INFO, "%d.%06d", secs, (int)av_rescale(us, 1000000, AV_TIME_BASE)); } av_log(NULL, AV_LOG_INFO, ", bitrate: "); if (ic->bit_rate) { av_log(NULL, AV_LOG_INFO,"%d kb/s", ic->bit_rate / 1000); } else { av_log(NULL, AV_LOG_INFO, "N/A"); } av_log(NULL, AV_LOG_INFO, "\n"); } for (i = 0; i < ic->nb_chapters; i++) { AVChapter *ch = ic->chapters[i]; av_log(NULL, AV_LOG_INFO, " Chapter #%d.%d: ", index, i); av_log(NULL, AV_LOG_INFO, "start %f, ", ch->start * av_q2d(ch->time_base)); av_log(NULL, AV_LOG_INFO, "end %f\n", ch->end * av_q2d(ch->time_base)); dump_metadata(NULL, ch->metadata, " "); } if(ic->nb_programs) { int j, k, total = 0; for(j=0; j<ic->nb_programs; j++) { AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata, "name", NULL, 0); av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, name ? name->value : ""); dump_metadata(NULL, ic->programs[j]->metadata, " "); for(k=0; k<ic->programs[j]->nb_stream_indexes; k++) { dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output); printed[ic->programs[j]->stream_index[k]] = 1; } total += ic->programs[j]->nb_stream_indexes; } if (total < ic->nb_streams) av_log(NULL, AV_LOG_INFO, " No Program\n"); } for(i=0;i<ic->nb_streams;i++) if (!printed[i]) dump_stream_format(ic, i, index, is_output); av_free(printed); }


static int r3d_read_redv(AVFormatContext *s, AVPacket *pkt, Atom *atom) { AVStream *st = s->streams[0]; int tmp; int av_unused tmp2; uint64_t pos = avio_tell(s->pb); unsigned dts; int ret; dts = avio_rb32(s->pb); tmp = avio_rb32(s->pb); av_dlog(s, "frame num %d\n", tmp); tmp = avio_r8(s->pb); // major version tmp2 = avio_r8(s->pb); // minor version av_dlog(s, "version %d.%d\n", tmp, tmp2); tmp = avio_rb16(s->pb); // unknown av_dlog(s, "unknown %d\n", tmp); if (tmp > 4) { tmp = avio_rb16(s->pb); // unknown av_dlog(s, "unknown %d\n", tmp); tmp = avio_rb16(s->pb); // unknown av_dlog(s, "unknown %d\n", tmp); tmp = avio_rb32(s->pb); av_dlog(s, "width %d\n", tmp); tmp = avio_rb32(s->pb); av_dlog(s, "height %d\n", tmp); tmp = avio_rb32(s->pb); av_dlog(s, "metadata len %d\n", tmp); } tmp = atom->size - 8 - (avio_tell(s->pb) - pos); if (tmp < 0) return -1; ret = av_get_packet(s->pb, pkt, tmp); if (ret < 0) { av_log(s, AV_LOG_ERROR, "error reading video packet\n"); return -1; } pkt->stream_index = 0; pkt->dts = dts; if (st->avg_frame_rate.num) pkt->duration = (uint64_t)st->time_base.den* st->avg_frame_rate.den/st->avg_frame_rate.num; av_dlog(s, "pkt dts %"PRId64" duration %d\n", pkt->dts, pkt->duration); return 0; }


void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h) { int i, j; w = (x + w) / VNC_STAT_RECT; h = (y + h) / VNC_STAT_RECT; x /= VNC_STAT_RECT; y /= VNC_STAT_RECT; for (j = y; j <= y + h; j++) { for (i = x; i <= x + w; i++) { vs->lossy_rect[j][i] = 1; } } }


static void slow_bar_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { AssignedDevRegion *d = opaque; uint8_t *out = d->u.r_virtbase + addr; DEBUG("slow_bar_writeb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val); *out = val; }


static void exynos4210_i2c_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { Exynos4210I2CState *s = (Exynos4210I2CState *)opaque; uint8_t v = value & 0xff; DPRINT("write %s [0x%02x] <- 0x%02x\n", exynos4_i2c_get_regname(offset), (unsigned int)offset, v); switch (offset) { case I2CCON_ADDR: s->i2ccon = (v & ~I2CCON_INT_PEND) | (s->i2ccon & I2CCON_INT_PEND); if ((s->i2ccon & I2CCON_INT_PEND) && !(v & I2CCON_INT_PEND)) { s->i2ccon &= ~I2CCON_INT_PEND; qemu_irq_lower(s->irq); if (!(s->i2ccon & I2CCON_INTRS_EN)) { s->i2cstat &= ~I2CSTAT_START_BUSY; } if (s->i2cstat & I2CSTAT_START_BUSY) { if (s->scl_free) { if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx) { exynos4210_i2c_data_send(s); } else if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx) { exynos4210_i2c_data_receive(s); } } else { s->i2ccon |= I2CCON_INT_PEND; qemu_irq_raise(s->irq); } } } break; case I2CSTAT_ADDR: s->i2cstat = (s->i2cstat & I2CSTAT_START_BUSY) | (v & ~I2CSTAT_START_BUSY); if (!(s->i2cstat & I2CSTAT_OUTPUT_EN)) { s->i2cstat &= ~I2CSTAT_START_BUSY; s->scl_free = true; qemu_irq_lower(s->irq); break; } /* Nothing to do if in i2c slave mode */ if (!I2C_IN_MASTER_MODE(s->i2cstat)) { break; } if (v & I2CSTAT_START_BUSY) { s->i2cstat &= ~I2CSTAT_LAST_BIT; s->i2cstat |= I2CSTAT_START_BUSY; /* Line is busy */ s->scl_free = false; /* Generate start bit and send slave address */ if (i2c_start_transfer(s->bus, s->i2cds >> 1, s->i2cds & 0x1) && (s->i2ccon & I2CCON_ACK_GEN)) { s->i2cstat |= I2CSTAT_LAST_BIT; } else if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Rx) { exynos4210_i2c_data_receive(s); } exynos4210_i2c_raise_interrupt(s); } else { i2c_end_transfer(s->bus); if (!(s->i2ccon & I2CCON_INT_PEND)) { s->i2cstat &= ~I2CSTAT_START_BUSY; } s->scl_free = true; } break; case I2CADD_ADDR: if ((s->i2cstat & I2CSTAT_OUTPUT_EN) == 0) { s->i2cadd = v; } break; case I2CDS_ADDR: if (s->i2cstat & I2CSTAT_OUTPUT_EN) { s->i2cds = v; s->scl_free = true; if (EXYNOS4_I2C_MODE(s->i2cstat) == I2CMODE_MASTER_Tx && (s->i2cstat & I2CSTAT_START_BUSY) && !(s->i2ccon & I2CCON_INT_PEND)) { exynos4210_i2c_data_send(s); } } break; case I2CLC_ADDR: s->i2clc = v; break; default: DPRINT("ERROR: Bad write offset 0x%x\n", (unsigned int)offset); break; } }


static void virtio_net_apply_guest_offloads(VirtIONet *n) { qemu_peer_set_offload(qemu_get_subqueue(n->nic, 0), !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)), !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)), !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)), !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)), !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO))); }


static int xen_pt_msixctrl_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry, uint16_t *val, uint16_t dev_value, uint16_t valid_mask) { XenPTRegInfo *reg = cfg_entry->reg; uint16_t writable_mask = 0; uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask); int debug_msix_enabled_old; /* modify emulate register */ writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask); /* create value for writing to I/O device register */ *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask); /* update MSI-X */ if ((*val & PCI_MSIX_FLAGS_ENABLE) && !(*val & PCI_MSIX_FLAGS_MASKALL)) { xen_pt_msix_update(s); } else if (!(*val & PCI_MSIX_FLAGS_ENABLE) && s->msix->enabled) { xen_pt_msix_disable(s); } debug_msix_enabled_old = s->msix->enabled; s->msix->enabled = !!(*val & PCI_MSIX_FLAGS_ENABLE); if (s->msix->enabled != debug_msix_enabled_old) { XEN_PT_LOG(&s->dev, "%s MSI-X\n", s->msix->enabled ? "enable" : "disable"); } return 0; }


int v9fs_co_mknod(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid, dev_t dev, mode_t mode) { int err; FsCred cred; cred_init(&cred); cred.fc_uid = uid; cred.fc_gid = gid; cred.fc_mode = mode; cred.fc_rdev = dev; v9fs_co_run_in_worker( { err = s->ops->mknod(&s->ctx, path->data, &cred); if (err < 0) { err = -errno; } }); return err; }


static uint64_t icp_control_read(void *opaque, target_phys_addr_t offset, unsigned size) { switch (offset >> 2) { case 0: /* CP_IDFIELD */ return 0x41034003; case 1: /* CP_FLASHPROG */ return 0; case 2: /* CP_INTREG */ return 0; case 3: /* CP_DECODE */ return 0x11; default: hw_error("icp_control_read: Bad offset %x\n", (int)offset); return 0; } }


int64_t bdrv_get_block_status_above(BlockDriverState *bs, BlockDriverState *base, int64_t sector_num, int nb_sectors, int *pnum, BlockDriverState **file) { Coroutine *co; BdrvCoGetBlockStatusData data = { .bs = bs, .base = base, .file = file, .sector_num = sector_num, .nb_sectors = nb_sectors, .pnum = pnum, .done = false, }; if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ bdrv_get_block_status_above_co_entry(&data); } else { AioContext *aio_context = bdrv_get_aio_context(bs); co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry, &data); qemu_coroutine_enter(co); while (!data.done) { aio_poll(aio_context, true); } } return data.ret; }


static int block_save_complete(QEMUFile *f, void *opaque) { int ret; DPRINTF("Enter save live complete submitted %d transferred %d\n", block_mig_state.submitted, block_mig_state.transferred); ret = flush_blks(f); if (ret) { blk_mig_cleanup(); return ret; } blk_mig_reset_dirty_cursor(); /* we know for sure that save bulk is completed and all async read completed */ assert(block_mig_state.submitted == 0); do { ret = blk_mig_save_dirty_block(f, 0); } while (ret == 0); blk_mig_cleanup(); if (ret) { return ret; } /* report completion */ qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); DPRINTF("Block migration completed\n"); qemu_put_be64(f, BLK_MIG_FLAG_EOS); return 0; }


static void omap_pwl_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { struct omap_pwl_s *s = (struct omap_pwl_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; if (size != 1) { return omap_badwidth_write8(opaque, addr, value); } switch (offset) { case 0x00: /* PWL_LEVEL */ s->level = value; omap_pwl_update(s); break; case 0x04: /* PWL_CTRL */ s->enable = value & 1; omap_pwl_update(s); break; default: OMAP_BAD_REG(addr); return; } }


static int id_wellformed(const char *id) { int i; if (!qemu_isalpha(id[0])) { return 0; } for (i = 1; id[i]; i++) { if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { return 0; } } return 1; }


static void memory_region_iorange_destructor(IORange *iorange) { g_free(container_of(iorange, MemoryRegionIORange, iorange)); }


static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { return -EINVAL; } s->snap = NULL; if (snap_buf[0] != '\0') { s->snap = g_strdup(snap_buf); } r = rados_create(&s->cluster, NULL); if (r < 0) { error_report("error initializing"); return r; } if (strstr(conf, "conf=") == NULL) { r = rados_conf_read_file(s->cluster, NULL); if (r < 0) { error_report("error reading config file"); rados_shutdown(s->cluster); return r; } } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); rados_shutdown(s->cluster); return r; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); rados_shutdown(s->cluster); return r; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); rados_shutdown(s->cluster); return r; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); rados_ioctx_destroy(s->io_ctx); rados_shutdown(s->cluster); return r; } bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); if (r < 0) { error_report("error opening eventfd"); goto failed; } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, NULL, qemu_rbd_aio_flush_cb, NULL, s); return 0; failed: rbd_close(s->image); rados_ioctx_destroy(s->io_ctx); rados_shutdown(s->cluster); return r; }


static void net_socket_receive_dgram(void *opaque, const uint8_t *buf, size_t size) { NetSocketState *s = opaque; sendto(s->fd, buf, size, 0, (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); }


int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) { env->msr_mask = def->msr_mask; env->mmu_model = def->mmu_model; env->excp_model = def->excp_model; env->bus_model = def->bus_model; env->bfd_mach = def->bfd_mach; if (create_ppc_opcodes(env, def) < 0) return -1; init_ppc_proc(env, def); #if defined(PPC_DUMP_CPU) { const unsigned char *mmu_model, *excp_model, *bus_model; switch (env->mmu_model) { case POWERPC_MMU_32B: mmu_model = "PowerPC 32"; break; case POWERPC_MMU_64B: mmu_model = "PowerPC 64"; break; case POWERPC_MMU_601: mmu_model = "PowerPC 601"; break; case POWERPC_MMU_SOFT_6xx: mmu_model = "PowerPC 6xx/7xx with software driven TLBs"; break; case POWERPC_MMU_SOFT_74xx: mmu_model = "PowerPC 74xx with software driven TLBs"; break; case POWERPC_MMU_SOFT_4xx: mmu_model = "PowerPC 4xx with software driven TLBs"; break; case POWERPC_MMU_SOFT_4xx_Z: mmu_model = "PowerPC 4xx with software driven TLBs " "and zones protections"; break; case POWERPC_MMU_REAL_4xx: mmu_model = "PowerPC 4xx real mode only"; break; case POWERPC_MMU_BOOKE: mmu_model = "PowerPC BookE"; break; case POWERPC_MMU_BOOKE_FSL: mmu_model = "PowerPC BookE FSL"; break; case POWERPC_MMU_64BRIDGE: mmu_model = "PowerPC 64 bridge"; break; default: mmu_model = "Unknown or invalid"; break; } switch (env->excp_model) { case POWERPC_EXCP_STD: excp_model = "PowerPC"; break; case POWERPC_EXCP_40x: excp_model = "PowerPC 40x"; break; case POWERPC_EXCP_601: excp_model = "PowerPC 601"; break; case POWERPC_EXCP_602: excp_model = "PowerPC 602"; break; case POWERPC_EXCP_603: excp_model = "PowerPC 603"; break; case POWERPC_EXCP_603E: excp_model = "PowerPC 603e"; break; case POWERPC_EXCP_604: excp_model = "PowerPC 604"; break; case POWERPC_EXCP_7x0: excp_model = "PowerPC 740/750"; break; case POWERPC_EXCP_7x5: excp_model = "PowerPC 745/755"; break; case POWERPC_EXCP_74xx: excp_model = "PowerPC 74xx"; break; case POWERPC_EXCP_970: excp_model = "PowerPC 970"; break; case POWERPC_EXCP_BOOKE: excp_model = "PowerPC BookE"; break; default: excp_model = "Unknown or invalid"; break; } switch (env->bus_model) { case PPC_FLAGS_INPUT_6xx: bus_model = "PowerPC 6xx"; break; case PPC_FLAGS_INPUT_BookE: bus_model = "PowerPC BookE"; break; case PPC_FLAGS_INPUT_405: bus_model = "PowerPC 405"; break; case PPC_FLAGS_INPUT_970: bus_model = "PowerPC 970"; break; case PPC_FLAGS_INPUT_401: bus_model = "PowerPC 401/403"; break; default: bus_model = "Unknown or invalid"; break; } printf("PowerPC %-12s : PVR %08x MSR %016" PRIx64 "\n" " MMU model : %s\n", def->name, def->pvr, def->msr_mask, mmu_model); if (env->tlb != NULL) { printf(" %d %s TLB in %d ways\n", env->nb_tlb, env->id_tlbs ? "splitted" : "merged", env->nb_ways); } printf(" Exceptions model : %s\n" " Bus model : %s\n", excp_model, bus_model); } dump_ppc_insns(env); dump_ppc_sprs(env); fflush(stdout); #endif return 0; }


static char *get_human_readable_size(char *buf, int buf_size, int64_t size) { static const char suffixes[NB_SUFFIXES] = "KMGT"; int64_t base; int i; if (size <= 999) { snprintf(buf, buf_size, "%" PRId64, size); } else { base = 1024; for (i = 0; i < NB_SUFFIXES; i++) { if (size < (10 * base)) { snprintf(buf, buf_size, "%0.1f%c", (double)size / base, suffixes[i]); break; } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { snprintf(buf, buf_size, "%" PRId64 "%c", ((size + (base >> 1)) / base), suffixes[i]); break; } base = base * 1024; } } return buf; }


static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { int ret; BDRVCloopState *s = bs->opaque; qemu_co_mutex_lock(&s->lock); ret = cloop_read(bs, sector_num, buf, nb_sectors); qemu_co_mutex_unlock(&s->lock); return ret; }


static void disas_sparc_insn(DisasContext * dc, unsigned int insn) { unsigned int opc, rs1, rs2, rd; TCGv cpu_src1, cpu_src2; TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32; TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(dc->pc); } opc = GET_FIELD(insn, 0, 1); rd = GET_FIELD(insn, 2, 6); switch (opc) { case 0: /* branches/sethi */ { unsigned int xop = GET_FIELD(insn, 7, 9); int32_t target; switch (xop) { #ifdef TARGET_SPARC64 case 0x1: /* V9 BPcc */ { int cc; target = GET_FIELD_SP(insn, 0, 18); target = sign_extend(target, 19); target <<= 2; cc = GET_FIELD_SP(insn, 20, 21); if (cc == 0) do_branch(dc, target, insn, 0); else if (cc == 2) do_branch(dc, target, insn, 1); else goto illegal_insn; goto jmp_insn; } case 0x3: /* V9 BPr */ { target = GET_FIELD_SP(insn, 0, 13) | (GET_FIELD_SP(insn, 20, 21) << 14); target = sign_extend(target, 16); target <<= 2; cpu_src1 = get_src1(dc, insn); do_branch_reg(dc, target, insn, cpu_src1); goto jmp_insn; } case 0x5: /* V9 FBPcc */ { int cc = GET_FIELD_SP(insn, 20, 21); if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } target = GET_FIELD_SP(insn, 0, 18); target = sign_extend(target, 19); target <<= 2; do_fbranch(dc, target, insn, cc); goto jmp_insn; } #else case 0x7: /* CBN+x */ { goto ncp_insn; } #endif case 0x2: /* BN+x */ { target = GET_FIELD(insn, 10, 31); target = sign_extend(target, 22); target <<= 2; do_branch(dc, target, insn, 0); goto jmp_insn; } case 0x6: /* FBN+x */ { if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } target = GET_FIELD(insn, 10, 31); target = sign_extend(target, 22); target <<= 2; do_fbranch(dc, target, insn, 0); goto jmp_insn; } case 0x4: /* SETHI */ /* Special-case %g0 because that's the canonical nop. */ if (rd) { uint32_t value = GET_FIELD(insn, 10, 31); TCGv t = gen_dest_gpr(dc, rd); tcg_gen_movi_tl(t, value << 10); gen_store_gpr(dc, rd, t); } break; case 0x0: /* UNIMPL */ default: goto illegal_insn; } break; } break; case 1: /*CALL*/ { target_long target = GET_FIELDs(insn, 2, 31) << 2; TCGv o7 = gen_dest_gpr(dc, 15); tcg_gen_movi_tl(o7, dc->pc); gen_store_gpr(dc, 15, o7); target += dc->pc; gen_mov_pc_npc(dc); #ifdef TARGET_SPARC64 if (unlikely(AM_CHECK(dc))) { target &= 0xffffffffULL; } #endif dc->npc = target; } goto jmp_insn; case 2: /* FPU & Logical Operations */ { unsigned int xop = GET_FIELD(insn, 7, 12); if (xop == 0x3a) { /* generate trap */ int cond = GET_FIELD(insn, 3, 6); TCGv_i32 trap; int l1 = -1, mask; if (cond == 0) { /* Trap never. */ break; } save_state(dc); if (cond != 8) { /* Conditional trap. */ DisasCompare cmp; #ifdef TARGET_SPARC64 /* V9 icc/xcc */ int cc = GET_FIELD_SP(insn, 11, 12); if (cc == 0) { gen_compare(&cmp, 0, cond, dc); } else if (cc == 2) { gen_compare(&cmp, 1, cond, dc); } else { goto illegal_insn; } #else gen_compare(&cmp, 0, cond, dc); #endif l1 = gen_new_label(); tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond), cmp.c1, cmp.c2, l1); free_compare(&cmp); } mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) ? UA2005_HTRAP_MASK : V8_TRAP_MASK); /* Don't use the normal temporaries, as they may well have gone out of scope with the branch above. While we're doing that we might as well pre-truncate to 32-bit. */ trap = tcg_temp_new_i32(); rs1 = GET_FIELD_SP(insn, 14, 18); if (IS_IMM) { rs2 = GET_FIELD_SP(insn, 0, 6); if (rs1 == 0) { tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP); /* Signal that the trap value is fully constant. */ mask = 0; } else { TCGv t1 = gen_load_gpr(dc, rs1); tcg_gen_trunc_tl_i32(trap, t1); tcg_gen_addi_i32(trap, trap, rs2); } } else { TCGv t1, t2; rs2 = GET_FIELD_SP(insn, 0, 4); t1 = gen_load_gpr(dc, rs1); t2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(t1, t1, t2); tcg_gen_trunc_tl_i32(trap, t1); } if (mask != 0) { tcg_gen_andi_i32(trap, trap, mask); tcg_gen_addi_i32(trap, trap, TT_TRAP); } gen_helper_raise_exception(cpu_env, trap); tcg_temp_free_i32(trap); if (cond == 8) { /* An unconditional trap ends the TB. */ dc->is_br = 1; goto jmp_insn; } else { /* A conditional trap falls through to the next insn. */ gen_set_label(l1); break; } } else if (xop == 0x28) { rs1 = GET_FIELD(insn, 13, 17); switch(rs1) { case 0: /* rdy */ #ifndef TARGET_SPARC64 case 0x01 ... 0x0e: /* undefined in the SPARCv8 manual, rdy on the microSPARC II */ case 0x0f: /* stbar in the SPARCv8 manual, rdy on the microSPARC II */ case 0x10 ... 0x1f: /* implementation-dependent in the SPARCv8 manual, rdy on the microSPARC II */ /* Read Asr17 */ if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) { TCGv t = gen_dest_gpr(dc, rd); /* Read Asr17 for a Leon3 monoprocessor */ tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1)); gen_store_gpr(dc, rd, t); break; } #endif gen_store_gpr(dc, rd, cpu_y); break; #ifdef TARGET_SPARC64 case 0x2: /* V9 rdccr */ update_psr(dc); gen_helper_rdccr(cpu_dst, cpu_env); gen_store_gpr(dc, rd, cpu_dst); break; case 0x3: /* V9 rdasi */ tcg_gen_ext_i32_tl(cpu_dst, cpu_asi); gen_store_gpr(dc, rd, cpu_dst); break; case 0x4: /* V9 rdtick */ { TCGv_ptr r_tickptr; r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, tick)); gen_helper_tick_get_count(cpu_dst, r_tickptr); tcg_temp_free_ptr(r_tickptr); gen_store_gpr(dc, rd, cpu_dst); } break; case 0x5: /* V9 rdpc */ { TCGv t = gen_dest_gpr(dc, rd); if (unlikely(AM_CHECK(dc))) { tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL); } else { tcg_gen_movi_tl(t, dc->pc); } gen_store_gpr(dc, rd, t); } break; case 0x6: /* V9 rdfprs */ tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs); gen_store_gpr(dc, rd, cpu_dst); break; case 0xf: /* V9 membar */ break; /* no effect */ case 0x13: /* Graphics Status */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_store_gpr(dc, rd, cpu_gsr); break; case 0x16: /* Softint */ tcg_gen_ext_i32_tl(cpu_dst, cpu_softint); gen_store_gpr(dc, rd, cpu_dst); break; case 0x17: /* Tick compare */ gen_store_gpr(dc, rd, cpu_tick_cmpr); break; case 0x18: /* System tick */ { TCGv_ptr r_tickptr; r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, stick)); gen_helper_tick_get_count(cpu_dst, r_tickptr); tcg_temp_free_ptr(r_tickptr); gen_store_gpr(dc, rd, cpu_dst); } break; case 0x19: /* System tick compare */ gen_store_gpr(dc, rd, cpu_stick_cmpr); break; case 0x10: /* Performance Control */ case 0x11: /* Performance Instrumentation Counter */ case 0x12: /* Dispatch Control */ case 0x14: /* Softint set, WO */ case 0x15: /* Softint clear, WO */ #endif default: goto illegal_insn; } #if !defined(CONFIG_USER_ONLY) } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */ #ifndef TARGET_SPARC64 if (!supervisor(dc)) { goto priv_insn; } update_psr(dc); gen_helper_rdpsr(cpu_dst, cpu_env); #else CHECK_IU_FEATURE(dc, HYPV); if (!hypervisor(dc)) goto priv_insn; rs1 = GET_FIELD(insn, 13, 17); switch (rs1) { case 0: // hpstate // gen_op_rdhpstate(); break; case 1: // htstate // gen_op_rdhtstate(); break; case 3: // hintp tcg_gen_mov_tl(cpu_dst, cpu_hintp); break; case 5: // htba tcg_gen_mov_tl(cpu_dst, cpu_htba); break; case 6: // hver tcg_gen_mov_tl(cpu_dst, cpu_hver); break; case 31: // hstick_cmpr tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr); break; default: goto illegal_insn; } #endif gen_store_gpr(dc, rd, cpu_dst); break; } else if (xop == 0x2a) { /* rdwim / V9 rdpr */ if (!supervisor(dc)) goto priv_insn; #ifdef TARGET_SPARC64 rs1 = GET_FIELD(insn, 13, 17); switch (rs1) { case 0: // tpc { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_ld_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tpc)); tcg_temp_free_ptr(r_tsptr); } break; case 1: // tnpc { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_ld_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tnpc)); tcg_temp_free_ptr(r_tsptr); } break; case 2: // tstate { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_ld_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tstate)); tcg_temp_free_ptr(r_tsptr); } break; case 3: // tt { TCGv_ptr r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tt)); tcg_temp_free_ptr(r_tsptr); } break; case 4: // tick { TCGv_ptr r_tickptr; r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, tick)); gen_helper_tick_get_count(cpu_tmp0, r_tickptr); tcg_temp_free_ptr(r_tickptr); } break; case 5: // tba tcg_gen_mov_tl(cpu_tmp0, cpu_tbr); break; case 6: // pstate tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, pstate)); break; case 7: // tl tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, tl)); break; case 8: // pil tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, psrpil)); break; case 9: // cwp gen_helper_rdcwp(cpu_tmp0, cpu_env); break; case 10: // cansave tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, cansave)); break; case 11: // canrestore tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, canrestore)); break; case 12: // cleanwin tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, cleanwin)); break; case 13: // otherwin tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, otherwin)); break; case 14: // wstate tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, wstate)); break; case 16: // UA2005 gl CHECK_IU_FEATURE(dc, GL); tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, gl)); break; case 26: // UA2005 strand status CHECK_IU_FEATURE(dc, HYPV); if (!hypervisor(dc)) goto priv_insn; tcg_gen_mov_tl(cpu_tmp0, cpu_ssr); break; case 31: // ver tcg_gen_mov_tl(cpu_tmp0, cpu_ver); break; case 15: // fq default: goto illegal_insn; } #else tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim); #endif gen_store_gpr(dc, rd, cpu_tmp0); break; } else if (xop == 0x2b) { /* rdtbr / V9 flushw */ #ifdef TARGET_SPARC64 save_state(dc); gen_helper_flushw(cpu_env); #else if (!supervisor(dc)) goto priv_insn; gen_store_gpr(dc, rd, cpu_tbr); #endif break; #endif } else if (xop == 0x34) { /* FPU Operations */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_op_clear_ieee_excp_and_FTT(); rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); xop = GET_FIELD(insn, 18, 26); save_state(dc); switch (xop) { case 0x1: /* fmovs */ cpu_src1_32 = gen_load_fpr_F(dc, rs2); gen_store_fpr_F(dc, rd, cpu_src1_32); break; case 0x5: /* fnegs */ gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs); break; case 0x9: /* fabss */ gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss); break; case 0x29: /* fsqrts */ CHECK_FPU_FEATURE(dc, FSQRT); gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts); break; case 0x2a: /* fsqrtd */ CHECK_FPU_FEATURE(dc, FSQRT); gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd); break; case 0x2b: /* fsqrtq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq); break; case 0x41: /* fadds */ gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds); break; case 0x42: /* faddd */ gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd); break; case 0x43: /* faddq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq); break; case 0x45: /* fsubs */ gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs); break; case 0x46: /* fsubd */ gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd); break; case 0x47: /* fsubq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq); break; case 0x49: /* fmuls */ CHECK_FPU_FEATURE(dc, FMUL); gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls); break; case 0x4a: /* fmuld */ CHECK_FPU_FEATURE(dc, FMUL); gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld); break; case 0x4b: /* fmulq */ CHECK_FPU_FEATURE(dc, FLOAT128); CHECK_FPU_FEATURE(dc, FMUL); gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq); break; case 0x4d: /* fdivs */ gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs); break; case 0x4e: /* fdivd */ gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd); break; case 0x4f: /* fdivq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq); break; case 0x69: /* fsmuld */ CHECK_FPU_FEATURE(dc, FSMULD); gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld); break; case 0x6e: /* fdmulq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq); break; case 0xc4: /* fitos */ gen_fop_FF(dc, rd, rs2, gen_helper_fitos); break; case 0xc6: /* fdtos */ gen_fop_FD(dc, rd, rs2, gen_helper_fdtos); break; case 0xc7: /* fqtos */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos); break; case 0xc8: /* fitod */ gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod); break; case 0xc9: /* fstod */ gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod); break; case 0xcb: /* fqtod */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod); break; case 0xcc: /* fitoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq); break; case 0xcd: /* fstoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq); break; case 0xce: /* fdtoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq); break; case 0xd1: /* fstoi */ gen_fop_FF(dc, rd, rs2, gen_helper_fstoi); break; case 0xd2: /* fdtoi */ gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi); break; case 0xd3: /* fqtoi */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi); break; #ifdef TARGET_SPARC64 case 0x2: /* V9 fmovd */ cpu_src1_64 = gen_load_fpr_D(dc, rs2); gen_store_fpr_D(dc, rd, cpu_src1_64); break; case 0x3: /* V9 fmovq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_move_Q(rd, rs2); break; case 0x6: /* V9 fnegd */ gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd); break; case 0x7: /* V9 fnegq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq); break; case 0xa: /* V9 fabsd */ gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd); break; case 0xb: /* V9 fabsq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq); break; case 0x81: /* V9 fstox */ gen_fop_DF(dc, rd, rs2, gen_helper_fstox); break; case 0x82: /* V9 fdtox */ gen_fop_DD(dc, rd, rs2, gen_helper_fdtox); break; case 0x83: /* V9 fqtox */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox); break; case 0x84: /* V9 fxtos */ gen_fop_FD(dc, rd, rs2, gen_helper_fxtos); break; case 0x88: /* V9 fxtod */ gen_fop_DD(dc, rd, rs2, gen_helper_fxtod); break; case 0x8c: /* V9 fxtoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq); break; #endif default: goto illegal_insn; } } else if (xop == 0x35) { /* FPU Operations */ #ifdef TARGET_SPARC64 int cond; #endif if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_op_clear_ieee_excp_and_FTT(); rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); xop = GET_FIELD(insn, 18, 26); save_state(dc); #ifdef TARGET_SPARC64 #define FMOVR(sz) \ do { \ DisasCompare cmp; \ cond = GET_FIELD_SP(insn, 14, 17); \ cpu_src1 = get_src1(dc, insn); \ gen_compare_reg(&cmp, cond, cpu_src1); \ gen_fmov##sz(dc, &cmp, rd, rs2); \ free_compare(&cmp); \ } while (0) if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */ FMOVR(s); break; } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr FMOVR(d); break; } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr CHECK_FPU_FEATURE(dc, FLOAT128); FMOVR(q); break; } #undef FMOVR #endif switch (xop) { #ifdef TARGET_SPARC64 #define FMOVCC(fcc, sz) \ do { \ DisasCompare cmp; \ cond = GET_FIELD_SP(insn, 14, 17); \ gen_fcompare(&cmp, fcc, cond); \ gen_fmov##sz(dc, &cmp, rd, rs2); \ free_compare(&cmp); \ } while (0) case 0x001: /* V9 fmovscc %fcc0 */ FMOVCC(0, s); break; case 0x002: /* V9 fmovdcc %fcc0 */ FMOVCC(0, d); break; case 0x003: /* V9 fmovqcc %fcc0 */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(0, q); break; case 0x041: /* V9 fmovscc %fcc1 */ FMOVCC(1, s); break; case 0x042: /* V9 fmovdcc %fcc1 */ FMOVCC(1, d); break; case 0x043: /* V9 fmovqcc %fcc1 */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(1, q); break; case 0x081: /* V9 fmovscc %fcc2 */ FMOVCC(2, s); break; case 0x082: /* V9 fmovdcc %fcc2 */ FMOVCC(2, d); break; case 0x083: /* V9 fmovqcc %fcc2 */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(2, q); break; case 0x0c1: /* V9 fmovscc %fcc3 */ FMOVCC(3, s); break; case 0x0c2: /* V9 fmovdcc %fcc3 */ FMOVCC(3, d); break; case 0x0c3: /* V9 fmovqcc %fcc3 */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(3, q); break; #undef FMOVCC #define FMOVCC(xcc, sz) \ do { \ DisasCompare cmp; \ cond = GET_FIELD_SP(insn, 14, 17); \ gen_compare(&cmp, xcc, cond, dc); \ gen_fmov##sz(dc, &cmp, rd, rs2); \ free_compare(&cmp); \ } while (0) case 0x101: /* V9 fmovscc %icc */ FMOVCC(0, s); break; case 0x102: /* V9 fmovdcc %icc */ FMOVCC(0, d); break; case 0x103: /* V9 fmovqcc %icc */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(0, q); break; case 0x181: /* V9 fmovscc %xcc */ FMOVCC(1, s); break; case 0x182: /* V9 fmovdcc %xcc */ FMOVCC(1, d); break; case 0x183: /* V9 fmovqcc %xcc */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVCC(1, q); break; #undef FMOVCC #endif case 0x51: /* fcmps, V9 %fcc */ cpu_src1_32 = gen_load_fpr_F(dc, rs1); cpu_src2_32 = gen_load_fpr_F(dc, rs2); gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32); break; case 0x52: /* fcmpd, V9 %fcc */ cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64); break; case 0x53: /* fcmpq, V9 %fcc */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_op_fcmpq(rd & 3); break; case 0x55: /* fcmpes, V9 %fcc */ cpu_src1_32 = gen_load_fpr_F(dc, rs1); cpu_src2_32 = gen_load_fpr_F(dc, rs2); gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32); break; case 0x56: /* fcmped, V9 %fcc */ cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64); break; case 0x57: /* fcmpeq, V9 %fcc */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rs1)); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_op_fcmpeq(rd & 3); break; default: goto illegal_insn; } } else if (xop == 0x2) { TCGv dst = gen_dest_gpr(dc, rd); rs1 = GET_FIELD(insn, 13, 17); if (rs1 == 0) { /* clr/mov shortcut : or %g0, x, y -> mov x, y */ if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_movi_tl(dst, simm); gen_store_gpr(dc, rd, dst); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2 == 0) { tcg_gen_movi_tl(dst, 0); gen_store_gpr(dc, rd, dst); } else { cpu_src2 = gen_load_gpr(dc, rs2); gen_store_gpr(dc, rd, cpu_src2); } } } else { cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_ori_tl(dst, cpu_src1, simm); gen_store_gpr(dc, rd, dst); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2 == 0) { /* mov shortcut: or x, %g0, y -> mov x, y */ gen_store_gpr(dc, rd, cpu_src1); } else { cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_or_tl(dst, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, dst); } } } #ifdef TARGET_SPARC64 } else if (xop == 0x25) { /* sll, V9 sllx */ cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); if (insn & (1 << 12)) { tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f); } else { tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f); } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); } else { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); } tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0); } gen_store_gpr(dc, rd, cpu_dst); } else if (xop == 0x26) { /* srl, V9 srlx */ cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); if (insn & (1 << 12)) { tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f); } else { tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL); tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f); } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0); } else { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL); tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0); } } gen_store_gpr(dc, rd, cpu_dst); } else if (xop == 0x27) { /* sra, V9 srax */ cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); if (insn & (1 << 12)) { tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f); } else { tcg_gen_ext32s_i64(cpu_dst, cpu_src1); tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f); } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); if (insn & (1 << 12)) { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0); } else { tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_ext32s_i64(cpu_dst, cpu_src1); tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0); } } gen_store_gpr(dc, rd, cpu_dst); #endif } else if (xop < 0x36) { if (xop < 0x20) { cpu_src1 = get_src1(dc, insn); cpu_src2 = get_src2(dc, insn); switch (xop & ~0x10) { case 0x0: /* add */ if (xop & 0x10) { gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); dc->cc_op = CC_OP_ADD; } else { tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); } break; case 0x1: /* and */ tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0x2: /* or */ tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0x3: /* xor */ tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0x4: /* sub */ if (xop & 0x10) { gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); dc->cc_op = CC_OP_SUB; } else { tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2); } break; case 0x5: /* andn */ tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0x6: /* orn */ tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0x7: /* xorn */ tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0x8: /* addx, V9 addc */ gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2, (xop & 0x10)); break; #ifdef TARGET_SPARC64 case 0x9: /* V9 mulx */ tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2); break; #endif case 0xa: /* umul */ CHECK_IU_FEATURE(dc, MUL); gen_op_umul(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0xb: /* smul */ CHECK_IU_FEATURE(dc, MUL); gen_op_smul(cpu_dst, cpu_src1, cpu_src2); if (xop & 0x10) { tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); dc->cc_op = CC_OP_LOGIC; } break; case 0xc: /* subx, V9 subc */ gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2, (xop & 0x10)); break; #ifdef TARGET_SPARC64 case 0xd: /* V9 udivx */ gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); break; #endif case 0xe: /* udiv */ CHECK_IU_FEATURE(dc, DIV); if (xop & 0x10) { gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1, cpu_src2); dc->cc_op = CC_OP_DIV; } else { gen_helper_udiv(cpu_dst, cpu_env, cpu_src1, cpu_src2); } break; case 0xf: /* sdiv */ CHECK_IU_FEATURE(dc, DIV); if (xop & 0x10) { gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1, cpu_src2); dc->cc_op = CC_OP_DIV; } else { gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1, cpu_src2); } break; default: goto illegal_insn; } gen_store_gpr(dc, rd, cpu_dst); } else { cpu_src1 = get_src1(dc, insn); cpu_src2 = get_src2(dc, insn); switch (xop) { case 0x20: /* taddcc */ gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD); dc->cc_op = CC_OP_TADD; break; case 0x21: /* tsubcc */ gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB); dc->cc_op = CC_OP_TSUB; break; case 0x22: /* taddcctv */ gen_helper_taddcctv(cpu_dst, cpu_env, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); dc->cc_op = CC_OP_TADDTV; break; case 0x23: /* tsubcctv */ gen_helper_tsubcctv(cpu_dst, cpu_env, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); dc->cc_op = CC_OP_TSUBTV; break; case 0x24: /* mulscc */ update_psr(dc); gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); dc->cc_op = CC_OP_ADD; break; #ifndef TARGET_SPARC64 case 0x25: /* sll */ if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f); } else { /* register */ tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0); } gen_store_gpr(dc, rd, cpu_dst); break; case 0x26: /* srl */ if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f); } else { /* register */ tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0); } gen_store_gpr(dc, rd, cpu_dst); break; case 0x27: /* sra */ if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 20, 31); tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f); } else { /* register */ tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0); } gen_store_gpr(dc, rd, cpu_dst); break; #endif case 0x30: { switch(rd) { case 0: /* wry */ tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff); break; #ifndef TARGET_SPARC64 case 0x01 ... 0x0f: /* undefined in the SPARCv8 manual, nop on the microSPARC II */ case 0x10 ... 0x1f: /* implementation-dependent in the SPARCv8 manual, nop on the microSPARC II */ break; #else case 0x2: /* V9 wrccr */ tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); gen_helper_wrccr(cpu_env, cpu_tmp0); tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); dc->cc_op = CC_OP_FLAGS; break; case 0x3: /* V9 wrasi */ tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff); tcg_gen_trunc_tl_i32(cpu_asi, cpu_tmp0); break; case 0x6: /* V9 wrfprs */ tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0); save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; break; case 0xf: /* V9 sir, nop if user */ #if !defined(CONFIG_USER_ONLY) if (supervisor(dc)) { ; // XXX } #endif break; case 0x13: /* Graphics Status */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2); break; case 0x14: /* Softint set */ if (!supervisor(dc)) goto illegal_insn; tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); gen_helper_set_softint(cpu_env, cpu_tmp0); break; case 0x15: /* Softint clear */ if (!supervisor(dc)) goto illegal_insn; tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); gen_helper_clear_softint(cpu_env, cpu_tmp0); break; case 0x16: /* Softint write */ if (!supervisor(dc)) goto illegal_insn; tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); gen_helper_write_softint(cpu_env, cpu_tmp0); break; case 0x17: /* Tick compare */ #if !defined(CONFIG_USER_ONLY) if (!supervisor(dc)) goto illegal_insn; #endif { TCGv_ptr r_tickptr; tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1, cpu_src2); r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, tick)); gen_helper_tick_set_limit(r_tickptr, cpu_tick_cmpr); tcg_temp_free_ptr(r_tickptr); } break; case 0x18: /* System tick */ #if !defined(CONFIG_USER_ONLY) if (!supervisor(dc)) goto illegal_insn; #endif { TCGv_ptr r_tickptr; tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, stick)); gen_helper_tick_set_count(r_tickptr, cpu_tmp0); tcg_temp_free_ptr(r_tickptr); } break; case 0x19: /* System tick compare */ #if !defined(CONFIG_USER_ONLY) if (!supervisor(dc)) goto illegal_insn; #endif { TCGv_ptr r_tickptr; tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1, cpu_src2); r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, stick)); gen_helper_tick_set_limit(r_tickptr, cpu_stick_cmpr); tcg_temp_free_ptr(r_tickptr); } break; case 0x10: /* Performance Control */ case 0x11: /* Performance Instrumentation Counter */ case 0x12: /* Dispatch Control */ #endif default: goto illegal_insn; } } break; #if !defined(CONFIG_USER_ONLY) case 0x31: /* wrpsr, V9 saved, restored */ { if (!supervisor(dc)) goto priv_insn; #ifdef TARGET_SPARC64 switch (rd) { case 0: gen_helper_saved(cpu_env); break; case 1: gen_helper_restored(cpu_env); break; case 2: /* UA2005 allclean */ case 3: /* UA2005 otherw */ case 4: /* UA2005 normalw */ case 5: /* UA2005 invalw */ // XXX default: goto illegal_insn; } #else tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); gen_helper_wrpsr(cpu_env, cpu_tmp0); tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); dc->cc_op = CC_OP_FLAGS; save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; #endif } break; case 0x32: /* wrwim, V9 wrpr */ { if (!supervisor(dc)) goto priv_insn; tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); #ifdef TARGET_SPARC64 switch (rd) { case 0: // tpc { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_st_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tpc)); tcg_temp_free_ptr(r_tsptr); } break; case 1: // tnpc { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_st_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tnpc)); tcg_temp_free_ptr(r_tsptr); } break; case 2: // tstate { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_st_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tstate)); tcg_temp_free_ptr(r_tsptr); } break; case 3: // tt { TCGv_ptr r_tsptr; r_tsptr = tcg_temp_new_ptr(); gen_load_trap_state_at_tl(r_tsptr, cpu_env); tcg_gen_st32_tl(cpu_tmp0, r_tsptr, offsetof(trap_state, tt)); tcg_temp_free_ptr(r_tsptr); } break; case 4: // tick { TCGv_ptr r_tickptr; r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, tick)); gen_helper_tick_set_count(r_tickptr, cpu_tmp0); tcg_temp_free_ptr(r_tickptr); } break; case 5: // tba tcg_gen_mov_tl(cpu_tbr, cpu_tmp0); break; case 6: // pstate save_state(dc); gen_helper_wrpstate(cpu_env, cpu_tmp0); dc->npc = DYNAMIC_PC; break; case 7: // tl save_state(dc); tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, tl)); dc->npc = DYNAMIC_PC; break; case 8: // pil gen_helper_wrpil(cpu_env, cpu_tmp0); break; case 9: // cwp gen_helper_wrcwp(cpu_env, cpu_tmp0); break; case 10: // cansave tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, cansave)); break; case 11: // canrestore tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, canrestore)); break; case 12: // cleanwin tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, cleanwin)); break; case 13: // otherwin tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, otherwin)); break; case 14: // wstate tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, wstate)); break; case 16: // UA2005 gl CHECK_IU_FEATURE(dc, GL); tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, gl)); break; case 26: // UA2005 strand status CHECK_IU_FEATURE(dc, HYPV); if (!hypervisor(dc)) goto priv_insn; tcg_gen_mov_tl(cpu_ssr, cpu_tmp0); break; default: goto illegal_insn; } #else tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0); if (dc->def->nwindows != 32) { tcg_gen_andi_tl(cpu_wim, cpu_wim, (1 << dc->def->nwindows) - 1); } #endif } break; case 0x33: /* wrtbr, UA2005 wrhpr */ { #ifndef TARGET_SPARC64 if (!supervisor(dc)) goto priv_insn; tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2); #else CHECK_IU_FEATURE(dc, HYPV); if (!hypervisor(dc)) goto priv_insn; tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); switch (rd) { case 0: // hpstate // XXX gen_op_wrhpstate(); save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); dc->is_br = 1; break; case 1: // htstate // XXX gen_op_wrhtstate(); break; case 3: // hintp tcg_gen_mov_tl(cpu_hintp, cpu_tmp0); break; case 5: // htba tcg_gen_mov_tl(cpu_htba, cpu_tmp0); break; case 31: // hstick_cmpr { TCGv_ptr r_tickptr; tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0); r_tickptr = tcg_temp_new_ptr(); tcg_gen_ld_ptr(r_tickptr, cpu_env, offsetof(CPUSPARCState, hstick)); gen_helper_tick_set_limit(r_tickptr, cpu_hstick_cmpr); tcg_temp_free_ptr(r_tickptr); } break; case 6: // hver readonly default: goto illegal_insn; } #endif } break; #endif #ifdef TARGET_SPARC64 case 0x2c: /* V9 movcc */ { int cc = GET_FIELD_SP(insn, 11, 12); int cond = GET_FIELD_SP(insn, 14, 17); DisasCompare cmp; TCGv dst; if (insn & (1 << 18)) { if (cc == 0) { gen_compare(&cmp, 0, cond, dc); } else if (cc == 2) { gen_compare(&cmp, 1, cond, dc); } else { goto illegal_insn; } } else { gen_fcompare(&cmp, cc, cond); } /* The get_src2 above loaded the normal 13-bit immediate field, not the 11-bit field we have in movcc. But it did handle the reg case. */ if (IS_IMM) { simm = GET_FIELD_SPs(insn, 0, 10); tcg_gen_movi_tl(cpu_src2, simm); } dst = gen_load_gpr(dc, rd); tcg_gen_movcond_tl(cmp.cond, dst, cmp.c1, cmp.c2, cpu_src2, dst); free_compare(&cmp); gen_store_gpr(dc, rd, dst); break; } case 0x2d: /* V9 sdivx */ gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); break; case 0x2e: /* V9 popc */ gen_helper_popc(cpu_dst, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); break; case 0x2f: /* V9 movr */ { int cond = GET_FIELD_SP(insn, 10, 12); DisasCompare cmp; TCGv dst; gen_compare_reg(&cmp, cond, cpu_src1); /* The get_src2 above loaded the normal 13-bit immediate field, not the 10-bit field we have in movr. But it did handle the reg case. */ if (IS_IMM) { simm = GET_FIELD_SPs(insn, 0, 9); tcg_gen_movi_tl(cpu_src2, simm); } dst = gen_load_gpr(dc, rd); tcg_gen_movcond_tl(cmp.cond, dst, cmp.c1, cmp.c2, cpu_src2, dst); free_compare(&cmp); gen_store_gpr(dc, rd, dst); break; } #endif default: goto illegal_insn; } } } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */ #ifdef TARGET_SPARC64 int opf = GET_FIELD_SP(insn, 5, 13); rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } switch (opf) { case 0x000: /* VIS I edge8cc */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x001: /* VIS II edge8n */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x002: /* VIS I edge8lcc */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x003: /* VIS II edge8ln */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x004: /* VIS I edge16cc */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x005: /* VIS II edge16n */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x006: /* VIS I edge16lcc */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x007: /* VIS II edge16ln */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x008: /* VIS I edge32cc */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x009: /* VIS II edge32n */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x00a: /* VIS I edge32lcc */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x00b: /* VIS II edge32ln */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x010: /* VIS I array8 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); gen_store_gpr(dc, rd, cpu_dst); break; case 0x012: /* VIS I array16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); tcg_gen_shli_i64(cpu_dst, cpu_dst, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x014: /* VIS I array32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); tcg_gen_shli_i64(cpu_dst, cpu_dst, 2); gen_store_gpr(dc, rd, cpu_dst); break; case 0x018: /* VIS I alignaddr */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0); gen_store_gpr(dc, rd, cpu_dst); break; case 0x01a: /* VIS I alignaddrl */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1); gen_store_gpr(dc, rd, cpu_dst); break; case 0x019: /* VIS II bmask */ CHECK_FPU_FEATURE(dc, VIS2); cpu_src1 = gen_load_gpr(dc, rs1); cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32); gen_store_gpr(dc, rd, cpu_dst); break; case 0x020: /* VIS I fcmple16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x022: /* VIS I fcmpne16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x024: /* VIS I fcmple32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x026: /* VIS I fcmpne32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x028: /* VIS I fcmpgt16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x02a: /* VIS I fcmpeq16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x02c: /* VIS I fcmpgt32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x02e: /* VIS I fcmpeq32 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); cpu_src2_64 = gen_load_fpr_D(dc, rs2); gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64); gen_store_gpr(dc, rd, cpu_dst); break; case 0x031: /* VIS I fmul8x16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16); break; case 0x033: /* VIS I fmul8x16au */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au); break; case 0x035: /* VIS I fmul8x16al */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al); break; case 0x036: /* VIS I fmul8sux16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16); break; case 0x037: /* VIS I fmul8ulx16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16); break; case 0x038: /* VIS I fmuld8sux16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16); break; case 0x039: /* VIS I fmuld8ulx16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16); break; case 0x03a: /* VIS I fpack32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32); break; case 0x03b: /* VIS I fpack16 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs2); cpu_dst_32 = gen_dest_fpr_F(dc); gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x03d: /* VIS I fpackfix */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs2); cpu_dst_32 = gen_dest_fpr_F(dc); gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x03e: /* VIS I pdist */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist); break; case 0x048: /* VIS I faligndata */ CHECK_FPU_FEATURE(dc, VIS1); gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata); break; case 0x04b: /* VIS I fpmerge */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge); break; case 0x04c: /* VIS II bshuffle */ CHECK_FPU_FEATURE(dc, VIS2); gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle); break; case 0x04d: /* VIS I fexpand */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand); break; case 0x050: /* VIS I fpadd16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16); break; case 0x051: /* VIS I fpadd16s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s); break; case 0x052: /* VIS I fpadd32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32); break; case 0x053: /* VIS I fpadd32s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32); break; case 0x054: /* VIS I fpsub16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16); break; case 0x055: /* VIS I fpsub16s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s); break; case 0x056: /* VIS I fpsub32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32); break; case 0x057: /* VIS I fpsub32s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32); break; case 0x060: /* VIS I fzero */ CHECK_FPU_FEATURE(dc, VIS1); cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_movi_i64(cpu_dst_64, 0); gen_store_fpr_D(dc, rd, cpu_dst_64); break; case 0x061: /* VIS I fzeros */ CHECK_FPU_FEATURE(dc, VIS1); cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_movi_i32(cpu_dst_32, 0); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x062: /* VIS I fnor */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64); break; case 0x063: /* VIS I fnors */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32); break; case 0x064: /* VIS I fandnot2 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64); break; case 0x065: /* VIS I fandnot2s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32); break; case 0x066: /* VIS I fnot2 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64); break; case 0x067: /* VIS I fnot2s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32); break; case 0x068: /* VIS I fandnot1 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64); break; case 0x069: /* VIS I fandnot1s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32); break; case 0x06a: /* VIS I fnot1 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64); break; case 0x06b: /* VIS I fnot1s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32); break; case 0x06c: /* VIS I fxor */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64); break; case 0x06d: /* VIS I fxors */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32); break; case 0x06e: /* VIS I fnand */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64); break; case 0x06f: /* VIS I fnands */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32); break; case 0x070: /* VIS I fand */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64); break; case 0x071: /* VIS I fands */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32); break; case 0x072: /* VIS I fxnor */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64); break; case 0x073: /* VIS I fxnors */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32); break; case 0x074: /* VIS I fsrc1 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs1); gen_store_fpr_D(dc, rd, cpu_src1_64); break; case 0x075: /* VIS I fsrc1s */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_32 = gen_load_fpr_F(dc, rs1); gen_store_fpr_F(dc, rd, cpu_src1_32); break; case 0x076: /* VIS I fornot2 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64); break; case 0x077: /* VIS I fornot2s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32); break; case 0x078: /* VIS I fsrc2 */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_64 = gen_load_fpr_D(dc, rs2); gen_store_fpr_D(dc, rd, cpu_src1_64); break; case 0x079: /* VIS I fsrc2s */ CHECK_FPU_FEATURE(dc, VIS1); cpu_src1_32 = gen_load_fpr_F(dc, rs2); gen_store_fpr_F(dc, rd, cpu_src1_32); break; case 0x07a: /* VIS I fornot1 */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64); break; case 0x07b: /* VIS I fornot1s */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32); break; case 0x07c: /* VIS I for */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64); break; case 0x07d: /* VIS I fors */ CHECK_FPU_FEATURE(dc, VIS1); gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32); break; case 0x07e: /* VIS I fone */ CHECK_FPU_FEATURE(dc, VIS1); cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_movi_i64(cpu_dst_64, -1); gen_store_fpr_D(dc, rd, cpu_dst_64); break; case 0x07f: /* VIS I fones */ CHECK_FPU_FEATURE(dc, VIS1); cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_movi_i32(cpu_dst_32, -1); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x080: /* VIS I shutdown */ case 0x081: /* VIS II siam */ // XXX goto illegal_insn; default: goto illegal_insn; } #else goto ncp_insn; #endif } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */ #ifdef TARGET_SPARC64 goto illegal_insn; #else goto ncp_insn; #endif #ifdef TARGET_SPARC64 } else if (xop == 0x39) { /* V9 return */ TCGv_i32 r_const; save_state(dc); cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2) { cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2); } else { tcg_gen_mov_tl(cpu_tmp0, cpu_src1); } } gen_helper_restore(cpu_env); gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_tmp0, r_const); tcg_temp_free_i32(r_const); tcg_gen_mov_tl(cpu_npc, cpu_tmp0); dc->npc = DYNAMIC_PC; goto jmp_insn; #endif } else { cpu_src1 = get_src1(dc, insn); if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2) { cpu_src2 = gen_load_gpr(dc, rs2); tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2); } else { tcg_gen_mov_tl(cpu_tmp0, cpu_src1); } } switch (xop) { case 0x38: /* jmpl */ { TCGv t; TCGv_i32 r_const; t = gen_dest_gpr(dc, rd); tcg_gen_movi_tl(t, dc->pc); gen_store_gpr(dc, rd, t); gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_tmp0, r_const); tcg_temp_free_i32(r_const); gen_address_mask(dc, cpu_tmp0); tcg_gen_mov_tl(cpu_npc, cpu_tmp0); dc->npc = DYNAMIC_PC; } goto jmp_insn; #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) case 0x39: /* rett, V9 return */ { TCGv_i32 r_const; if (!supervisor(dc)) goto priv_insn; gen_mov_pc_npc(dc); r_const = tcg_const_i32(3); gen_helper_check_align(cpu_env, cpu_tmp0, r_const); tcg_temp_free_i32(r_const); tcg_gen_mov_tl(cpu_npc, cpu_tmp0); dc->npc = DYNAMIC_PC; gen_helper_rett(cpu_env); } goto jmp_insn; #endif case 0x3b: /* flush */ if (!((dc)->def->features & CPU_FEATURE_FLUSH)) goto unimp_flush; /* nop */ break; case 0x3c: /* save */ save_state(dc); gen_helper_save(cpu_env); gen_store_gpr(dc, rd, cpu_tmp0); break; case 0x3d: /* restore */ save_state(dc); gen_helper_restore(cpu_env); gen_store_gpr(dc, rd, cpu_tmp0); break; #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) case 0x3e: /* V9 done/retry */ { switch (rd) { case 0: if (!supervisor(dc)) goto priv_insn; dc->npc = DYNAMIC_PC; dc->pc = DYNAMIC_PC; gen_helper_done(cpu_env); goto jmp_insn; case 1: if (!supervisor(dc)) goto priv_insn; dc->npc = DYNAMIC_PC; dc->pc = DYNAMIC_PC; gen_helper_retry(cpu_env); goto jmp_insn; default: goto illegal_insn; } } break; #endif default: goto illegal_insn; } } break; } break; case 3: /* load/store instructions */ { unsigned int xop = GET_FIELD(insn, 7, 12); /* ??? gen_address_mask prevents us from using a source register directly. Always generate a temporary. */ TCGv cpu_addr = get_temp_tl(dc); tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn)); if (xop == 0x3c || xop == 0x3e) { /* V9 casa/casxa : no offset */ } else if (IS_IMM) { /* immediate */ simm = GET_FIELDs(insn, 19, 31); if (simm != 0) { tcg_gen_addi_tl(cpu_addr, cpu_addr, simm); } } else { /* register */ rs2 = GET_FIELD(insn, 27, 31); if (rs2 != 0) { tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2)); } } if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || (xop > 0x17 && xop <= 0x1d ) || (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { TCGv cpu_val = gen_dest_gpr(dc, rd); switch (xop) { case 0x0: /* ld, V9 lduw, load unsigned word */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx); break; case 0x1: /* ldub, load unsigned byte */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx); break; case 0x2: /* lduh, load unsigned halfword */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx); break; case 0x3: /* ldd, load double word */ if (rd & 1) goto illegal_insn; else { TCGv_i32 r_const; TCGv_i64 t64; save_state(dc); r_const = tcg_const_i32(7); /* XXX remove alignment check */ gen_helper_check_align(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); gen_address_mask(dc, cpu_addr); t64 = tcg_temp_new_i64(); tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx); tcg_gen_trunc_i64_tl(cpu_tmp0, t64); tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL); gen_store_gpr(dc, rd + 1, cpu_tmp0); tcg_gen_shri_i64(t64, t64, 32); tcg_gen_trunc_i64_tl(cpu_val, t64); tcg_temp_free_i64(t64); tcg_gen_andi_tl(cpu_val, cpu_val, 0xffffffffULL); } break; case 0x9: /* ldsb, load signed byte */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); break; case 0xa: /* ldsh, load signed halfword */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx); break; case 0xd: /* ldstub -- XXX: should be atomically */ { TCGv r_const; gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); r_const = tcg_const_tl(0xff); tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx); tcg_temp_free(r_const); } break; case 0x0f: /* swap, swap register with memory. Also atomically */ CHECK_IU_FEATURE(dc, SWAP); cpu_src1 = gen_load_gpr(dc, rd); gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); tcg_gen_qemu_st32(cpu_src1, cpu_addr, dc->mem_idx); tcg_gen_mov_tl(cpu_val, cpu_tmp0); break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) case 0x10: /* lda, V9 lduwa, load word alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0); break; case 0x11: /* lduba, load unsigned byte alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0); break; case 0x12: /* lduha, load unsigned halfword alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0); break; case 0x13: /* ldda, load double word alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif if (rd & 1) goto illegal_insn; save_state(dc); gen_ldda_asi(dc, cpu_val, cpu_addr, insn, rd); goto skip_move; case 0x19: /* ldsba, load signed byte alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1); break; case 0x1a: /* ldsha, load signed halfword alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1); break; case 0x1d: /* ldstuba -- XXX: should be atomically */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_ldstub_asi(cpu_val, cpu_addr, insn); break; case 0x1f: /* swapa, swap reg with alt. memory. Also atomically */ CHECK_IU_FEATURE(dc, SWAP); #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); cpu_src1 = gen_load_gpr(dc, rd); gen_swap_asi(cpu_val, cpu_src1, cpu_addr, insn); break; #ifndef TARGET_SPARC64 case 0x30: /* ldc */ case 0x31: /* ldcsr */ case 0x33: /* lddc */ goto ncp_insn; #endif #endif #ifdef TARGET_SPARC64 case 0x08: /* V9 ldsw */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx); break; case 0x0b: /* V9 ldx */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x18: /* V9 ldswa */ save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1); break; case 0x1b: /* V9 ldxa */ save_state(dc); gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0); break; case 0x2d: /* V9 prefetch, no effect */ goto skip_move; case 0x30: /* V9 ldfa */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc); gen_ldf_asi(cpu_addr, insn, 4, rd); gen_update_fprs_dirty(rd); goto skip_move; case 0x33: /* V9 lddfa */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc); gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd)); gen_update_fprs_dirty(DFPREG(rd)); goto skip_move; case 0x3d: /* V9 prefetcha, no effect */ goto skip_move; case 0x32: /* V9 ldqfa */ CHECK_FPU_FEATURE(dc, FLOAT128); if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc); gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd)); gen_update_fprs_dirty(QFPREG(rd)); goto skip_move; #endif default: goto illegal_insn; } gen_store_gpr(dc, rd, cpu_val); #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) skip_move: ; #endif } else if (xop >= 0x20 && xop < 0x24) { if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc); switch (xop) { case 0x20: /* ldf, load fpreg */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); cpu_dst_32 = gen_dest_fpr_F(dc); tcg_gen_trunc_tl_i32(cpu_dst_32, cpu_tmp0); gen_store_fpr_F(dc, rd, cpu_dst_32); break; case 0x21: /* ldfsr, V9 ldxfsr */ #ifdef TARGET_SPARC64 gen_address_mask(dc, cpu_addr); if (rd == 1) { TCGv_i64 t64 = tcg_temp_new_i64(); tcg_gen_qemu_ld64(t64, cpu_addr, dc->mem_idx); gen_helper_ldxfsr(cpu_env, t64); tcg_temp_free_i64(t64); break; } #endif { TCGv_i32 t32 = get_temp_i32(dc); tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); tcg_gen_trunc_tl_i32(t32, cpu_tmp0); gen_helper_ldfsr(cpu_env, t32); } break; case 0x22: /* ldqf, load quad fpreg */ { TCGv_i32 r_const; CHECK_FPU_FEATURE(dc, FLOAT128); r_const = tcg_const_i32(dc->mem_idx); gen_address_mask(dc, cpu_addr); gen_helper_ldqf(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); gen_op_store_QT0_fpr(QFPREG(rd)); gen_update_fprs_dirty(QFPREG(rd)); } break; case 0x23: /* lddf, load double fpreg */ gen_address_mask(dc, cpu_addr); cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_qemu_ld64(cpu_dst_64, cpu_addr, dc->mem_idx); gen_store_fpr_D(dc, rd, cpu_dst_64); break; default: goto illegal_insn; } } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || xop == 0xe || xop == 0x1e) { TCGv cpu_val = gen_load_gpr(dc, rd); switch (xop) { case 0x4: /* st, store word */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); break; case 0x5: /* stb, store byte */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx); break; case 0x6: /* sth, store halfword */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx); break; case 0x7: /* std, store double word */ if (rd & 1) goto illegal_insn; else { TCGv_i32 r_const; TCGv_i64 t64; TCGv lo; save_state(dc); gen_address_mask(dc, cpu_addr); r_const = tcg_const_i32(7); /* XXX remove alignment check */ gen_helper_check_align(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); lo = gen_load_gpr(dc, rd + 1); t64 = tcg_temp_new_i64(); tcg_gen_concat_tl_i64(t64, lo, cpu_val); tcg_gen_qemu_st64(t64, cpu_addr, dc->mem_idx); tcg_temp_free_i64(t64); } break; #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) case 0x14: /* sta, V9 stwa, store word alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 4); dc->npc = DYNAMIC_PC; break; case 0x15: /* stba, store byte alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 1); dc->npc = DYNAMIC_PC; break; case 0x16: /* stha, store halfword alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 2); dc->npc = DYNAMIC_PC; break; case 0x17: /* stda, store double word alternate */ #ifndef TARGET_SPARC64 if (IS_IMM) goto illegal_insn; if (!supervisor(dc)) goto priv_insn; #endif if (rd & 1) goto illegal_insn; else { save_state(dc); gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd); } break; #endif #ifdef TARGET_SPARC64 case 0x0e: /* V9 stx */ gen_address_mask(dc, cpu_addr); tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x1e: /* V9 stxa */ save_state(dc); gen_st_asi(cpu_val, cpu_addr, insn, 8); dc->npc = DYNAMIC_PC; break; #endif default: goto illegal_insn; } } else if (xop > 0x23 && xop < 0x28) { if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } save_state(dc); switch (xop) { case 0x24: /* stf, store fpreg */ gen_address_mask(dc, cpu_addr); cpu_src1_32 = gen_load_fpr_F(dc, rd); tcg_gen_ext_i32_tl(cpu_tmp0, cpu_src1_32); tcg_gen_qemu_st32(cpu_tmp0, cpu_addr, dc->mem_idx); break; case 0x25: /* stfsr, V9 stxfsr */ { TCGv t = get_temp_tl(dc); tcg_gen_ld_tl(t, cpu_env, offsetof(CPUSPARCState, fsr)); #ifdef TARGET_SPARC64 gen_address_mask(dc, cpu_addr); if (rd == 1) { tcg_gen_qemu_st64(t, cpu_addr, dc->mem_idx); break; } #endif tcg_gen_qemu_st32(t, cpu_addr, dc->mem_idx); } break; case 0x26: #ifdef TARGET_SPARC64 /* V9 stqf, store quad fpreg */ { TCGv_i32 r_const; CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT0(QFPREG(rd)); r_const = tcg_const_i32(dc->mem_idx); gen_address_mask(dc, cpu_addr); gen_helper_stqf(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); } break; #else /* !TARGET_SPARC64 */ /* stdfq, store floating point queue */ #if defined(CONFIG_USER_ONLY) goto illegal_insn; #else if (!supervisor(dc)) goto priv_insn; if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } goto nfq_insn; #endif #endif case 0x27: /* stdf, store double fpreg */ gen_address_mask(dc, cpu_addr); cpu_src1_64 = gen_load_fpr_D(dc, rd); tcg_gen_qemu_st64(cpu_src1_64, cpu_addr, dc->mem_idx); break; default: goto illegal_insn; } } else if (xop > 0x33 && xop < 0x3f) { save_state(dc); switch (xop) { #ifdef TARGET_SPARC64 case 0x34: /* V9 stfa */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_stf_asi(cpu_addr, insn, 4, rd); break; case 0x36: /* V9 stqfa */ { TCGv_i32 r_const; CHECK_FPU_FEATURE(dc, FLOAT128); if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } r_const = tcg_const_i32(7); gen_helper_check_align(cpu_env, cpu_addr, r_const); tcg_temp_free_i32(r_const); gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd)); } break; case 0x37: /* V9 stdfa */ if (gen_trap_ifnofpu(dc)) { goto jmp_insn; } gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); break; case 0x3c: /* V9 casa */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); break; case 0x3e: /* V9 casxa */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd); break; #else case 0x34: /* stc */ case 0x35: /* stcsr */ case 0x36: /* stdcq */ case 0x37: /* stdc */ goto ncp_insn; #endif default: goto illegal_insn; } } else { goto illegal_insn; } } break; } /* default case for non jump instructions */ if (dc->npc == DYNAMIC_PC) { dc->pc = DYNAMIC_PC; gen_op_next_insn(); } else if (dc->npc == JUMP_PC) { /* we can do a static jump */ gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); dc->is_br = 1; } else { dc->pc = dc->npc; dc->npc = dc->npc + 4; } jmp_insn: goto egress; illegal_insn: { TCGv_i32 r_const; save_state(dc); r_const = tcg_const_i32(TT_ILL_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); dc->is_br = 1; } goto egress; unimp_flush: { TCGv_i32 r_const; save_state(dc); r_const = tcg_const_i32(TT_UNIMP_FLUSH); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); dc->is_br = 1; } goto egress; #if !defined(CONFIG_USER_ONLY) priv_insn: { TCGv_i32 r_const; save_state(dc); r_const = tcg_const_i32(TT_PRIV_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free_i32(r_const); dc->is_br = 1; } goto egress; #endif nfpu_insn: save_state(dc); gen_op_fpexception_im(FSR_FTT_UNIMPFPOP); dc->is_br = 1; goto egress; #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) nfq_insn: save_state(dc); gen_op_fpexception_im(FSR_FTT_SEQ_ERROR); dc->is_br = 1; goto egress; #endif #ifndef TARGET_SPARC64 ncp_insn: { TCGv r_const; save_state(dc); r_const = tcg_const_i32(TT_NCP_INSN); gen_helper_raise_exception(cpu_env, r_const); tcg_temp_free(r_const); dc->is_br = 1; } goto egress; #endif egress: if (dc->n_t32 != 0) { int i; for (i = dc->n_t32 - 1; i >= 0; --i) { tcg_temp_free_i32(dc->t32[i]); } dc->n_t32 = 0; } if (dc->n_ttl != 0) { int i; for (i = dc->n_ttl - 1; i >= 0; --i) { tcg_temp_free(dc->ttl[i]); } dc->n_ttl = 0; } }


int use_gdb_syscalls(void) { if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED : GDB_SYS_DISABLED); } return gdb_syscall_mode == GDB_SYS_ENABLED; }


static void s390_hot_add_cpu(const int64_t id, Error **errp) { MachineState *machine = MACHINE(qdev_get_machine()); s390x_new_cpu(machine->cpu_model, id, errp); }


static bool virtio_pci_modern_state_needed(void *opaque) { VirtIOPCIProxy *proxy = opaque; return !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN); }


static int on2avc_decode_band_types(On2AVCContext *c, GetBitContext *gb) { int bits_per_sect = c->is_long ? 5 : 3; int esc_val = (1 << bits_per_sect) - 1; int num_bands = c->num_bands * c->num_windows; int band = 0, i, band_type, run_len, run; while (band < num_bands) { band_type = get_bits(gb, 4); run_len = 1; do { run = get_bits(gb, bits_per_sect); run_len += run; } while (run == esc_val); if (band + run_len > num_bands) { av_log(c->avctx, AV_LOG_ERROR, "Invalid band type run\n"); return AVERROR_INVALIDDATA; } for (i = band; i < band + run_len; i++) { c->band_type[i] = band_type; c->band_run_end[i] = band + run_len; } band += run_len; } return 0; }


static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band, float *bits, float lambda) { int i, b = 0; uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; const int band_size = ff_celt_freq_range[band] << f->size; float buf[176 * 2], lowband_scratch[176], norm1[176], norm2[176]; float dist, cost, err_x = 0.0f, err_y = 0.0f; float *X = buf; float *X_orig = f->block[0].coeffs + (ff_celt_freq_bands[band] << f->size); float *Y = (f->channels == 2) ? &buf[176] : NULL; float *Y_orig = f->block[1].coeffs + (ff_celt_freq_bands[band] << f->size); OPUS_RC_CHECKPOINT_SPAWN(rc); memcpy(X, X_orig, band_size*sizeof(float)); if (Y) memcpy(Y, Y_orig, band_size*sizeof(float)); f->remaining2 = ((f->framebits << 3) - f->anticollapse_needed) - opus_rc_tell_frac(rc) - 1; if (band <= f->coded_bands - 1) { int curr_balance = f->remaining / FFMIN(3, f->coded_bands - band); b = av_clip_uintp2(FFMIN(f->remaining2 + 1, f->pulses[band] + curr_balance), 14); } if (f->dual_stereo) { pvq->quant_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); pvq->quant_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); } else { pvq->quant_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); } for (i = 0; i < band_size; i++) { err_x += (X[i] - X_orig[i])*(X[i] - X_orig[i]); if (Y) err_y += (Y[i] - Y_orig[i])*(Y[i] - Y_orig[i]); } dist = sqrtf(err_x) + sqrtf(err_y); cost = OPUS_RC_CHECKPOINT_BITS(rc)/8.0f; *bits += cost; OPUS_RC_CHECKPOINT_ROLLBACK(rc); return lambda*dist*cost; }


static int mpegts_read_header(AVFormatContext *s) { MpegTSContext *ts = s->priv_data; AVIOContext *pb = s->pb; uint8_t buf[8 * 1024] = {0}; int len; int64_t pos, probesize = #if AV_HAVE_INCOMPATIBLE_LIBAV_ABI s->probesize ? s->probesize : s->probesize2; #else s->probesize; #endif if (ffio_ensure_seekback(pb, probesize) < 0) av_log(s, AV_LOG_WARNING, "Failed to allocate buffers for seekback\n"); /* read the first 8192 bytes to get packet size */ pos = avio_tell(pb); len = avio_read(pb, buf, sizeof(buf)); ts->raw_packet_size = get_packet_size(buf, len); if (ts->raw_packet_size <= 0) { av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n"); ts->raw_packet_size = TS_PACKET_SIZE; } ts->stream = s; ts->auto_guess = 0; if (s->iformat == &ff_mpegts_demuxer) { /* normal demux */ /* first do a scan to get all the services */ seek_back(s, pb, pos); mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); handle_packets(ts, probesize / ts->raw_packet_size); /* if could not find service, enable auto_guess */ ts->auto_guess = 1; av_log(ts->stream, AV_LOG_TRACE, "tuning done\n"); s->ctx_flags |= AVFMTCTX_NOHEADER; } else { AVStream *st; int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l; int64_t pcrs[2], pcr_h; int packet_count[2]; uint8_t packet[TS_PACKET_SIZE]; const uint8_t *data; /* only read packets */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 60, 1, 27000000); st->codec->codec_type = AVMEDIA_TYPE_DATA; st->codec->codec_id = AV_CODEC_ID_MPEG2TS; /* we iterate until we find two PCRs to estimate the bitrate */ pcr_pid = -1; nb_pcrs = 0; nb_packets = 0; for (;;) { ret = read_packet(s, packet, ts->raw_packet_size, &data); if (ret < 0) return ret; pid = AV_RB16(data + 1) & 0x1fff; if ((pcr_pid == -1 || pcr_pid == pid) && parse_pcr(&pcr_h, &pcr_l, data) == 0) { finished_reading_packet(s, ts->raw_packet_size); pcr_pid = pid; packet_count[nb_pcrs] = nb_packets; pcrs[nb_pcrs] = pcr_h * 300 + pcr_l; nb_pcrs++; if (nb_pcrs >= 2) break; } else { finished_reading_packet(s, ts->raw_packet_size); } nb_packets++; } /* NOTE1: the bitrate is computed without the FEC */ /* NOTE2: it is only the bitrate of the start of the stream */ ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]); ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0]; s->bit_rate = TS_PACKET_SIZE * 8 * 27000000LL / ts->pcr_incr; st->codec->bit_rate = s->bit_rate; st->start_time = ts->cur_pcr; av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%d\n", st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); } seek_back(s, pb, pos); return 0; }


static void apply_tns(float coef[1024], TemporalNoiseShaping *tns, IndividualChannelStream *ics, int decode) { const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb); int w, filt, m, i; int bottom, top, order, start, end, size, inc; float lpc[TNS_MAX_ORDER]; float tmp[TNS_MAX_ORDER]; for (w = 0; w < ics->num_windows; w++) { bottom = ics->num_swb; for (filt = 0; filt < tns->n_filt[w]; filt++) { top = bottom; bottom = FFMAX(0, top - tns->length[w][filt]); order = tns->order[w][filt]; if (order == 0) continue; // tns_decode_coef compute_lpc_coefs(tns->coef[w][filt], order, lpc, 0, 0, 0); start = ics->swb_offset[FFMIN(bottom, mmm)]; end = ics->swb_offset[FFMIN( top, mmm)]; if ((size = end - start) <= 0) continue; if (tns->direction[w][filt]) { inc = -1; start = end - 1; } else { inc = 1; } start += w * 128; if (decode) { // ar filter for (m = 0; m < size; m++, start += inc) for (i = 1; i <= FFMIN(m, order); i++) coef[start] -= coef[start - i * inc] * lpc[i - 1]; } else { // ma filter for (m = 0; m < size; m++, start += inc) { tmp[0] = coef[start]; for (i = 1; i <= FFMIN(m, order); i++) coef[start] += tmp[i] * lpc[i - 1]; for (i = order; i > 0; i--) tmp[i] = tmp[i - 1]; } } } } }


void do_info_snapshots(Monitor *mon) { DriveInfo *dinfo; BlockDriverState *bs, *bs1; QEMUSnapshotInfo *sn_tab, *sn; int nb_sns, i; char buf[256]; bs = get_bs_snapshots(); if (!bs) { monitor_printf(mon, "No available block device supports snapshots\n"); return; } monitor_printf(mon, "Snapshot devices:"); QTAILQ_FOREACH(dinfo, &drives, next) { bs1 = dinfo->bdrv; if (bdrv_has_snapshot(bs1)) { if (bs == bs1) monitor_printf(mon, " %s", bdrv_get_device_name(bs1)); } } monitor_printf(mon, "\n"); nb_sns = bdrv_snapshot_list(bs, &sn_tab); if (nb_sns < 0) { monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns); return; } monitor_printf(mon, "Snapshot list (from %s):\n", bdrv_get_device_name(bs)); monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); for(i = 0; i < nb_sns; i++) { sn = &sn_tab[i]; monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn)); } qemu_free(sn_tab); }


static int activate(AVFilterContext *ctx) { PreMultiplyContext *s = ctx->priv; if (s->inplace) { AVFrame *frame = NULL; AVFrame *out = NULL; int ret, status; int64_t pts; if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) { if ((ret = filter_frame(ctx, &out, frame, frame)) < 0) return ret; av_frame_free(&frame); ret = ff_filter_frame(ctx->outputs[0], out); } if (ret < 0) { return ret; } else if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) { ff_outlink_set_status(ctx->outputs[0], status, pts); return 0; } else { if (ff_outlink_frame_wanted(ctx->outputs[0])) ff_inlink_request_frame(ctx->inputs[0]); return 0; } } else { return ff_framesync_activate(&s->fs); } }


int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp) { return -EINVAL; }


static int unix_open(URLContext *h, const char *filename, int flags) { UnixContext *s = h->priv_data; int fd, ret; av_strstart(filename, "unix:", &filename); s->addr.sun_family = AF_UNIX; av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path)); if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0) return ff_neterrno(); if (s->listen) { fd = ff_listen_bind(fd, (struct sockaddr *)&s->addr, sizeof(s->addr), s->timeout, h); if (fd < 0) { ret = fd; goto fail; } } else { ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr, sizeof(s->addr), s->timeout, h, 0); if (ret < 0) goto fail; } s->fd = fd; return 0; fail: if (s->listen && AVUNERROR(ret) != EADDRINUSE) unlink(s->addr.sun_path); if (fd >= 0) closesocket(fd); return ret; }


static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) { gen_set_cpsr(cpsr, 0xffffffff); dead_tmp(cpsr); store_reg(s, 15, pc); s->is_jmp = DISAS_UPDATE; }


static inline void RENAME(rgb16ToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, int width) { int i; assert(src1 == src2); for(i=0; i<width; i++) { int d0= ((uint32_t*)src1)[i]; int dl= (d0&0x07E0F81F); int dh= ((d0>>5)&0x07C0F83F); int dh2= (dh>>11) + (dh<<21); int d= dh2 + dl; int r= d&0x7F; int b= (d>>11)&0x7F; int g= d>>21; dstU[i]= ((2*RU*r + GU*g + 2*BU*b)>>(RGB2YUV_SHIFT+1-2)) + 128; dstV[i]= ((2*RV*r + GV*g + 2*BV*b)>>(RGB2YUV_SHIFT+1-2)) + 128; } }