Use tcg_gen_not.
[qemu] / target-cris / op_helper.c
1 /*
2  *  CRIS helper routines
3  *
4  *  Copyright (c) 2007 AXIS Communications
5  *  Written by Edgar E. Iglesias
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser 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.
11  *
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  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <assert.h>
23 #include "exec.h"
24 #include "mmu.h"
25
26 #define MMUSUFFIX _mmu
27 #ifdef __s390__
28 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
29 #else
30 # define GETPC() (__builtin_return_address(0))
31 #endif
32
33 #define SHIFT 0
34 #include "softmmu_template.h"
35
36 #define SHIFT 1
37 #include "softmmu_template.h"
38
39 #define SHIFT 2
40 #include "softmmu_template.h"
41
42 #define SHIFT 3
43 #include "softmmu_template.h"
44
45 #define D(x)
46
47 /* Try to fill the TLB and return an exception if error. If retaddr is
48    NULL, it means that the function was called in C code (i.e. not
49    from generated code or from helper.c) */
50 /* XXX: fix it to restore all registers */
51 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
52 {
53     TranslationBlock *tb;
54     CPUState *saved_env;
55     unsigned long pc;
56     int ret;
57
58     /* XXX: hack to restore env in all cases, even if not called from
59        generated code */
60     saved_env = env;
61     env = cpu_single_env;
62
63     D(fprintf(logfile, "%s pc=%x tpc=%x ra=%x\n", __func__, 
64              env->pc, env->debug1, retaddr));
65     ret = cpu_cris_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
66     if (__builtin_expect(ret, 0)) {
67         if (retaddr) {
68             /* now we have a real cpu fault */
69             pc = (unsigned long)retaddr;
70             tb = tb_find_pc(pc);
71             if (tb) {
72                 /* the PC is inside the translated code. It means that we have
73                    a virtual CPU fault */
74                 cpu_restore_state(tb, env, pc, NULL);
75             }
76         }
77         cpu_loop_exit();
78     }
79     env = saved_env;
80 }
81
82 void helper_raise_exception(uint32_t index)
83 {
84         env->exception_index = index;
85         cpu_loop_exit();
86 }
87
88 void helper_tlb_flush_pid(uint32_t pid)
89 {
90 #if !defined(CONFIG_USER_ONLY)
91         cris_mmu_flush_pid(env, pid);
92 #endif
93 }
94
95 void helper_tlb_flush(void)
96 {
97         tlb_flush(env, 1);
98 }
99
100 void helper_dump(uint32_t a0, uint32_t a1)
101 {
102         (fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1)); 
103 }
104
105 void helper_dummy(void)
106 {
107
108 }
109
110 /* Used by the tlb decoder.  */
111 #define EXTRACT_FIELD(src, start, end) \
112             (((src) >> start) & ((1 << (end - start + 1)) - 1))
113
114 void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg)
115 {
116         uint32_t srs;
117         srs = env->pregs[PR_SRS];
118         srs &= 3;
119         env->sregs[srs][sreg] = env->regs[reg];
120
121 #if !defined(CONFIG_USER_ONLY)
122         if (srs == 1 || srs == 2) {
123                 if (sreg == 6) {
124                         /* Writes to tlb-hi write to mm_cause as a side 
125                            effect.  */
126                         env->sregs[SFR_RW_MM_TLB_HI] = T0;
127                         env->sregs[SFR_R_MM_CAUSE] = T0;
128                 }
129                 else if (sreg == 5) {
130                         uint32_t set;
131                         uint32_t idx;
132                         uint32_t lo, hi;
133                         uint32_t vaddr;
134                         int tlb_v;
135
136                         idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
137                         set >>= 4;
138                         set &= 3;
139
140                         idx &= 15;
141                         /* We've just made a write to tlb_lo.  */
142                         lo = env->sregs[SFR_RW_MM_TLB_LO];
143                         /* Writes are done via r_mm_cause.  */
144                         hi = env->sregs[SFR_R_MM_CAUSE];
145
146                         vaddr = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].hi,
147                                               13, 31);
148                         vaddr <<= TARGET_PAGE_BITS;
149                         tlb_v = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].lo,
150                                             3, 3);
151                         env->tlbsets[srs - 1][set][idx].lo = lo;
152                         env->tlbsets[srs - 1][set][idx].hi = hi;
153
154                         D(fprintf(logfile, 
155                                   "tlb flush vaddr=%x v=%d pc=%x\n", 
156                                   vaddr, tlb_v, env->pc));
157                         tlb_flush_page(env, vaddr);
158                 }
159         }
160 #endif
161 }
162
163 void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg)
164 {
165         uint32_t srs;
166         env->pregs[PR_SRS] &= 3;
167         srs = env->pregs[PR_SRS];
168         
169 #if !defined(CONFIG_USER_ONLY)
170         if (srs == 1 || srs == 2)
171         {
172                 uint32_t set;
173                 uint32_t idx;
174                 uint32_t lo, hi;
175
176                 idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
177                 set >>= 4;
178                 set &= 3;
179                 idx &= 15;
180
181                 /* Update the mirror regs.  */
182                 hi = env->tlbsets[srs - 1][set][idx].hi;
183                 lo = env->tlbsets[srs - 1][set][idx].lo;
184                 env->sregs[SFR_RW_MM_TLB_HI] = hi;
185                 env->sregs[SFR_RW_MM_TLB_LO] = lo;
186         }
187 #endif
188         env->regs[reg] = env->sregs[srs][sreg];
189         RETURN();
190 }
191
192 static void cris_ccs_rshift(CPUState *env)
193 {
194         uint32_t ccs;
195
196         /* Apply the ccs shift.  */
197         ccs = env->pregs[PR_CCS];
198         ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
199         if (ccs & U_FLAG)
200         {
201                 /* Enter user mode.  */
202                 env->ksp = env->regs[R_SP];
203                 env->regs[R_SP] = env->pregs[PR_USP];
204         }
205
206         env->pregs[PR_CCS] = ccs;
207 }
208
209 void helper_rfe(void)
210 {
211         D(fprintf(logfile, "rfe: erp=%x pid=%x ccs=%x btarget=%x\n", 
212                  env->pregs[PR_ERP], env->pregs[PR_PID],
213                  env->pregs[PR_CCS],
214                  env->btarget));
215
216         cris_ccs_rshift(env);
217
218         /* RFE sets the P_FLAG only if the R_FLAG is not set.  */
219         if (!(env->pregs[PR_CCS] & R_FLAG))
220                 env->pregs[PR_CCS] |= P_FLAG;
221 }
222
223 void helper_store(uint32_t a0)
224 {
225         if (env->pregs[PR_CCS] & P_FLAG )
226         {
227                 cpu_abort(env, "cond_store_failed! pc=%x a0=%x\n",
228                           env->pc, a0);
229         }
230 }
231
232 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
233                           int is_asi)
234 {
235         D(printf("%s addr=%x w=%d ex=%d asi=%d\n", 
236                 __func__, addr, is_write, is_exec, is_asi));
237 }
238
239 static void evaluate_flags_writeback(uint32_t flags)
240 {
241         int x;
242
243         /* Extended arithmetics, leave the z flag alone.  */
244         env->debug3 = env->pregs[PR_CCS];
245
246         if (env->cc_x_live)
247                 x = env->cc_x;
248         else
249                 x = env->pregs[PR_CCS] & X_FLAG;
250
251         if ((x || env->cc_op == CC_OP_ADDC)
252             && flags & Z_FLAG)
253                 env->cc_mask &= ~Z_FLAG;
254
255         /* all insn clear the x-flag except setf or clrf.  */
256         env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
257         flags &= env->cc_mask;
258         env->pregs[PR_CCS] |= flags;
259 }
260
261 void helper_evaluate_flags_muls(void)
262 {
263         uint32_t src;
264         uint32_t dst;
265         uint32_t res;
266         uint32_t flags = 0;
267         int64_t tmp;
268         int32_t mof;
269         int dneg;
270
271         src = env->cc_src;
272         dst = env->cc_dest;
273         res = env->cc_result;
274
275         dneg = ((int32_t)res) < 0;
276
277         mof = env->pregs[PR_MOF];
278         tmp = mof;
279         tmp <<= 32;
280         tmp |= res;
281         if (tmp == 0)
282                 flags |= Z_FLAG;
283         else if (tmp < 0)
284                 flags |= N_FLAG;
285         if ((dneg && mof != -1)
286             || (!dneg && mof != 0))
287                 flags |= V_FLAG;
288         evaluate_flags_writeback(flags);
289 }
290
291 void  helper_evaluate_flags_mulu(void)
292 {
293         uint32_t src;
294         uint32_t dst;
295         uint32_t res;
296         uint32_t flags = 0;
297         uint64_t tmp;
298         uint32_t mof;
299
300         src = env->cc_src;
301         dst = env->cc_dest;
302         res = env->cc_result;
303
304         mof = env->pregs[PR_MOF];
305         tmp = mof;
306         tmp <<= 32;
307         tmp |= res;
308         if (tmp == 0)
309                 flags |= Z_FLAG;
310         else if (tmp >> 63)
311                 flags |= N_FLAG;
312         if (mof)
313                 flags |= V_FLAG;
314
315         evaluate_flags_writeback(flags);
316 }
317
318 void  helper_evaluate_flags_mcp(void)
319 {
320         uint32_t src;
321         uint32_t dst;
322         uint32_t res;
323         uint32_t flags = 0;
324
325         src = env->cc_src;
326         dst = env->cc_dest;
327         res = env->cc_result;
328
329         if ((res & 0x80000000L) != 0L)
330         {
331                 flags |= N_FLAG;
332                 if (((src & 0x80000000L) == 0L)
333                     && ((dst & 0x80000000L) == 0L))
334                 {
335                         flags |= V_FLAG;
336                 }
337                 else if (((src & 0x80000000L) != 0L) &&
338                          ((dst & 0x80000000L) != 0L))
339                 {
340                         flags |= R_FLAG;
341                 }
342         }
343         else
344         {
345                 if (res == 0L)
346                         flags |= Z_FLAG;
347                 if (((src & 0x80000000L) != 0L)
348                     && ((dst & 0x80000000L) != 0L))
349                         flags |= V_FLAG;
350                 if ((dst & 0x80000000L) != 0L
351                     || (src & 0x80000000L) != 0L)
352                         flags |= R_FLAG;
353         }
354
355         evaluate_flags_writeback(flags);
356 }
357
358 void  helper_evaluate_flags_alu_4(void)
359 {
360         uint32_t src;
361         uint32_t dst;
362         uint32_t res;
363         uint32_t flags = 0;
364
365         src = env->cc_src;
366         dst = env->cc_dest;
367         res = env->cc_result;
368
369         if ((res & 0x80000000L) != 0L)
370         {
371                 flags |= N_FLAG;
372                 if (((src & 0x80000000L) == 0L)
373                     && ((dst & 0x80000000L) == 0L))
374                 {
375                         flags |= V_FLAG;
376                 }
377                 else if (((src & 0x80000000L) != 0L) &&
378                          ((dst & 0x80000000L) != 0L))
379                 {
380                         flags |= C_FLAG;
381                 }
382         }
383         else
384         {
385                 if (res == 0L)
386                         flags |= Z_FLAG;
387                 if (((src & 0x80000000L) != 0L)
388                     && ((dst & 0x80000000L) != 0L))
389                         flags |= V_FLAG;
390                 if ((dst & 0x80000000L) != 0L
391                     || (src & 0x80000000L) != 0L)
392                         flags |= C_FLAG;
393         }
394
395         if (env->cc_op == CC_OP_SUB
396             || env->cc_op == CC_OP_CMP) {
397                 flags ^= C_FLAG;
398         }
399         evaluate_flags_writeback(flags);
400 }
401
402 void  helper_evaluate_flags_move_4 (void)
403 {
404         uint32_t src;
405         uint32_t res;
406         uint32_t flags = 0;
407
408         src = env->cc_src;
409         res = env->cc_result;
410
411         if ((int32_t)res < 0)
412                 flags |= N_FLAG;
413         else if (res == 0L)
414                 flags |= Z_FLAG;
415
416         evaluate_flags_writeback(flags);
417 }
418 void  helper_evaluate_flags_move_2 (void)
419 {
420         uint32_t src;
421         uint32_t flags = 0;
422         uint16_t res;
423
424         src = env->cc_src;
425         res = env->cc_result;
426
427         if ((int16_t)res < 0L)
428                 flags |= N_FLAG;
429         else if (res == 0)
430                 flags |= Z_FLAG;
431
432         evaluate_flags_writeback(flags);
433 }
434
435 /* TODO: This is expensive. We could split things up and only evaluate part of
436    CCR on a need to know basis. For now, we simply re-evaluate everything.  */
437 void helper_evaluate_flags (void)
438 {
439         uint32_t src;
440         uint32_t dst;
441         uint32_t res;
442         uint32_t flags = 0;
443
444         src = env->cc_src;
445         dst = env->cc_dest;
446         res = env->cc_result;
447
448
449         /* Now, evaluate the flags. This stuff is based on
450            Per Zander's CRISv10 simulator.  */
451         switch (env->cc_size)
452         {
453                 case 1:
454                         if ((res & 0x80L) != 0L)
455                         {
456                                 flags |= N_FLAG;
457                                 if (((src & 0x80L) == 0L)
458                                     && ((dst & 0x80L) == 0L))
459                                 {
460                                         flags |= V_FLAG;
461                                 }
462                                 else if (((src & 0x80L) != 0L)
463                                          && ((dst & 0x80L) != 0L))
464                                 {
465                                         flags |= C_FLAG;
466                                 }
467                         }
468                         else
469                         {
470                                 if ((res & 0xFFL) == 0L)
471                                 {
472                                         flags |= Z_FLAG;
473                                 }
474                                 if (((src & 0x80L) != 0L)
475                                     && ((dst & 0x80L) != 0L))
476                                 {
477                                         flags |= V_FLAG;
478                                 }
479                                 if ((dst & 0x80L) != 0L
480                                     || (src & 0x80L) != 0L)
481                                 {
482                                         flags |= C_FLAG;
483                                 }
484                         }
485                         break;
486                 case 2:
487                         if ((res & 0x8000L) != 0L)
488                         {
489                                 flags |= N_FLAG;
490                                 if (((src & 0x8000L) == 0L)
491                                     && ((dst & 0x8000L) == 0L))
492                                 {
493                                         flags |= V_FLAG;
494                                 }
495                                 else if (((src & 0x8000L) != 0L)
496                                          && ((dst & 0x8000L) != 0L))
497                                 {
498                                         flags |= C_FLAG;
499                                 }
500                         }
501                         else
502                         {
503                                 if ((res & 0xFFFFL) == 0L)
504                                 {
505                                         flags |= Z_FLAG;
506                                 }
507                                 if (((src & 0x8000L) != 0L)
508                                     && ((dst & 0x8000L) != 0L))
509                                 {
510                                         flags |= V_FLAG;
511                                 }
512                                 if ((dst & 0x8000L) != 0L
513                                     || (src & 0x8000L) != 0L)
514                                 {
515                                         flags |= C_FLAG;
516                                 }
517                         }
518                         break;
519                 case 4:
520                         if ((res & 0x80000000L) != 0L)
521                         {
522                                 flags |= N_FLAG;
523                                 if (((src & 0x80000000L) == 0L)
524                                     && ((dst & 0x80000000L) == 0L))
525                                 {
526                                         flags |= V_FLAG;
527                                 }
528                                 else if (((src & 0x80000000L) != 0L) &&
529                                          ((dst & 0x80000000L) != 0L))
530                                 {
531                                         flags |= C_FLAG;
532                                 }
533                         }
534                         else
535                         {
536                                 if (res == 0L)
537                                         flags |= Z_FLAG;
538                                 if (((src & 0x80000000L) != 0L)
539                                     && ((dst & 0x80000000L) != 0L))
540                                         flags |= V_FLAG;
541                                 if ((dst & 0x80000000L) != 0L
542                                     || (src & 0x80000000L) != 0L)
543                                         flags |= C_FLAG;
544                         }
545                         break;
546                 default:
547                         break;
548         }
549
550         if (env->cc_op == CC_OP_SUB
551             || env->cc_op == CC_OP_CMP) {
552                 flags ^= C_FLAG;
553         }
554         evaluate_flags_writeback(flags);
555 }