4 * Copyright (c) 2008-2009 Stuart Brady <stuart.brady@gmail.com>
5 * Copyright (c) 2009 Laurent Desnogues
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
33 const TranslationBlock
*tb
;
36 /* global register indexes */
38 static TCGv_ptr cpu_env
;
40 static TCGv cpu_gpr
[32];
42 static char cpu_reg_names
[
46 void openrisc_translate_init(void)
51 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
55 for (i
= 0; i
< 32; i
++) {
57 cpu_gpr
[i
] = tcg_global_mem_new(TCG_AREG0
,
58 offsetof(CPUState
, gpr
[i
]), p
);
59 p
+= (i
< 10) ? 3 : 4;
63 static inline void store_cpu_offset(TCGv var
, int offset
)
65 tcg_gen_st_tl(var
, cpu_env
, offset
);
69 #define store_cpu_field(var, name) \
70 store_cpu_offset(var, offsetof(CPUState, name))
72 static inline void gen_set_pc_im(target_ulong val
)
74 TCGv tmp
= tcg_temp_new();
75 tcg_gen_movi_tl(tmp
, val
);
76 store_cpu_field(tmp
, pc
);
79 static inline void gen_goto_tb(DisasContext
*s
, int n
, target_ulong dest
)
81 const TranslationBlock
*tb
;
84 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
87 tcg_gen_exit_tb((long)tb
+ n
);
94 static inline uint32_t field(uint32_t val
, int start
, int length
)
97 val
&= ~(~0 << length
);
101 static void disas_openrisc_insn(DisasContext
*dc
)
104 int op
, opext
, opext2
, d
, a
, b
;
105 target_ulong im16
, im16b
;
109 insn
= ldl_code(dc
->pc
);
112 op
= field(insn
, 26, 6);
113 /* opext = field(insn, 21, 5); */
114 d
= field(insn
, 21, 5);
115 a
= field(insn
, 16, 5);
116 b
= field(insn
, 11, 5);
117 im16
= field(insn
, 0, 16);
118 im16b
= field(insn
, 0, 11) | (d
<< 11);
123 case 0x01: /* l.jal */
125 case 0x03: /* l.bnf */
127 case 0x04: /* l.bf */
129 case 0x05: /* l.nop */
138 /* csync, msync, psync */
140 case 0x09: /* l.rfe */
143 #ifdef TARGET_OPENRISC64
144 case 0x0a: /* [vector ops] */
146 case 0x10: /* lv.all_eq.b */
148 case 0x11: /* lv.all_eq.h */
150 case 0x12: /* lv.all_ge.b */
152 case 0x13: /* lv.all_ge.h */
154 case 0x14: /* lv.all_gt.b */
156 case 0x15: /* lv.all_gt.h */
158 case 0x16: /* lv.all_le.b */
160 case 0x17: /* lv.all_le.h */
162 case 0x18: /* lv.all_lt.b */
164 case 0x19: /* lv.all_lt.h */
166 case 0x1a: /* lv.all_ne.b */
168 case 0x1b: /* lv.all_ne.h */
170 case 0x20: /* lv.any_eq.b */
172 case 0x21: /* lv.any_eq.h */
174 case 0x22: /* lv.any_ge.b */
176 case 0x23: /* lv.any_ge.h */
178 case 0x24: /* lv.any_gt.b */
180 case 0x25: /* lv.any_gt.h */
182 case 0x26: /* lv.any_le.b */
184 case 0x27: /* lv.any_le.h */
186 case 0x28: /* lv.any_lt.b */
188 case 0x29: /* lv.any_lt.h */
190 case 0x2a: /* lv.any_ne.b */
192 case 0x2b: /* lv.any_ne.h */
194 case 0x30: /* lv.add.b */
196 case 0x31: /* lv.add.h */
198 case 0x32: /* lv.adds.b */
200 case 0x33: /* lv.adds.h */
202 case 0x34: /* lv.addu.b */
204 case 0x35: /* lv.addu.h */
206 case 0x36: /* lv.addus.b */
208 case 0x37: /* lv.addus.h */
210 case 0x38: /* lv.and */
212 case 0x39: /* lv.avg.b */
214 case 0x3a: /* lv.avg.h */
216 case 0x40: /* lv.cmp_eq.b */
218 case 0x41: /* lv.cmp_eq.h */
220 case 0x42: /* lv.cmp_ge.b */
222 case 0x43: /* lv.cmp_ge.h */
224 case 0x44: /* lv.cmp_gt.b */
226 case 0x45: /* lv.cmp_gt.h */
228 case 0x46: /* lv.cmp_le.b */
230 case 0x47: /* lv.cmp_le.h */
232 case 0x48: /* lv.cmp_lt.b */
234 case 0x49: /* lv.cmp_lt.h */
236 case 0x4a: /* lv.cmp_ne.b */
238 case 0x4b: /* lv.cmp_ne.h */
240 case 0x54: /* lv.madds.h */
242 case 0x55: /* lv.max.b */
244 case 0x56: /* lv.max.h */
246 case 0x57: /* lv.merge.b */
248 case 0x58: /* lv.merge.h */
250 case 0x59: /* lv.min.b */
252 case 0x5a: /* lv.min.h */
254 case 0x5b: /* lv.msubs.h */
256 case 0x5c: /* lv.muls.h */
258 case 0x5d: /* lv.nand */
260 case 0x5e: /* lv.nor */
262 case 0x5f: /* lv.or */
264 case 0x60: /* lv.pack.b */
266 case 0x61: /* lv.pack.h */
268 case 0x62: /* lv.packs.b */
270 case 0x63: /* lv.packs.h */
272 case 0x64: /* lv.packus.b */
274 case 0x65: /* lv.packus.h */
276 case 0x66: /* lv.perm.n */
278 case 0x67: /* lv.rl.b */
280 case 0x68: /* lv.rl.h */
282 case 0x69: /* lv.sll.b */
284 case 0x6a: /* lv.sll.h */
286 case 0x6b: /* lv.sll */
288 case 0x6c: /* lv.srl.b */
290 case 0x6d: /* lv.srl.h */
292 case 0x6e: /* lv.sra.b */
294 case 0x6f: /* lv.sra.h */
296 case 0x70: /* lv.sra */
298 case 0x71: /* lv.sub.b */
300 case 0x72: /* lv.sub.h */
302 case 0x73: /* lv.subs.b */
304 case 0x74: /* lv.subs.h */
306 case 0x75: /* lv.subu.b */
308 case 0x76: /* lv.subu.h */
310 case 0x77: /* lv.subus.b */
312 case 0x78: /* lv.subus.h */
314 case 0x79: /* lv.unpack.b */
316 case 0x7a: /* lv.unpack.h */
318 case 0x7b: /* lv.xor.h */
320 case 0xc0 ... 0xff: /* lv.cust[1234] */
326 case 0x11: /* l.jr */
328 case 0x12: /* l.jalr */
330 case 0x13: /* [l.maci] */
332 case 0x1c: /* [l.cust1] */
334 case 0x1d: /* [l.cust2] */
336 case 0x1e: /* [l.cust3] */
338 case 0x1f: /* [l.cust4] */
341 case 0x20 ... 0x26: /* Loads */
343 tcg_gen_addi_tl(t0
, cpu_gpr
[a
], (int16_t)im16
);
345 #ifdef TARGET_OPENRISC64
346 case 0x20: /* l.ld */
347 tcg_gen_qemu_ld64(cpu_gpr
[d
], t0
, dc
->mem_idx
);
350 case 0x21: /* l.lwz */
351 tcg_gen_qemu_ld32u(cpu_gpr
[d
], t0
, dc
->mem_idx
);
353 case 0x22: /* l.lws */
354 tcg_gen_qemu_ld32s(cpu_gpr
[d
], t0
, dc
->mem_idx
);
356 case 0x23: /* l.lbz */
357 tcg_gen_qemu_ld8u(cpu_gpr
[d
], t0
, dc
->mem_idx
);
359 case 0x24: /* l.lbs */
360 tcg_gen_qemu_ld8s(cpu_gpr
[d
], t0
, dc
->mem_idx
);
362 case 0x25: /* l.lhz */
363 tcg_gen_qemu_ld16u(cpu_gpr
[d
], t0
, dc
->mem_idx
);
365 case 0x26: /* l.lhs */
366 tcg_gen_qemu_ld16s(cpu_gpr
[d
], t0
, dc
->mem_idx
);
372 case 0x27: /* l.addi */
373 tcg_gen_addi_tl(cpu_gpr
[d
], cpu_gpr
[a
], (int16_t)im16
);
375 case 0x28: /* l.addic */
376 //tcg_gen_addi_tl(cpu_gpr[d], cpu_gpr[a], im);
377 /* FIXME: also adds carry */
380 case 0x29: /* l.andi */
381 tcg_gen_andi_tl(cpu_gpr
[d
], cpu_gpr
[a
], im16
);
383 case 0x2a: /* l.ori */
384 tcg_gen_ori_tl(cpu_gpr
[d
], cpu_gpr
[a
], im16
);
386 case 0x2b: /* l.xori */
387 tcg_gen_ori_tl(cpu_gpr
[d
], cpu_gpr
[a
], im16
);
389 case 0x2c: /* l.muli */
390 tcg_gen_muli_tl(cpu_gpr
[d
], cpu_gpr
[a
], im16
);
393 case 0x2d: /* l.mfspr */
398 case 0x00: /* l.slli */
399 // tcg_gen_shli_tl(cpu_gpr[d], cpu_gpr[a], im);
401 case 0x01: /* l.srli */
402 // tcg_gen_shri_tl(cpu_gpr[d], cpu_gpr[a], im);
404 case 0x02: /* l.srai */
405 // tcg_gen_sari_tl(cpu_gpr[d], cpu_gpr[a], im);
407 case 0x03: /* [l.rori] */
408 /* illegal instruction */
413 case 0x30: /* l.mtspr */
417 case 0x01: /* [l.mac] */
419 case 0x02: /* [l.msb] */
424 case 0x32: /* [floating point ops] */
427 case 0x34 ... 0x37: /* Stores */
429 tcg_gen_addi_tl(t0
, cpu_gpr
[a
], (int16_t)im16b
);
431 #ifdef TARGET_OPENRISC64
432 case 0x34: /* l.sd */
433 tcg_gen_qemu_st64(cpu_gpr
[b
], t0
, dc
->mem_idx
);
436 case 0x35: /* l.sw */
437 tcg_gen_qemu_st32(cpu_gpr
[b
], t0
, dc
->mem_idx
);
439 case 0x36: /* l.sb */
440 tcg_gen_qemu_st8(cpu_gpr
[b
], t0
, dc
->mem_idx
);
442 case 0x37: /* l.sh */
443 tcg_gen_qemu_st16(cpu_gpr
[b
], t0
, dc
->mem_idx
);
451 case 0x0: /* l.add */
452 tcg_gen_add_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
454 case 0x1: /* l.addc */
455 /* tcg_gen_add_tl(cpu_gpr[d], cpu_gpr[a], cpu_gpr[b]); */
456 /* FIXME: also adds carry */
458 case 0x2: /* l.sub */
459 tcg_gen_sub_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
461 case 0x3: /* l.and */
462 tcg_gen_and_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
465 tcg_gen_or_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
467 case 0x5: /* l.xor */
468 tcg_gen_xor_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
470 case 0x6: /* l.mul */
471 tcg_gen_mul_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
474 case 0x8: /* Shifts */
475 #ifdef TARGET_OPENRISC64
476 /* FIXME: only use bits 0..5 of shift reg */
478 /* FIXME: only use bits 0..4 of shift reg */
481 case 0x0: /* l.sll */
482 tcg_gen_shl_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
484 case 0x1: /* l.srl */
485 tcg_gen_shr_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
487 case 0x2: /* l.sra */
488 tcg_gen_sar_tl(cpu_gpr
[d
], cpu_gpr
[a
], cpu_gpr
[b
]);
490 case 0x3: /* [l.ror] */
491 /* tcg_gen_ror_tl(cpu_gpr[d], cpu_gpr[a], cpu_gpr[b]); */
492 /* illegal instruction */
497 case 0xb: /* l.mulu */
501 case 0x9: /* l.div */
503 case 0xa: /* l.divu */
508 case 0x00: /* l.exths */
509 tcg_gen_ext16s_tl(cpu_gpr
[d
], cpu_gpr
[a
]);
511 case 0x01: /* l.extbs */
512 tcg_gen_ext8s_tl(cpu_gpr
[d
], cpu_gpr
[a
]);
514 case 0x02: /* l.exthz */
515 tcg_gen_ext16u_tl(cpu_gpr
[d
], cpu_gpr
[a
]);
517 case 0x03: /* l.extbz */
518 tcg_gen_ext8u_tl(cpu_gpr
[d
], cpu_gpr
[a
]);
525 #ifdef TARGET_OPENRISC64
526 case 0x00: /* l.extws */
527 tcg_gen_ext32s_tl(cpu_gpr
[d
], cpu_gpr
[a
]);
529 case 0x01: /* l.extwz */
530 tcg_gen_ext32u_tl(cpu_gpr
[d
], cpu_gpr
[a
]);
536 case 0x0e: /* l.cmov */
540 case 0x00: /* l.ff1 */
541 /* tcg_gen_clz_tl(cpu_gpr[d], cpu_gpr[a]); */
543 case 0x01: /* l.fl1 */
544 /* tcg_gen_ctz_tl(cpu_gpr[d], cpu_gpr[a]); */
552 l1
= gen_new_label();
553 l2
= gen_new_label();
555 case 0x00: /* l.sfeqi */
556 tcg_gen_brcondi_tl(TCG_COND_EQ
, cpu_gpr
[a
], im16
, l1
);
558 case 0x01: /* l.sfnei */
559 tcg_gen_brcondi_tl(TCG_COND_NE
, cpu_gpr
[a
], im16
, l1
);
561 case 0x02: /* l.sfgtui */
562 tcg_gen_brcondi_tl(TCG_COND_GTU
, cpu_gpr
[a
], im16
, l1
);
564 case 0x03: /* l.sfgeui */
565 tcg_gen_brcondi_tl(TCG_COND_GEU
, cpu_gpr
[a
], im16
, l1
);
567 case 0x04: /* l.sfltui */
568 tcg_gen_brcondi_tl(TCG_COND_LTU
, cpu_gpr
[a
], im16
, l1
);
570 case 0x05: /* l.sfleui */
571 tcg_gen_brcondi_tl(TCG_COND_LEU
, cpu_gpr
[a
], im16
, l1
);
573 case 0x0a: /* l.sfgtsi */
574 tcg_gen_brcondi_tl(TCG_COND_GT
, cpu_gpr
[a
], im16
, l1
);
576 case 0x0b: /* l.sfgesi */
577 tcg_gen_brcondi_tl(TCG_COND_GE
, cpu_gpr
[a
], im16
, l1
);
579 case 0x0c: /* l.sfltsi */
580 tcg_gen_brcondi_tl(TCG_COND_LT
, cpu_gpr
[a
], im16
, l1
);
582 case 0x0d: /* l.sflesi */
583 tcg_gen_brcondi_tl(TCG_COND_LE
, cpu_gpr
[a
], im16
, l1
);
586 // use andi to clear the compare flag
587 // tcg_gen_movi_tl(t, 0);
590 // use ori to set the compare flag
591 // tcg_gen_movi_tl(t, 1);
596 l1
= gen_new_label();
597 l2
= gen_new_label();
599 case 0x00: /* l.sfeq */
600 tcg_gen_brcond_tl(TCG_COND_EQ
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
602 case 0x01: /* l.sfne */
603 tcg_gen_brcond_tl(TCG_COND_NE
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
605 case 0x02: /* l.sfgtu */
606 tcg_gen_brcond_tl(TCG_COND_GTU
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
608 case 0x03: /* l.sfgeu */
609 tcg_gen_brcond_tl(TCG_COND_GEU
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
611 case 0x04: /* l.sfltu */
612 tcg_gen_brcond_tl(TCG_COND_LTU
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
614 case 0x05: /* l.sfleu */
615 tcg_gen_brcond_tl(TCG_COND_LEU
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
617 case 0x0a: /* l.sfgts */
618 tcg_gen_brcond_tl(TCG_COND_GT
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
620 case 0x0b: /* l.sfges */
621 tcg_gen_brcond_tl(TCG_COND_GE
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
623 case 0x0c: /* l.sflts */
624 tcg_gen_brcond_tl(TCG_COND_LT
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
626 case 0x0d: /* l.sfles */
627 tcg_gen_brcond_tl(TCG_COND_LE
, cpu_gpr
[a
], cpu_gpr
[b
], l1
);
630 // use andi to clear the compare flag
631 // tcg_gen_movi_tl(t, 0);
634 // use ori to set the compare flag
635 // tcg_gen_movi_tl(t, 1);
639 case 0x3c: /* [l.cust5] */
641 case 0x3d: /* [l.cust6] */
643 case 0x3e: /* [l.cust7] */
645 case 0x3f: /* [l.cust8] */
650 fprintf(stderr
, "Unimp @" TARGET_FMT_lx
" %08x\n", dc
->pc
, insn
);
654 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
655 basic block 'tb'. If search_pc is TRUE, also generate PC
656 information for each intermediate instruction. */
658 static inline void gen_intermediate_code_internal(CPUState
*env
,
659 TranslationBlock
*tb
,
662 DisasContext dc1
, *dc
= &dc1
;
663 target_ulong pc_start
;
669 dc
->is_jmp
= DISAS_NEXT
;
673 disas_openrisc_insn(dc
);
676 switch (dc
->is_jmp
) {
678 gen_goto_tb(dc
, 1, dc
->pc
);
682 *gen_opc_ptr
= INDEX_op_end
;
685 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
686 fprintf(logfile
, "----------------\n");
687 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
688 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, 0);
689 fprintf(logfile
, "\n");
693 tb
->size
= dc
->pc
- pc_start
;
696 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
698 gen_intermediate_code_internal(env
, tb
, 0);
701 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
703 gen_intermediate_code_internal(env
, tb
, 1);
707 void cpu_dump_state(CPUState
*env
, FILE *f
,
708 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
711 fprintf(stderr
, "pc=" TARGET_FMT_lx
"\n", env
->pc
);
715 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
716 unsigned long searched_pc
, int pc_pos
, void *puc
)
718 env
->pc
= gen_opc_pc
[pc_pos
];