Fix typo
[qemu/hppa.git] / target-hppa / translate.c
blob27f8d63462398e20553d35127857680a6f26868e
1 /*
2 * HPPA translation
3 *
4 * Copyright (c) 2005-2009 Stuart Brady <stuart.brady@gmail.com>
5 * Copyright (c) 2007 Randolph Chung <tausq@debian.org>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-common.h"
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
37 typedef void (cond_helper)(void);
38 typedef void (load_helper)(void);
39 typedef void (store_helper)(void);
41 #define DYNGEN_OP(op) static inline op;
42 #include "op_stubs.h"
43 #undef DYNGEN_OP
44 #define DYNGEN_OP(op) static inline op {}
45 #include "op_stubs.h"
46 #undef DYNGEN_OP
48 #define DEBUG_DISAS
50 #define DYNAMIC_PC 1 /* dynamic PC value */
51 #define JUMP_PC 2 /* dynamic PC value which takes only two values
52 according to jump_pc[T2] */
54 /* global register indexes */
55 static TCGv_ptr cpu_env;
56 static char cpu_reg_names[
57 10*4 + 22*5 /* GRs */
59 static TCGv cpu_gr[32];
60 static TCGv cpu_sr[8];
61 static TCGv cpu_cr[32];
62 static TCGv cpu_T[3];
64 #include "gen-icount.h"
66 void hppa_translate_init(void)
68 int i;
69 char *p;
71 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
73 p = cpu_reg_names;
75 TCGV_UNUSED(cpu_gr[0]);
76 for (i = 1; i < 32; i++) {
77 sprintf(p, "r%d", i);
78 cpu_gr[i] = tcg_global_mem_new(TCG_AREG0,
79 offsetof(CPUState, gr[i]), p);
80 p += (i < 10) ? 3 : 4;
84 typedef struct DisasContext {
85 target_ulong iaoq[2];
86 target_ulong iasq[2];
87 unsigned int is_br:1;
88 struct TranslationBlock *tb;
89 int mem_idx;
90 } DisasContext;
92 static void disas_hppa_insn(DisasContext * dc);
94 static uint32_t field(uint32_t val, int start, int length)
96 val >>= start;
97 val &= ~(~0 << length);
98 return val;
101 static int32_t field_signext(uint32_t val, int start, int length)
103 val >>= start;
104 if (val & (1 << (length - 1)))
105 val |= ~0 << length;
106 else
107 val &= ~(~0 << length);
108 return val;
111 static int32_t field_lowsignext(uint32_t val, int start, int length)
113 if (val & (1 << start)) {
114 val >>= start + 1;
115 val |= ~0 << (length - 1);
116 } else {
117 val >>= start + 1;
118 val &= ~(~0 << (length - 1));
120 return val;
123 static int32_t signext(uint32_t val, int length)
125 if (val & (1 << (length - 1)))
126 val |= ~0 << length;
127 return val;
130 static uint32_t assemble_12(uint32_t x, uint32_t y)
132 return (y << 11) | ((x & 1) << 10) | ((x >> 1) & ~(~0 << 10));
135 static uint32_t assemble_17(uint32_t x, uint32_t y, uint32_t z)
137 return (z << 16) | (x << 11) | ((y & 1) << 10) | ((y >> 1) & ~(~0 << 10));
140 static uint32_t assemble_21(uint32_t x)
142 return ((x & 1) << 20) |
143 (((x >> 1) & ~(~0 << 11)) << 9) |
144 (((x >> 14) & ~(~0 << 2)) << 7) |
145 (((x >> 16) & ~(~0 << 5)) << 2) |
146 ((x >> 12) & ~(~0 << 2));
149 /* General registers */
150 static inline void gen_movl_reg_TN(int reg, TCGv tn)
152 if (reg == 0)
153 tcg_gen_movi_tl(tn, 0);
154 else
155 tcg_gen_mov_tl(tn, cpu_gr[reg]);
158 static inline void gen_movl_TN_reg(int reg, TCGv tn)
160 if (reg == 0)
161 return;
162 else
163 tcg_gen_mov_tl(cpu_gr[reg], tn);
166 /* Control registers */
167 static inline void gen_movl_cr_TN(int cr, TCGv tn)
169 tcg_gen_mov_tl(tn, cpu_cr[cr]);
172 static inline void gen_movl_TN_cr(int cr, TCGv tn)
174 tcg_gen_mov_tl(cpu_cr[cr], tn);
177 /* Space registers */
178 static inline void gen_movl_sr_TN(int sr, TCGv tn)
180 tcg_gen_mov_tl(tn, cpu_sr[sr]);
183 static inline void gen_movl_TN_sr(int sr, TCGv tn)
185 tcg_gen_mov_tl(cpu_sr[sr], tn);
188 static void gen_goto_tb(DisasContext *dc, int tb_num,
189 target_ulong pc, target_ulong npc)
191 TranslationBlock *tb;
192 tb = dc->tb;
193 if ((tb->pc & TARGET_PAGE_MASK) == (pc & TARGET_PAGE_MASK)) {
194 tcg_gen_goto_tb(tb_num);
195 gen_op_save_pc(pc, npc);
196 tcg_gen_exit_tb((long)tb + tb_num);
197 } else {
198 gen_op_save_pc(pc, npc);
199 tcg_gen_exit_tb(0);
203 static void gen_branch(DisasContext *dc, long tb,
204 target_ulong pc, target_ulong npc)
206 gen_goto_tb(dc, tb, pc, npc);
209 /* T0 == opd1, T1 == opd2 */
210 static cond_helper * const gen_cond_add[8] = {
211 gen_op_eval_never,
212 gen_op_eval_add_eq,
213 gen_op_eval_add_slt,
214 gen_op_eval_add_slteq,
215 gen_op_eval_add_nuv,
216 gen_op_eval_add_znv,
217 gen_op_eval_add_sv,
218 gen_op_eval_add_od,
221 /* T0 == opd1, T1 == opd2 */
222 static cond_helper * const gen_cond_sub[8] = {
223 gen_op_eval_never,
224 gen_op_eval_sub_eq,
225 gen_op_eval_sub_slt,
226 gen_op_eval_sub_slteq,
227 gen_op_eval_sub_ult,
228 gen_op_eval_sub_ulteq,
229 gen_op_eval_sub_sv,
230 gen_op_eval_sub_od,
233 /* T0 == opd1, T1 == opd2 */
234 static cond_helper * const gen_cond_addc[8] = {
235 gen_op_eval_never,
236 gen_op_eval_addc_eq,
237 gen_op_eval_addc_slt,
238 gen_op_eval_addc_slteq,
239 gen_op_eval_addc_nuv,
240 gen_op_eval_addc_znv,
241 gen_op_eval_addc_sv,
242 gen_op_eval_addc_od,
245 /* T0 == opd1, T1 == opd2 */
246 static cond_helper * const gen_cond_subb[8] = {
247 gen_op_eval_never,
248 gen_op_eval_subb_eq,
249 gen_op_eval_subb_slt,
250 gen_op_eval_subb_slteq,
251 gen_op_eval_subb_ult,
252 gen_op_eval_subb_ulteq,
253 gen_op_eval_subb_sv,
254 gen_op_eval_subb_od,
257 /* T0 == res */
258 static cond_helper * const gen_cond_log[8] = {
259 gen_op_eval_never,
260 gen_op_eval_log_eq,
261 gen_op_eval_log_slt,
262 gen_op_eval_log_slteq,
263 gen_op_eval_never, /* undefined */
264 gen_op_eval_never, /* undefined */
265 gen_op_eval_never, /* undefined */
266 gen_op_eval_log_od,
269 /* T0 == res */
270 static cond_helper * const gen_cond_unit[8] = {
271 gen_op_eval_never,
272 gen_op_eval_never, /* undefined */
273 gen_op_eval_unit_sbz,
274 gen_op_eval_unit_shz,
275 gen_op_eval_unit_sdc,
276 gen_op_eval_never, /* undefined */
277 gen_op_eval_unit_sbc,
278 gen_op_eval_unit_shc,
281 /* T0 == res, T2 == carry */
282 static cond_helper * const gen_cond_sed[8] = {
283 gen_op_eval_never,
284 gen_op_eval_log_eq,
285 gen_op_eval_log_slt,
286 gen_op_eval_log_od,
287 gen_op_eval_always,
288 gen_op_eval_log_neq,
289 gen_op_eval_log_sgteq,
290 gen_op_eval_log_ev,
293 static void gen_branch_cond(DisasContext *dc, long tb, target_ulong disp,
294 int n, int f)
296 int l1;
297 target_ulong target;
298 target = dc->iaoq[0] + disp + 8;
300 l1 = gen_new_label();
302 if (f)
303 gen_op_jnz_T2_label(l1);
304 else
305 gen_op_jz_T2_label(l1);
307 /* taken branch */
308 if (n && ((int32_t)disp >= 0))
309 gen_goto_tb(dc, 0, target, target + 4);
310 else
311 gen_goto_tb(dc, 0, dc->iaoq[1], target);
313 gen_set_label(l1);
315 /* failed branch */
316 if (n && ((int32_t)disp < 0))
317 gen_goto_tb(dc, 1, dc->iaoq[1] + 4, dc->iaoq[1] + 8);
318 else
319 gen_goto_tb(dc, 1, dc->iaoq[1], dc->iaoq[1] + 4);
322 static void gen_nullify_cond(DisasContext *dc, long tb, int f)
324 int l1;
326 l1 = gen_new_label();
328 if (f)
329 gen_op_jnz_T2_label(l1);
330 else
331 gen_op_jz_T2_label(l1);
333 /* nullify */
334 gen_goto_tb(dc, 0, dc->iaoq[1] + 4, dc->iaoq[1] + 8);
336 gen_set_label(l1);
338 /* don't nullify */
339 gen_goto_tb(dc, 1, dc->iaoq[1], dc->iaoq[1] + 4);
341 /* FIXME */
342 dc->is_br = 1;
345 static void save_state(DisasContext *dc)
347 /* XXX */
350 static inline void
351 gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
352 int search_pc)
354 target_ulong pc_start, last_pc;
355 uint16_t *gen_opc_end;
356 CPUBreakpoint *bp;
357 DisasContext dc1, *dc = &dc1;
358 int j, lj = -1;
359 int num_insns;
360 int max_insns;
362 memset(dc, 0, sizeof(DisasContext));
363 dc->tb = tb;
364 pc_start = tb->pc;
365 dc->iaoq[0] = pc_start;
366 dc->iaoq[1] = (target_ulong) tb->cs_base;
367 last_pc = dc->iaoq[0];
368 dc->iasq[0] = dc->iasq[1] = 0; /* FIXME */
369 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
370 num_insns = 0;
371 max_insns = tb->cflags & CF_COUNT_MASK;
372 if (max_insns == 0)
373 max_insns = CF_COUNT_MASK;
375 gen_icount_start();
376 while (!dc->is_br && gen_opc_ptr < gen_opc_end) {
377 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
378 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
379 if (bp->pc == dc->iaoq[0]) {
380 gen_op_save_pc(dc->iaoq[0], dc->iaoq[1]);
381 gen_op_debug();
382 tcg_gen_exit_tb(0);
383 dc->is_br = 1;
384 goto exit_gen_loop;
388 if (search_pc) {
389 qemu_log("Search PC...\n");
390 j = gen_opc_ptr - gen_opc_buf;
391 if (lj < j) {
392 lj++;
393 while (lj < j)
394 gen_opc_instr_start[lj++] = 0;
395 gen_opc_pc[lj] = dc->iaoq[0];
396 gen_opc_instr_start[lj] = 1;
397 gen_opc_icount[lj] = num_insns;
400 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
401 gen_io_start();
402 last_pc = dc->iaoq[0];
403 disas_hppa_insn(dc);
404 num_insns++;
406 if (dc->is_br)
407 break;
408 /* if we reach a page boundary, we stop generation so that the
409 PC of a TT_TFAULT exception is always in the right page */
410 if ((dc->iaoq[0] & (TARGET_PAGE_SIZE - 1)) == 0)
411 break;
412 /* if single step mode, we generate only one instruction and
413 generate an exception */
414 if (env->singlestep_enabled || singlestep)
415 break;
416 if (num_insns >= max_insns)
417 break;
419 if (tb->cflags & CF_LAST_IO)
420 gen_io_end();
421 if (env->singlestep_enabled || singlestep) {
422 gen_op_save_pc(dc->iaoq[0], dc->iaoq[1]);
423 gen_op_debug();
424 tcg_gen_exit_tb(0);
425 } else if (!dc->is_br) {
426 gen_op_save_pc(dc->iaoq[0], dc->iaoq[1]);
427 tcg_gen_exit_tb(0);
430 exit_gen_loop:
431 gen_icount_end(tb, num_insns);
432 *gen_opc_ptr = INDEX_op_end;
433 if (search_pc) {
434 j = gen_opc_ptr - gen_opc_buf;
435 lj++;
436 while (lj <= j)
437 gen_opc_instr_start[lj++] = 0;
438 tb->size = 0;
439 #if 0
440 if (loglevel > 0) {
441 page_dump(logfile);
443 #endif
445 gen_opc_jump_pc[0] = dc->jump_pc[0];
446 gen_opc_jump_pc[1] = dc->jump_pc[1];
448 } else {
449 tb->size = last_pc + 4 - pc_start;
450 tb->icount = num_insns;
452 #ifdef DEBUG_DISAS
453 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
454 qemu_log("--------------\n");
455 qemu_log("IN: %s\n", lookup_symbol(pc_start));
456 log_target_disas(pc_start, last_pc + 4 - pc_start, 0);
457 qemu_log("\n");
459 #endif
462 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
464 gen_intermediate_code_internal(env, tb, 0);
467 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
469 gen_intermediate_code_internal(env, tb, 1);
472 #define LDST_CMPLT_NONE 0
473 #define LDST_CMPLT_S 1
474 #define LDST_CMPLT_SM 2
475 #define LDST_CMPLT_M 3
476 #define LDST_CMPLT_MA 4
477 #define LDST_CMPLT_MB 5
479 static int get_ldst_cmplt(uint32_t insn)
481 int indexed_load = (field(insn, 12, 1) == 0);
482 if (indexed_load) {
483 int u = field(insn, 13, 1);
484 int m = field(insn, 5, 1);
486 if (u == 0 && m == 0)
487 return LDST_CMPLT_NONE;
488 else if (u == 0 && m == 1)
489 return LDST_CMPLT_M;
490 else if (u == 1 && m == 0)
491 return LDST_CMPLT_S;
492 else if (u == 1 && m == 1)
493 return LDST_CMPLT_SM;
494 } else {
495 int a = field(insn, 13, 1);
496 int m = field(insn, 5, 1);
497 uint32_t ext4 = field(insn, 6, 4);
498 target_long im5;
499 if (ext4 <= 7) /* load */
500 im5 = field_signext(insn, 16, 5);
501 else /* store */
502 im5 = field_signext(insn, 0, 5);
504 if (m == 0)
505 return LDST_CMPLT_NONE;
506 else if (a == 0 && m == 1 && im5 != 0)
507 return LDST_CMPLT_MA;
508 else if (a == 1 && m == 1)
509 return LDST_CMPLT_MB;
511 return LDST_CMPLT_NONE;
514 static void gen_load(uint32_t insn, int shift, load_helper *op)
516 int indexed_load = (field(insn, 12, 1) == 0);
517 int cmplt = get_ldst_cmplt(insn);
518 int b = field(insn, 21, 5);
519 int t = field(insn, 0, 5);
521 /* load value at address T0 to T1 */
523 if (indexed_load) {
524 int x = field(insn, 16, 5);
525 switch (cmplt) {
526 case LDST_CMPLT_S:
527 case LDST_CMPLT_SM:
528 gen_movl_reg_TN(x, cpu_T[0]);
529 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], shift);
530 break;
531 case LDST_CMPLT_M:
532 default:
533 gen_movl_reg_TN(x, cpu_T[0]);
534 break;
536 } else {
537 target_long im5 = field_lowsignext(insn, 16, 5);
538 tcg_gen_movi_tl(cpu_T[0], im5);
541 switch (cmplt) {
542 case LDST_CMPLT_MB:
543 /* dx in T0 */
544 gen_movl_reg_TN(b, cpu_T[1]);
545 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]); /* copy dx to T2 */
546 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]); /* T0 = GR[b] + dx */
547 tcg_gen_add_tl(cpu_T[1], cpu_T[2], cpu_T[1]); /* GR[b] += dx */
548 gen_movl_TN_reg(b, cpu_T[1]);
549 break;
550 case LDST_CMPLT_MA:
551 case LDST_CMPLT_M:
552 case LDST_CMPLT_SM:
553 /* dx in T0 */
554 gen_movl_reg_TN(b, cpu_T[1]);
555 tcg_gen_mov_tl(cpu_T[2], cpu_T[1]);
556 tcg_gen_add_tl(cpu_T[1], cpu_T[0], cpu_T[1]); /* GR[b] += dx */
557 gen_movl_TN_reg(b, cpu_T[1]);
558 tcg_gen_mov_tl(cpu_T[0], cpu_T[2]); /* T0 = GR[b] */
559 break;
560 default:
561 /* dx in T0 */
562 gen_movl_reg_TN(b, cpu_T[1]);
563 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]); /* T0 = GR[b] + dx */
564 break;
567 op();
568 gen_movl_TN_reg(t, cpu_T[1]);
571 static void gen_store(uint32_t insn, store_helper *op)
573 target_long im5 = field_lowsignext(insn, 0, 5);
574 int r = field(insn, 16, 5);
575 int b = field(insn, 21, 5);
576 int cmplt = get_ldst_cmplt(insn);
578 /* store T1 at address T0 */
580 tcg_gen_movi_tl(cpu_T[0], im5);
581 switch (cmplt) {
582 case LDST_CMPLT_MB:
583 gen_movl_reg_TN(b, cpu_T[1]);
584 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]); /* T2 = dx */
585 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]); /* offset = GR[b] + dx */
586 tcg_gen_add_tl(cpu_T[1], cpu_T[2], cpu_T[1]); /* GR[b] += dx */
587 gen_movl_TN_reg(b, cpu_T[1]);
588 break;
589 case LDST_CMPLT_MA:
590 gen_movl_reg_TN(b, cpu_T[1]);
591 tcg_gen_mov_tl(cpu_T[2], cpu_T[1]); /* T2 = GR[b] */
592 tcg_gen_add_tl(cpu_T[1], cpu_T[0], cpu_T[1]); /* GR[b] += dx */
593 gen_movl_TN_reg(b, cpu_T[1]);
594 tcg_gen_mov_tl(cpu_T[0], cpu_T[2]); /* offset = GR[b] */
595 break;
596 default:
597 gen_movl_reg_TN(b, cpu_T[1]);
598 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]); /* offset = GR[b] + dx */
599 break;
601 gen_movl_reg_TN(r, cpu_T[1]);
602 op();
606 static void gen_shrpw(uint32_t insn)
608 int r1 = field(insn, 16, 5);
609 int r2 = field(insn, 21, 5);
610 int t = field(insn, 0, 5);
612 gen_movl_reg_TN(r1, cpu_T[1]);
613 gen_movl_reg_TN(r2, cpu_T[2]);
614 gen_op_shrpw_cc();
615 gen_movl_TN_reg(t, cpu_T[0]);
618 static void gen_extrw(uint32_t insn)
620 int r = field(insn, 21, 5);
621 int t = field(insn, 16, 5);
622 int clen = 32 - field(insn, 0, 5);
623 int se = field(insn, 10, 1);
625 tcg_gen_movi_tl(cpu_T[1], clen);
626 gen_movl_reg_TN(r, cpu_T[2]);
627 gen_op_extrw_cc();
628 gen_movl_TN_reg(t, cpu_T[0]);
631 static void gen_depw(uint32_t insn)
633 int t = field(insn, 21, 5);
634 int r = field(insn, 16, 5);
635 int clen = 32 - field(insn, 0, 5);
636 int nz = field(insn, 10, 1);
638 tcg_gen_movi_tl(cpu_T[1], clen);
639 gen_movl_reg_TN(r, cpu_T[2]);
640 gen_op_depw_cc();
641 gen_movl_TN_reg(t, cpu_T[0]);
644 static void gen_depwi(uint32_t insn)
646 int t = field(insn, 21, 5);
647 target_long im5 = field_signext(insn, 16, 5);
648 int clen = 32 - field(insn, 0, 5);
649 int nz = field(insn, 10, 1);
651 tcg_gen_movi_tl(cpu_T[1], clen);
652 tcg_gen_movi_tl(cpu_T[2], im5);
653 gen_op_depw_cc();
654 gen_movl_TN_reg(t, cpu_T[0]);
657 static void disas_hppa_insn(DisasContext * dc)
659 uint32_t insn;
660 int op;
661 int ext6;
663 insn = ldl_code(dc->iaoq[0]);
664 op = field(insn, 26, 6);
666 /* TODO:
667 * traps
668 * signals
669 * spaces
670 * floating point ops
671 * misc ops
672 * refactoring
674 * Mostly done:
675 * branches
676 * nullification
677 * conditions
678 * carry
681 /* Major Opcodes */
682 switch (op) {
683 case 0x00: /* System_op */
685 int ext8;
686 ext8 = field(insn, 5, 8);
687 switch (ext8) {
688 case 0x00: /* BREAK */
689 gen_op_break();
690 break;
692 case 0x20: /* SYNC/SYNCDMA */
693 if (field(insn, 20, 1))
694 gen_op_syncdma();
695 else
696 gen_op_sync();
697 break;
699 case 0x60: /* RFI */
700 gen_op_rfi();
701 dc->is_br = 1;
702 break;
704 case 0x65: /* RFI,R (RFIR) */
705 gen_op_rfi();
706 gen_op_restore_shadow();
707 dc->is_br = 1;
708 break;
710 case 0x6b: /* SSM */
711 gen_op_check_priv0();
712 gen_op_ssm(field(insn, 16, 7));
713 gen_movl_TN_reg(field(insn, 0, 5), cpu_T[0]);
714 break;
716 case 0x73: /* RSM */
717 gen_op_check_priv0();
718 gen_op_rsm(field(insn, 16, 7));
719 gen_movl_TN_reg(field(insn, 0, 5), cpu_T[0]);
720 break;
722 case 0xc3: /* MTSM */
723 gen_op_check_priv0();
724 gen_movl_reg_TN(field(insn, 16, 5), cpu_T[0]);
725 gen_op_mtsm();
726 break;
728 case 0x85: /* LDSID */
730 int s, b, t;
731 s = field(insn, 14, 2);
732 b = field(insn, 21, 5);
733 t = field(insn, 0, 5);
734 break;
737 case 0xc1: /* MTSP */
739 int sr = field(insn, 13, 3);
740 int r = field(insn, 16, 5);
741 gen_movl_reg_TN(r, cpu_T[0]);
742 gen_movl_TN_sr(sr, cpu_T[0]);
743 break;
746 case 0x25: /* MFSP */
748 int sr = field(insn, 13, 3);
749 int t = field(insn, 0, 5);
750 if (sr >= 3)
751 gen_op_check_priv0();
752 gen_movl_sr_TN(sr, cpu_T[0]);
753 gen_movl_TN_reg(t, cpu_T[0]);
754 break;
757 #ifdef TARGET_HPPA64
758 case 0xa5: /* MFIA */
759 break;
760 #endif
762 case 0xc2: /* MTCTL */
764 int t, r;
765 t = field(insn, 21, 5);
766 r = field(insn, 16, 5);
767 if (t >= 1 && t < 7)
768 break;
769 if (t != 11)
770 gen_op_check_priv0();
771 switch (t) {
772 case 0: /* recovery counter */
773 /* TODO: mask 32-bits for 64-bit op */
774 case 14:
775 case 15:
776 case 16:
777 case 24:
778 case 25:
779 case 26:
780 case 27:
781 case 28:
782 case 29:
783 case 30:
784 case 31:
785 case 8: /* PID0 */
786 case 9: /* PID1 */
787 case 12: /* PID2 */
788 case 13: /* PID3 */
789 /* Undefined in PSW[Q] set */
790 case 17:
791 case 18:
792 case 20:
793 case 21:
794 case 22:
795 gen_movl_reg_TN(r, cpu_T[0]);
796 gen_movl_TN_cr(0, cpu_T[0]);
797 break;
799 case 23:
800 gen_movl_cr_TN(23, cpu_T[0]);
801 gen_movl_reg_TN(r, cpu_T[1]);
802 tcg_gen_andc_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
803 gen_movl_TN_cr(23, cpu_T[0]);
804 break;
806 case 10: /* CCR/SCR */
807 case 11: /* SAR - handled differently on 64-bit */
808 gen_movl_reg_TN(r, cpu_T[0]);
809 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
810 gen_movl_TN_cr(10, cpu_T[0]);
811 break;
813 break;
816 #ifdef TARGET_HPPA64
817 case 0xc6: /* MTSARCM */
818 break;
819 #endif
821 case 0x45: /* MFCTL/MFCTL,W */
823 int r, t;
824 r = field(insn, 21, 5);
825 t = field(insn, 0, 5);
826 if (r >= 1 && r < 7)
827 break;
828 if (r != 11 && r != 26 && r != 27)
829 gen_op_check_priv0();
830 if (r == 16) /* interval timer */
831 gen_op_check_int_timer_priv();
833 if ((r >= 17 && r <= 22) || (r == 0)) {
834 gen_movl_cr_TN(r, cpu_T[0]);
835 gen_movl_TN_reg(t, cpu_T[0]);
836 } else if (r == 11) { /* SAR */
837 /* Check - may need to mask and shift */
838 gen_movl_cr_TN(r, cpu_T[0]);
839 gen_movl_TN_reg(t, cpu_T[0]);
840 } else if (r >= 8) {
841 gen_movl_cr_TN(r, cpu_T[0]);
842 gen_movl_TN_reg(t, cpu_T[0]);
844 break;
847 default:
848 gen_op_undef_insn();
849 break;
851 break;
854 case 0x01: /* Mem_Mgmt */
856 int ext5;
857 ext5 = field(insn, 0, 5);
858 if (!field(insn, 12, 1)) {
859 int ext7;
860 ext7 = field(insn, 6, 7);
861 switch (ext7) {
862 case 0x08: /* PITLB */
863 case 0x09: /* PITLBE */
864 case 0x0a: /* FIC,0A (FIC) */
865 case 0x0b: /* FICE */
866 #ifdef TARGET_HPPA64
867 case 0x20: /* IITLBT */
868 case 0x18: /* PITLB,L */
869 #else
870 case 0x01: /* IITLBA */
871 case 0x00: /* IITLBP */
872 #endif
873 break;
875 default:
876 gen_op_undef_insn();
877 break;
879 } else {
880 int ext8;
881 ext8 = field(insn, 6, 8);
883 switch (ext8) {
884 case 0x48: /* PDTLB */
885 case 0x49: /* PDTLBE */
886 case 0x4a: /* FDC (index) */
887 case 0x4b: /* FDCE */
888 case 0x4e: /* PDC */
889 case 0x46: /* PROBE,R (PROBER) */
890 case 0xc6: /* PROBEI,R (PROBERI) */
891 case 0x47: /* PROBE,W (PROBEW) */
892 case 0xc7: /* PROBEI,W (PROBEWI) */
893 case 0x4d: /* LPA */
894 case 0x4c: /* LCI */
895 #ifdef TARGET_HPPA64
896 case 0x60: /* IDTLBT */
897 case 0x58: /* PDTLB,L */
898 case 0xca: /* FDC (imm) */
899 #else
900 case 0x41: /* IDTLBA */
901 case 0x40: /* IDTLBP */
902 #endif
903 break;
905 default:
906 gen_op_undef_insn();
907 break;
910 break;
913 case 0x02: /* Arith/Log */
915 int t, f, c, r1, r2;
916 r2 = field(insn, 21, 5);
917 r1 = field(insn, 16, 5);
918 c = field(insn, 13, 3);
919 f = field(insn, 12, 1);
920 ext6 = field(insn, 6, 6);
921 t = field(insn, 0, 5);
922 gen_movl_reg_TN(r1, cpu_T[0]);
923 gen_movl_reg_TN(r2, cpu_T[1]);
925 /* Opcode Extensions */
926 switch (ext6) {
927 case 0x18: /* ADD */
928 if (c || f)
929 gen_cond_add[c]();
930 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
931 break;
932 case 0x28: /* ADD,L (ADDL) */
933 if (c || f)
934 gen_cond_add[c]();
935 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
936 break;
937 case 0x38: /* ADD,TSV (ADDO) */
938 gen_op_eval_add_sv();
939 /* gen_op_overflow_trap(); */
940 if (c || f)
941 gen_cond_add[c]();
942 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
943 break;
944 case 0x1c: /* ADD,C (ADDC) */
945 if (c || f)
946 gen_cond_addc[c]();
947 gen_helper_addc_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
948 break;
949 case 0x3c: /* ADD,C,TSV (ADDCO) */
950 gen_op_eval_addc_sv();
951 /* gen_op_overflow_trap(); */
952 if (c || f)
953 gen_cond_addc[c]();
954 gen_helper_addc_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
955 break;
956 case 0x19: /* SHLADD (1) (SH1ADD) */
957 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 1);
958 if (c || f)
959 gen_cond_add[c](); /* FIXME */
960 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
961 break;
962 case 0x29: /* SHLADD,L (1) (SH1ADDL) */
963 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 1);
964 if (c || f)
965 gen_cond_add[c]();
966 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
967 break;
968 case 0x39: /* SHLADD,TSV (1) (SH1ADDO) */
969 gen_op_eval_add_sv(); /* FIXME */
970 /* gen_op_overflow_trap(); */
971 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 1);
972 if (c || f)
973 gen_cond_add[c](); /* FIXME */
974 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
975 break;
976 case 0x1a: /* SHLADD (2) (SH2ADD) */
977 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 2);
978 if (c || f)
979 gen_cond_add[c](); /* FIXME */
980 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
981 break;
982 case 0x2a: /* SHLADD,L (2) (SH2ADDL) */
983 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 2);
984 if (c || f)
985 gen_cond_add[c]();
986 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
987 break;
988 case 0x3a: /* SHLADD,TSV (2) (SH2ADDO) */
989 gen_op_eval_add_sv(); /* FIXME */
990 /* gen_op_overflow_trap(); */
991 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 2);
992 if (c || f)
993 gen_cond_add[c](); /* FIXME */
994 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
995 break;
996 case 0x1b: /* SHLADD (3) (SH3ADD) */
997 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 3);
998 if (c || f)
999 gen_cond_add[c](); /* FIXME */
1000 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
1001 break;
1002 case 0x2b: /* SHLADD,L (3) (SH3ADDL) */
1003 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 3);
1004 if (c || f)
1005 gen_cond_add[c]();
1006 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1007 break;
1008 case 0x3b: /* SHLADD,TSV (3) (SH3ADDO) */
1009 gen_op_eval_add_sv(); /* FIXME */
1010 /* gen_op_overflow_trap(); */
1011 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 3);
1012 if (c || f)
1013 gen_cond_add[c](); /* FIXME */
1014 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
1015 break;
1016 case 0x10: /* SUB */
1017 if (c || f)
1018 gen_cond_sub[c]();
1019 gen_op_sub_T1_T0_cc();
1020 break;
1021 case 0x30: /* SUB,TSV (SUBO) */
1022 gen_op_eval_sub_sv();
1023 /* gen_op_overflow_trap(); */
1024 if (c || f)
1025 gen_cond_sub[c]();
1026 gen_op_sub_T1_T0_cc();
1027 break;
1028 case 0x13: /* SUB,TC (SUBT) */
1029 if (c || f)
1030 gen_cond_sub[c]();
1031 /* gen_cond_trap(); */
1032 gen_op_sub_T1_T0_cc();
1033 break;
1034 case 0x33: /* SUB,TSV,TC (SUBTO) */
1035 gen_op_eval_sub_sv();
1036 /* gen_op_overflow_trap(); */
1037 if (c || f)
1038 gen_cond_sub[c]();
1039 /* gen_cond_trap(); */
1040 gen_op_sub_T1_T0_cc();
1041 break;
1042 case 0x14: /* SUB,B (SUBB) */
1043 if (c || f)
1044 gen_cond_subb[c]();
1045 gen_op_subb_T1_T0_cc();
1046 break;
1047 case 0x34: /* SUB,B,TSV (SUBBO) */
1048 gen_op_eval_subb_sv();
1049 /* gen_op_overflow_trap(); */
1050 if (c || f)
1051 gen_cond_subb[c]();
1052 gen_op_subb_T1_T0_cc();
1053 break;
1054 case 0x11: /* DS */
1055 /* if (c || f)
1056 gen_cond_ds[c](); */
1057 gen_op_ds_T1_T0();
1058 break;
1059 case 0x00: /* ANDCM */
1060 tcg_gen_andc_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1061 if (c || f)
1062 gen_cond_log[c]();
1063 break;
1064 case 0x08: /* AND */
1065 tcg_gen_and_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1066 if (c || f)
1067 gen_cond_log[c]();
1068 break;
1069 case 0x09: /* OR */
1070 tcg_gen_or_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1071 if (c || f)
1072 gen_cond_log[c]();
1073 break;
1074 case 0x0a: /* XOR */
1075 tcg_gen_xor_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1076 if (c || f)
1077 gen_cond_log[c]();
1078 break;
1079 case 0x0e: /* UXOR */
1080 gen_op_uxor_T1_T0();
1081 if (c || f)
1082 gen_cond_unit[c]();
1083 break;
1084 case 0x22: /* CMPCLR (COMCLR) */
1085 if (c || f)
1086 gen_cond_sub[c]();
1087 tcg_gen_movi_tl(cpu_T[0], 0);
1088 break;
1089 case 0x26: /* UADDCM */
1090 /* FIXME: 'c' specifies unit size */
1091 gen_op_uaddcm_T1_T0();
1092 if (c || f)
1093 gen_cond_unit[c]();
1094 break;
1095 case 0x27: /* UADDCM,TC (UADDCMT) */
1096 /* FIXME: 'c' specifies unit size */
1097 gen_op_uaddcm_T1_T0();
1098 if (c || f) {
1099 gen_cond_unit[c]();
1100 /* gen_cond_trap(); */
1102 break;
1103 case 0x2e: /* DCOR */
1104 if (r1 != 0)
1105 gen_op_undef_insn();
1106 else {
1107 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
1108 gen_op_dcor_T0();
1110 break;
1111 case 0x2f: /* DCOR,I (IDCOR) */
1112 if (r1 != 0)
1113 gen_op_undef_insn();
1114 else {
1115 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
1116 gen_op_idcor_T0();
1118 break;
1119 #ifdef TARGET_HPPA64
1120 /* Also included in MAX-1 (PA-7100LC and PA-7300LC) */
1121 case 0x0f: /* HADD */
1122 case 0x0d: /* HADD,SS */
1123 case 0x0c: /* HADD,US */
1124 case 0x07: /* HSUB */
1125 case 0x05: /* HSUB,SS */
1126 case 0x04: /* HSUB,US */
1127 case 0x0b: /* HAVG (HAVE) */
1128 case 0x1d: /* HSHLADD (1) (HSL1ADD) */
1129 case 0x1e: /* HSHLADD (2) (HSL2ADD) */
1130 case 0x1f: /* HSHLADD (3) (HSL3ADD) */
1131 case 0x15: /* HSHRADD (1) (HSR1ADD) */
1132 case 0x16: /* HSHRADD (2) (HSR2ADD) */
1133 case 0x17: /* HSHRADD (3) (HSR3ADD) */
1134 break;
1135 #endif
1136 default: /* Undefined Instruction */
1137 gen_op_undef_insn();
1138 break;
1140 gen_movl_TN_reg(t, cpu_T[0]);
1141 if (c || f)
1142 gen_nullify_cond(dc, (long)dc->tb, f);
1143 break;
1146 case 0x03: /* Index_Mem */
1148 int ext4 = field(insn, 6, 4);
1149 switch (ext4) {
1150 /* XXX: gen_op_*_raw only works for user-mode emulation
1151 * we really need gen_load and gen_store to be macros
1152 * to allow _phys and _virtual to be used
1154 case 0x00: /* LDB (index/short) (LDBX/LDBS) */
1155 gen_load(insn, 0, gen_op_ldb_raw);
1156 break;
1157 case 0x01: /* LDH (index/short) (LDHX/LDHS) */
1158 gen_load(insn, 1, gen_op_ldh_raw);
1159 break;
1160 case 0x02: /* LDW (index/short) (LDWX/LDWS) */
1161 gen_load(insn, 2, gen_op_ldw_raw);
1162 break;
1163 case 0x06: /* LDWA (index/short) (LDWAX/LDWAS) */
1164 gen_op_check_priv0();
1165 gen_load(insn, 2, gen_op_ldw_phys);
1166 break;
1167 case 0x07: /* LDCW (index/short) (LDCWX/LDCWS) */
1168 gen_load(insn, 2, gen_op_ldcw_raw);
1169 break;
1170 case 0x08: /* STB (short) (STBS) */
1171 gen_store(insn, gen_op_stb_raw);
1172 break;
1173 case 0x09: /* STH (short) (STHS) */
1174 gen_store(insn, gen_op_sth_raw);
1175 break;
1176 case 0x0a: /* STW (short) (STWS) */
1177 gen_store(insn, gen_op_stw_raw);
1178 break;
1179 case 0x0c: /* STBY (short) (STBYS) */
1180 /* XXX */
1181 break;
1182 case 0x0e: /* STWA (short) (STWAS) */
1183 gen_store(insn, gen_op_stw_phys);
1184 break;
1186 #ifdef TARGET_HPPA64
1187 case 0x03: /* LDD (index/short) */
1188 case 0x04: /* LDDA (index/short) */
1189 case 0x05: /* LDCD (index/short) */
1190 case 0x0b: /* STD (short) */
1191 case 0x0d: /* STDBY (short) */
1192 case 0x0f: /* STDA (short) */
1193 /* XXX - pa20 */
1194 break;
1195 #endif
1197 break;
1200 case 0x04: /* SPOPn */
1201 /* SPOP0 */
1202 /* SPOP1 */
1203 /* SPOP2 */
1204 /* SPOP3 */
1205 break;
1207 case 0x05: /* DIAG */
1208 case 0x06: /* FMPYADD */
1209 break;
1211 case 0x08: /* LDIL */
1213 int t;
1214 target_ulong im21;
1215 t = field(insn, 21, 5);
1216 if (t) {
1217 im21 = assemble_21(field(insn, 0, 21)) << (32 - 21);
1218 tcg_gen_movi_tl(cpu_T[0], im21);
1219 gen_movl_TN_reg(t, cpu_T[0]);
1221 break;
1224 case 0x09: /* Copr_w */
1225 if (!field(insn, 12, 1))
1226 if (!field(insn, 9, 1))
1227 /* CLDW (index) (CLDWX) */ {}
1228 else
1229 /* CSTW (index) (CSTWX) */ {}
1230 else
1231 if (!field(insn, 9, 1))
1232 /* CLDW (short) (CLDWS) */ {}
1233 else
1234 /* CSTW (short) (CSTWS) */ {}
1235 break;
1237 case 0x0a: /* ADDIL */
1239 int r;
1240 target_ulong im21;
1241 r = field(insn, 21, 5);
1242 im21 = assemble_21(field(insn, 0, 21)) << (32 - 21);
1243 gen_movl_reg_TN(r, cpu_T[1]);
1244 tcg_gen_movi_tl(cpu_T[0], im21);
1245 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1246 gen_movl_TN_reg(1, cpu_T[0]);
1247 break;
1250 case 0x0b: /* Copr_dw */
1251 if (!field(insn, 12, 1))
1252 if (!field(insn, 9, 1))
1253 /* CLDD (index) (CLDDX) */ {}
1254 else
1255 /* CSTD (index) (CLTDX) */ {}
1256 else
1257 if (!field(insn, 9, 1))
1258 /* CLDD (short) (CLDDS) */ {}
1259 else
1260 /* CSTD (short) (CSTDS) */ {}
1261 break;
1263 case 0x0c: /* COPR */
1264 break;
1266 case 0x0d: /* LDO - Load Offset */
1268 int b, t;
1269 target_long im14;
1270 b = field(insn, 21, 5);
1271 t = field(insn, 16, 5);
1272 im14 = field_lowsignext(insn, 0, 14);
1273 gen_movl_reg_TN(b, cpu_T[0]);
1274 tcg_gen_movi_tl(cpu_T[1], im14);
1275 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1276 gen_movl_TN_reg(t, cpu_T[0]);
1277 break;
1280 case 0x0e: /* Float */
1281 case 0x0f: /* Product Specific */
1282 break;
1284 case 0x10: /* LDB */
1285 case 0x11: /* LDH */
1286 case 0x12: /* LDW */
1288 int b, t, s;
1289 target_long im14;
1290 b = field(insn, 21, 5);
1291 t = field(insn, 16, 5);
1292 s = field(insn, 14, 2);
1293 im14 = field_lowsignext(insn, 0, 14);
1294 gen_movl_reg_TN(b, cpu_T[0]);
1295 tcg_gen_movi_tl(cpu_T[1], s);
1296 /* gen_op_space_sel_T0_T1(); */
1297 tcg_gen_movi_tl(cpu_T[1], im14);
1298 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1299 switch (op) {
1300 case 0x10: /* LDB */
1301 tcg_gen_qemu_ld8u(cpu_T[1], cpu_T[0], dc->mem_idx);
1302 break;
1303 case 0x11: /* LDH */
1304 tcg_gen_qemu_ld16u(cpu_T[1], cpu_T[0], dc->mem_idx);
1305 break;
1306 case 0x12: /* LDW */
1307 tcg_gen_qemu_ld32u(cpu_T[1], cpu_T[0], dc->mem_idx);
1308 break;
1310 gen_movl_TN_reg(t, cpu_T[1]);
1311 break;
1314 case 0x13: /* LDW,M (LDWM) post-incr/pre-decr */
1316 int b, t, s;
1317 target_long im14;
1318 b = field(insn, 21, 5);
1319 t = field(insn, 16, 5);
1320 s = field(insn, 14, 2);
1321 im14 = field_lowsignext(insn, 0, 14);
1322 gen_movl_reg_TN(b, cpu_T[0]);
1323 /* tcg_gen_movi_tl(cpu_T[1], s); */
1324 /* gen_op_space_sel_T0_T1(); */
1325 /* XXX: check this */
1326 if (im14 & (1 << 31)) {
1327 tcg_gen_movi_tl(cpu_T[1], im14);
1328 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1330 tcg_gen_qemu_ld32u(cpu_T[1], cpu_T[0], dc->mem_idx);
1331 gen_movl_TN_reg(t, cpu_T[1]);
1332 if (!(im14 & (1 << 31))) {
1333 tcg_gen_movi_tl(cpu_T[1], im14);
1334 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1336 gen_movl_TN_reg(b, cpu_T[0]);
1337 break;
1340 #ifdef TARGET_HPPA64
1341 case 0x14: /* Load_dw */
1342 /* LDD/FLDD (long) */
1343 break;
1345 case 0x16: /* FLDW,M */
1346 case 0x17: /* LDW,M pre-incr/post-decr */
1347 break;
1348 #endif
1350 case 0x18: /* STB */
1351 case 0x19: /* STH */
1352 case 0x1a: /* STW */
1354 int b, r, s;
1355 target_long im14;
1356 b = field(insn, 21, 5);
1357 r = field(insn, 16, 5);
1358 s = field(insn, 14, 2);
1359 im14 = field_lowsignext(insn, 0, 14);
1360 gen_movl_reg_TN(b, cpu_T[0]);
1361 /* tcg_gen_movi_tl(cpu_T[1], s); */
1362 /* gen_op_space_sel_T0_T1(); */
1363 tcg_gen_movi_tl(cpu_T[1], im14);
1364 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1365 gen_movl_reg_TN(r, cpu_T[1]);
1366 switch (op) {
1367 case 0x18: /* STB */
1368 tcg_gen_qemu_st8(cpu_T[1], cpu_T[0], dc->mem_idx);
1369 break;
1370 case 0x19: /* STH */
1371 tcg_gen_qemu_st16(cpu_T[1], cpu_T[0], dc->mem_idx);
1372 break;
1373 case 0x1a: /* STW */
1374 tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], dc->mem_idx);
1375 break;
1377 break;
1380 case 0x1b: /* STW,M (STWM) post-incr/pre-decr */
1382 int b, r, s;
1383 target_long im14;
1384 b = field(insn, 21, 5);
1385 r = field(insn, 16, 5);
1386 s = field(insn, 14, 2);
1387 im14 = field_lowsignext(insn, 0, 14);
1388 gen_movl_reg_TN(b, cpu_T[0]);
1389 /* tcg_gen_movi_tl(cpu_T[1], s); */
1390 /* gen_op_space_sel_T0_T1(); */
1391 /* XXX: check this */
1392 if (im14 & (1 << 31)) {
1393 tcg_gen_movi_tl(cpu_T[1], im14);
1394 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1396 gen_movl_reg_TN(r, cpu_T[1]);
1397 tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], dc->mem_idx);
1398 if (!(im14 & (1 << 31))) {
1399 tcg_gen_movi_tl(cpu_T[1], im14);
1400 tcg_gen_add_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
1402 gen_movl_TN_reg(b, cpu_T[0]);
1403 break;
1406 #ifdef TARGET_HPPA64
1407 case 0x1c: /* Store_dw */
1408 /* STD/FSTD (long) */
1409 break;
1411 case 0x1e: /* FSTW,M */
1412 case 0x1f: /* STW,M pre-incr/post-decr */
1413 break;
1414 #endif
1416 case 0x20: /* CMPB (true) (COMBT) */
1417 case 0x21: /* CMPIB (true) (COMIBT) */
1418 case 0x22: /* CMPB (false) (COMBF) */
1419 case 0x23: /* CMPIB (false) (COMIBF) */
1421 int f, c, w1, n, w;
1422 target_long disp;
1423 switch (op) {
1424 case 0x20: /* CMPB (true) (COMBT) */
1425 case 0x22: /* CMPB (false) (COMBF) */
1427 int r1, r2;
1428 r2 = field(insn, 21, 5);
1429 r1 = field(insn, 16, 5);
1430 gen_movl_reg_TN(r1, cpu_T[0]);
1431 gen_movl_reg_TN(r2, cpu_T[1]);
1432 break;
1434 case 0x21: /* CMPIB (true) (COMIBT) */
1435 case 0x23: /* CMPIB (false) (COMIBF) */
1437 int r;
1438 target_long im5;
1439 r = field(insn, 21, 5);
1440 im5 = field_lowsignext(insn, 16, 5);
1441 tcg_gen_movi_tl(cpu_T[0], im5);
1442 gen_movl_reg_TN(r, cpu_T[1]);
1443 break;
1446 f = field(insn, 27, 1);
1447 c = field(insn, 13, 3);
1448 w1 = field(insn, 2, 11);
1449 n = field(insn, 1, 1);
1450 w = field(insn, 0, 1);
1451 disp = signext(assemble_12(w1, w), 12) << 2;
1453 gen_cond_sub[c]();
1454 gen_branch_cond(dc, (long)dc->tb, disp, n, f);
1456 /* FIXME */
1457 dc->is_br = 1;
1458 break;
1461 case 0x24: /* CMPICLR (COMICLR) */
1463 int r, t, c, f;
1464 target_long im11;
1465 if (field(insn, 11, 1))
1466 gen_op_undef_insn();
1467 else {
1468 r = field(insn, 21, 5);
1469 t = field(insn, 16, 5);
1470 c = field(insn, 13, 3);
1471 f = field(insn, 12, 1);
1472 im11 = field_lowsignext(insn, 0, 11);
1473 gen_movl_reg_TN(r, cpu_T[0]);
1474 tcg_gen_movi_tl(cpu_T[1], im11);
1475 if (c || f)
1476 gen_cond_sub[c]();
1477 tcg_gen_movi_tl(cpu_T[0], 0);
1478 gen_movl_TN_reg(t, cpu_T[0]);
1479 if (c || f)
1480 gen_nullify_cond(dc, (long)dc->tb, f);
1482 break;
1485 case 0x25: /* SUBI / SUBI,TSV (SUBIO) */
1487 int r, t, c, f, o;
1488 target_long im11;
1489 r = field(insn, 21, 5);
1490 t = field(insn, 16, 5);
1491 c = field(insn, 13, 3);
1492 f = field(insn, 12, 1);
1493 o = field(insn, 11, 1);
1494 im11 = field_lowsignext(insn, 0, 11);
1495 gen_movl_reg_TN(r, cpu_T[0]);
1496 if (o) {
1497 gen_op_eval_sub_sv();
1498 /* gen_op_overflow_trap(); */
1500 if (c || f)
1501 gen_cond_sub[c]();
1502 gen_op_sub_T1_T0_cc();
1503 if (c || f)
1504 gen_nullify_cond(dc, (long)dc->tb, f);
1505 break;
1508 case 0x26: /* FMPYSUB */
1509 /* TODO */
1510 break;
1512 #ifdef TARGET_HPPA64
1513 case 0x27: /* CMPB (dw true) */
1514 break;
1515 #endif
1517 case 0x28: /* ADDB (true) (ADDBT) */
1518 case 0x29: /* ADDIB (true) (ADDIBT) */
1519 case 0x2a: /* ADDB (false) (ADDBF) */
1520 case 0x2b: /* ADDIB (false) (ADDIBF) */
1522 int f, c, w1, n, w;
1523 target_long disp;
1524 switch (op) {
1525 case 0x28: /* ADDB (true) (ADDBT) */
1526 case 0x2a: /* ADDB (false) (ADDBF) */
1528 int r1, r2;
1529 r2 = field(insn, 21, 5);
1530 r1 = field(insn, 16, 5);
1531 gen_movl_reg_TN(r1, cpu_T[0]);
1532 gen_movl_reg_TN(r2, cpu_T[1]);
1533 break;
1535 case 0x29: /* ADDIB (true) (ADDIBT) */
1536 case 0x2b: /* ADDIB (false) (ADDIBF) */
1538 int r;
1539 target_long im5;
1540 r = field(insn, 21, 5);
1541 im5 = field_lowsignext(insn, 16, 5);
1542 tcg_gen_movi_tl(cpu_T[0], im5);
1543 gen_movl_reg_TN(r, cpu_T[1]);
1544 break;
1547 f = field(insn, 27, 1);
1548 c = field(insn, 13, 3);
1549 w1 = field(insn, 2, 11);
1550 n = field(insn, 1, 1);
1551 w = field(insn, 0, 1);
1552 disp = signext(assemble_12(w1, w), 12) << 2;
1554 gen_cond_add[c]();
1555 gen_branch_cond(dc, (long)dc->tb, disp, n, f);
1557 /* FIXME */
1558 dc->is_br = 1;
1559 break;
1562 case 0x2c: /* ADDI,TC (ADDIT) / ADDI,TSV,TC (ADDITO) */
1563 case 0x2d: /* ADDI / ADDI,TSV (ADDIO) */
1565 int r, t, c, f, o;
1566 target_long im11;
1567 r = field(insn, 21, 5);
1568 t = field(insn, 16, 5);
1569 c = field(insn, 13, 3);
1570 f = field(insn, 12, 1);
1571 o = field(insn, 11, 1);
1572 im11 = field_lowsignext(insn, 0, 11);
1573 gen_movl_reg_TN(r, cpu_T[0]);
1574 tcg_gen_movi_tl(cpu_T[1], im11);
1575 if (o) {
1576 gen_op_eval_add_sv();
1577 /* gen_op_overflow_trap(); */
1579 if (c || f) {
1580 gen_cond_add[c]();
1581 if (op == 0x2c) /* ADDI,TC (ADDIT) / ADDI,TSV,TC (ADDITO) */
1582 ; /* gen_cond_trap(); */
1584 gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1]);
1585 if ((c || f) && (op == 0x2d)) /* ADDI / ADDI,TSV (ADDIO) */
1586 gen_nullify_cond(dc, (long)dc->tb, f);
1587 gen_movl_TN_reg(t, cpu_T[0]);
1588 break;
1591 #ifdef TARGET_HPPA64
1592 case 0x2e: /* Fp_fused */
1593 case 0x2f: /* CMPB (dw false) */
1594 break;
1595 #endif
1597 case 0x30: /* BB (sar) (BVB) */
1598 case 0x31: /* BB */
1599 case 0x32: /* MOVB */
1600 case 0x33: /* MOVIB */
1601 /* disp = signext(assemble_12(w1, w), 12) << 2; */
1602 /* FIXME */
1603 dc->is_br = 1;
1604 break;
1606 case 0x34: /* Shift/Extract */
1608 int ext3;
1609 ext3 = field(insn, 10, 3);
1610 switch (ext3) {
1611 case 0: /* VSHD = SHRPW with SAR */
1612 gen_movl_cr_TN(11, cpu_T[0]);
1613 gen_shrpw(insn);
1614 break;
1615 case 2: /* SHD = SHRPW */
1617 int sa = 31 - field(insn, 5, 5);
1618 tcg_gen_movi_tl(cpu_T[0], sa);
1619 gen_shrpw(insn);
1620 break;
1622 case 4: /* VEXTRU = EXTRW,U with SAR */
1623 case 5: /* VEXTRS = EXTRW,S with SAR */
1624 gen_movl_cr_TN(11, cpu_T[0]);
1625 gen_extrw(insn);
1626 break;
1627 case 6: /* EXTRU = EXTRW,U */
1628 case 7: /* EXTRS = EXTRW,S */
1630 int pos = field(insn, 5, 5);
1631 tcg_gen_movi_tl(cpu_T[0], pos);
1632 gen_extrw(insn);
1633 break;
1636 break;
1639 case 0x35: /* Deposit */
1641 int ext3;
1642 ext3 = field(insn, 10, 3);
1643 switch (ext3) {
1644 case 0: /* VZDEP = DEPW,Z with SAR */
1645 case 1: /* VDEP = DEPW with SAR */
1646 gen_movl_cr_TN(11, cpu_T[0]);
1647 gen_depw(insn);
1648 break;
1649 case 2: /* ZDEP = DEPW,Z */
1650 case 3: /* DEP = DEPW */
1652 int cpos = field(insn, 5, 5);
1653 tcg_gen_movi_tl(cpu_T[0], cpos);
1654 gen_depw(insn);
1655 break;
1657 case 4: /* VZDEPI = DEPW,Z */
1658 case 5: /* VDEPI = DEPW,Z */
1659 gen_movl_cr_TN(11, cpu_T[0]);
1660 gen_depwi(insn);
1661 break;
1662 case 6: /* ZDEPI = DEPWI,Z */
1663 case 7: /* DEPI = DEPWI */
1665 int cpos = field(insn, 5, 5);
1666 tcg_gen_movi_tl(cpu_T[0], cpos);
1667 gen_depwi(insn);
1668 break;
1671 break;
1674 #ifdef TARGET_HPPA64
1675 case 0x36: /* EXTRD */
1676 break;
1677 #endif
1679 case 0x38: /* BE */
1680 case 0x39: /* BE,L (BLE) */
1682 int b, w1, s, w2, n, w;
1683 target_long disp;
1684 b = field(insn, 21, 5);
1685 w1 = field(insn, 16, 5);
1686 s = field(insn, 13, 3);
1687 w2 = field(insn, 2, 11);
1688 n = field(insn, 1, 1);
1689 w = field(insn, 0, 1);
1690 disp = signext(assemble_17(w1,w2,w),17) << 2;
1691 /* */
1693 /* FIXME */
1694 dc->is_br = 1;
1695 break;
1698 case 0x3a: /* Branch */
1700 int t, w, w1, ext3, w2, n;
1701 target_long disp;
1702 ext3 = field(insn, 13, 3);
1703 t = field(insn, 21, 5);
1704 w1 = field(insn, 16, 5);
1705 w2 = field(insn, 2, 11);
1706 n = field(insn, 1, 1);
1707 w = field(insn, 0, 1);
1708 disp = signext(assemble_17(w1,w2,w),17) << 2;
1709 switch (ext3) {
1710 case 0: /* B,L (BL) */
1711 /* TODO: dc->iaoq[1] + 4 into t */
1712 if (n) {
1713 gen_branch(dc, 0, dc->iaoq[0] + disp + 8, dc->iaoq[0] + disp + 12);
1714 } else {
1715 gen_branch(dc, 0, dc->iaoq[1], dc->iaoq[0] + disp + 8);
1717 break;
1718 case 2: /* BLR */
1719 /* if w == 0 ( ill_insn ) */
1720 case 6: /* BV */
1721 case 1: /* B,GATE (GATE) */
1722 break;
1725 /* FIXME */
1726 dc->is_br = 1;
1727 break;
1730 #ifdef TARGET_HPPA64
1731 case 0x3b: /* CMPIB (dw) */
1732 break;
1734 case 0x3c: /* DEPD */
1735 case 0x3d: /* DEPI */
1736 break;
1738 case 0x3e: /* Multimedia (MAX-2) */
1739 /* PERMH */
1740 /* HSHL */
1741 /* HSHR,U */
1742 /* HSHR,S */
1743 /* MIXW,L */
1744 /* MIXW,R */
1745 /* MIXH,L */
1746 /* MIXH,R */
1747 break;
1748 #endif
1750 default: /* Illegal Instruction */
1751 gen_op_ill_insn();
1752 break;
1755 dc->iaoq[0] = dc->iaoq[1];
1756 dc->iaoq[1] = dc->iaoq[1] + 4;
1759 CPUHPPAState *cpu_hppa_init(const char *cpu_model)
1761 CPUHPPAState *env;
1763 env = qemu_mallocz(sizeof(CPUHPPAState));
1764 cpu_exec_init(env);
1765 hppa_translate_init();
1766 tlb_flush(env, 1);
1767 qemu_init_vcpu(env);
1768 return env;
1771 void cpu_dump_state(CPUState *env, FILE *f,
1772 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1773 int flags)
1775 int i;
1777 cpu_fprintf(f, "PSW = %08X\n", env->psw);
1778 for (i=0; i<31; i++) {
1779 cpu_fprintf(f, "R%02d=%08x", i, env->gr[i]);
1780 if ((i % 4) == 3)
1781 cpu_fprintf(f, "\n");
1782 else
1783 cpu_fprintf(f, " ");
1786 for (i=0; i<31; i++) {
1787 cpu_fprintf(f, "CR%02d=%08x", i, env->cr[i]);
1788 if ((i % 4) == 3)
1789 cpu_fprintf(f, "\n");
1790 else
1791 cpu_fprintf(f, " ");
1794 cpu_fprintf(f, "IAOQ = %08X %08X\tIASQ = %08X %08X\n",
1795 env->iaoq[0], env->iaoq[1], env->iasq[0], env->iasq[1]);
1798 void gen_pc_load(CPUState *env, TranslationBlock *tb,
1799 unsigned long searched_pc, int pc_pos, void *puc)
1801 env->iaoq[0] = gen_opc_pc[pc_pos];
1802 env->iaoq[1] = gen_opc_npc[pc_pos];