Annotation of qemu/target-m68k/op.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  m68k micro operations
                      3:  * 
                      4:  *  Copyright (c) 2006 CodeSourcery
                      5:  *  Written by Paul Brook
                      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:  * 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 "exec.h"
                     23: #include "m68k-qreg.h"
                     24: 
                     25: #ifndef offsetof
                     26: #define offsetof(type, field) ((size_t) &((type *)0)->field)
                     27: #endif
                     28: 
                     29: static long qreg_offsets[] = {
                     30: #define DEFO32(name, offset) offsetof(CPUState, offset),
                     31: #define DEFR(name, reg, mode) -1,
                     32: #define DEFF64(name, offset) offsetof(CPUState, offset),
                     33:     0,
                     34: #include "qregs.def"
                     35: };
                     36: 
                     37: #define CPU_FP_STATUS env->fp_status
                     38: 
                     39: #define RAISE_EXCEPTION(n) do { \
                     40:     env->exception_index = n; \
                     41:     cpu_loop_exit(); \
                     42:     } while(0)
                     43: 
                     44: #define get_op helper_get_op
                     45: #define set_op helper_set_op
                     46: #define get_opf64 helper_get_opf64
                     47: #define set_opf64 helper_set_opf64
                     48: uint32_t
                     49: get_op(int qreg)
                     50: {
                     51:     if (qreg == QREG_T0) {
                     52:         return T0;
                     53:     } else if (qreg < TARGET_NUM_QREGS) {
                     54:         return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
                     55:     } else {
                     56:         return env->qregs[qreg - TARGET_NUM_QREGS];
                     57:     }
                     58: }
                     59: 
                     60: void set_op(int qreg, uint32_t val)
                     61: {
                     62:     if (qreg == QREG_T0) {
                     63:         T0 = val;
                     64:     } else if (qreg < TARGET_NUM_QREGS) {
                     65:         *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
                     66:     } else {
                     67:         env->qregs[qreg - TARGET_NUM_QREGS] = val;
                     68:     }
                     69: }
                     70: 
                     71: float64 get_opf64(int qreg)
                     72: {
                     73:     if (qreg < TARGET_NUM_QREGS) {
                     74:         return *(float64 *)(((long)env) + qreg_offsets[qreg]);
                     75:     } else {
                     76:         return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
                     77:     }
                     78: }
                     79: 
                     80: void set_opf64(int qreg, float64 val)
                     81: {
                     82:     if (qreg < TARGET_NUM_QREGS) {
                     83:         *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
                     84:     } else {
                     85:         *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val;
                     86:     }
                     87: }
                     88: 
                     89: #define OP(name) void OPPROTO op_##name (void)
                     90: 
                     91: OP(mov32)
                     92: {
                     93:     set_op(PARAM1, get_op(PARAM2));
                     94:     FORCE_RET();
                     95: }
                     96: 
                     97: OP(mov32_im)
                     98: {
                     99:     set_op(PARAM1, PARAM2);
                    100:     FORCE_RET();
                    101: }
                    102: 
                    103: OP(movf64)
                    104: {
                    105:     set_opf64(PARAM1, get_opf64(PARAM2));
                    106:     FORCE_RET();
                    107: }
                    108: 
                    109: OP(zerof64)
                    110: {
                    111:     set_opf64(PARAM1, 0);
                    112:     FORCE_RET();
                    113: }
                    114: 
                    115: OP(add32)
                    116: {
                    117:     uint32_t op2 = get_op(PARAM2);
                    118:     uint32_t op3 = get_op(PARAM3);
                    119:     set_op(PARAM1, op2 + op3);
                    120:     FORCE_RET();
                    121: }
                    122: 
                    123: OP(sub32)
                    124: {
                    125:     uint32_t op2 = get_op(PARAM2);
                    126:     uint32_t op3 = get_op(PARAM3);
                    127:     set_op(PARAM1, op2 - op3);
                    128:     FORCE_RET();
                    129: }
                    130: 
                    131: OP(mul32)
                    132: {
                    133:     uint32_t op2 = get_op(PARAM2);
                    134:     uint32_t op3 = get_op(PARAM3);
                    135:     set_op(PARAM1, op2 * op3);
                    136:     FORCE_RET();
                    137: }
                    138: 
                    139: OP(not32)
                    140: {
                    141:     uint32_t arg = get_op(PARAM2);
                    142:     set_op(PARAM1, ~arg);
                    143:     FORCE_RET();
                    144: }
                    145: 
                    146: OP(neg32)
                    147: {
                    148:     uint32_t arg = get_op(PARAM2);
                    149:     set_op(PARAM1, -arg);
                    150:     FORCE_RET();
                    151: }
                    152: 
                    153: OP(bswap32)
                    154: {
                    155:     uint32_t arg = get_op(PARAM2);
                    156:     arg = (arg >> 24) | (arg << 24)
                    157:           | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000);
                    158:     set_op(PARAM1, arg);
                    159:     FORCE_RET();
                    160: }
                    161: 
                    162: OP(btest)
                    163: {
                    164:     uint32_t op1 = get_op(PARAM1);
                    165:     uint32_t op2 = get_op(PARAM2);
                    166:     if (op1 & op2)
                    167:         env->cc_dest &= ~CCF_Z;
                    168:     else
                    169:         env->cc_dest |= CCF_Z;
                    170:     FORCE_RET();
                    171: }
                    172: 
                    173: OP(addx_cc)
                    174: {
                    175:     uint32_t op1 = get_op(PARAM1);
                    176:     uint32_t op2 = get_op(PARAM2);
                    177:     uint32_t res;
                    178:     if (env->cc_x) {
                    179:         env->cc_x = (op1 <= op2);
                    180:         env->cc_op = CC_OP_SUBX;
                    181:         res = op1 - (op2 + 1);
                    182:     } else {
                    183:         env->cc_x = (op1 < op2);
                    184:         env->cc_op = CC_OP_SUB;
                    185:         res = op1 - op2;
                    186:     }
                    187:     set_op(PARAM1, res);
                    188:     FORCE_RET();
                    189: }
                    190: 
                    191: OP(subx_cc)
                    192: {
                    193:     uint32_t op1 = get_op(PARAM1);
                    194:     uint32_t op2 = get_op(PARAM2);
                    195:     uint32_t res;
                    196:     if (env->cc_x) {
                    197:         res = op1 + op2 + 1;
                    198:         env->cc_x = (res <= op2);
                    199:         env->cc_op = CC_OP_ADDX;
                    200:     } else {
                    201:         res = op1 + op2;
                    202:         env->cc_x = (res < op2);
                    203:         env->cc_op = CC_OP_ADD;
                    204:     }
                    205:     set_op(PARAM1, res);
                    206:     FORCE_RET();
                    207: }
                    208: 
                    209: /* Logic ops.  */
                    210: 
                    211: OP(and32)
                    212: {
                    213:     uint32_t op2 = get_op(PARAM2);
                    214:     uint32_t op3 = get_op(PARAM3);
                    215:     set_op(PARAM1, op2 & op3);
                    216:     FORCE_RET();
                    217: }
                    218: 
                    219: OP(or32)
                    220: {
                    221:     uint32_t op2 = get_op(PARAM2);
                    222:     uint32_t op3 = get_op(PARAM3);
                    223:     set_op(PARAM1, op2 | op3);
                    224:     FORCE_RET();
                    225: }
                    226: 
                    227: OP(xor32)
                    228: {
                    229:     uint32_t op2 = get_op(PARAM2);
                    230:     uint32_t op3 = get_op(PARAM3);
                    231:     set_op(PARAM1, op2 ^ op3);
                    232:     FORCE_RET();
                    233: }
                    234: 
                    235: /* Shifts.  */
                    236: OP(shl32)
                    237: {
                    238:     uint32_t op2 = get_op(PARAM2);
                    239:     uint32_t op3 = get_op(PARAM3);
                    240:     uint32_t result;
                    241:     result = op2 << op3;
                    242:     set_op(PARAM1, result);
                    243:     FORCE_RET();
                    244: }
                    245: 
                    246: OP(shl_cc)
                    247: {
                    248:     uint32_t op1 = get_op(PARAM1);
                    249:     uint32_t op2 = get_op(PARAM2);
                    250:     uint32_t result;
                    251:     result = op1 << op2;
                    252:     set_op(PARAM1, result);
                    253:     env->cc_x = (op1 << (op2 - 1)) & 1;
                    254:     FORCE_RET();
                    255: }
                    256: 
                    257: OP(shr32)
                    258: {
                    259:     uint32_t op2 = get_op(PARAM2);
                    260:     uint32_t op3 = get_op(PARAM3);
                    261:     uint32_t result;
                    262:     result = op2 >> op3;
                    263:     set_op(PARAM1, result);
                    264:     FORCE_RET();
                    265: }
                    266: 
                    267: OP(shr_cc)
                    268: {
                    269:     uint32_t op1 = get_op(PARAM1);
                    270:     uint32_t op2 = get_op(PARAM2);
                    271:     uint32_t result;
                    272:     result = op1 >> op2;
                    273:     set_op(PARAM1, result);
                    274:     env->cc_x = (op1 >> (op2 - 1)) & 1;
                    275:     FORCE_RET();
                    276: }
                    277: 
                    278: OP(sar_cc)
                    279: {
                    280:     int32_t op1 = get_op(PARAM1);
                    281:     uint32_t op2 = get_op(PARAM2);
                    282:     uint32_t result;
                    283:     result = op1 >> op2;
                    284:     set_op(PARAM1, result);
                    285:     env->cc_x = (op1 >> (op2 - 1)) & 1;
                    286:     FORCE_RET();
                    287: }
                    288: 
                    289: /* Value extend.  */
                    290: 
                    291: OP(ext8u32)
                    292: {
                    293:     uint32_t op2 = get_op(PARAM2);
                    294:     set_op(PARAM1, (uint8_t)op2);
                    295:     FORCE_RET();
                    296: }
                    297: 
                    298: OP(ext8s32)
                    299: {
                    300:     uint32_t op2 = get_op(PARAM2);
                    301:     set_op(PARAM1, (int8_t)op2);
                    302:     FORCE_RET();
                    303: }
                    304: 
                    305: OP(ext16u32)
                    306: {
                    307:     uint32_t op2 = get_op(PARAM2);
                    308:     set_op(PARAM1, (uint16_t)op2);
                    309:     FORCE_RET();
                    310: }
                    311: 
                    312: OP(ext16s32)
                    313: {
                    314:     uint32_t op2 = get_op(PARAM2);
                    315:     set_op(PARAM1, (int16_t)op2);
                    316:     FORCE_RET();
                    317: }
                    318: 
                    319: /* Load/store ops.  */
                    320: OP(ld8u32)
                    321: {
                    322:     uint32_t addr = get_op(PARAM2);
                    323:     set_op(PARAM1, ldub(addr));
                    324:     FORCE_RET();
                    325: }
                    326: 
                    327: OP(ld8s32)
                    328: {
                    329:     uint32_t addr = get_op(PARAM2);
                    330:     set_op(PARAM1, ldsb(addr));
                    331:     FORCE_RET();
                    332: }
                    333: 
                    334: OP(ld16u32)
                    335: {
                    336:     uint32_t addr = get_op(PARAM2);
                    337:     set_op(PARAM1, lduw(addr));
                    338:     FORCE_RET();
                    339: }
                    340: 
                    341: OP(ld16s32)
                    342: {
                    343:     uint32_t addr = get_op(PARAM2);
                    344:     set_op(PARAM1, ldsw(addr));
                    345:     FORCE_RET();
                    346: }
                    347: 
                    348: OP(ld32)
                    349: {
                    350:     uint32_t addr = get_op(PARAM2);
                    351:     set_op(PARAM1, ldl(addr));
                    352:     FORCE_RET();
                    353: }
                    354: 
                    355: OP(st8)
                    356: {
                    357:     uint32_t addr = get_op(PARAM1);
                    358:     stb(addr, get_op(PARAM2));
                    359:     FORCE_RET();
                    360: }
                    361: 
                    362: OP(st16)
                    363: {
                    364:     uint32_t addr = get_op(PARAM1);
                    365:     stw(addr, get_op(PARAM2));
                    366:     FORCE_RET();
                    367: }
                    368: 
                    369: OP(st32)
                    370: {
                    371:     uint32_t addr = get_op(PARAM1);
                    372:     stl(addr, get_op(PARAM2));
                    373:     FORCE_RET();
                    374: }
                    375: 
                    376: OP(ldf64)
                    377: {
                    378:     uint32_t addr = get_op(PARAM2);
                    379:     set_opf64(PARAM1, ldfq(addr));
                    380:     FORCE_RET();
                    381: }
                    382: 
                    383: OP(stf64)
                    384: {
                    385:     uint32_t addr = get_op(PARAM1);
                    386:     stfq(addr, get_opf64(PARAM2));
                    387:     FORCE_RET();
                    388: }
                    389: 
                    390: OP(flush_flags)
                    391: {
                    392:     int cc_op  = PARAM1;
                    393:     if (cc_op == CC_OP_DYNAMIC)
                    394:         cc_op = env->cc_op;
                    395:     cpu_m68k_flush_flags(env, cc_op);
                    396:     FORCE_RET();
                    397: }
                    398: 
                    399: OP(divu)
                    400: {
                    401:     uint32_t num;
                    402:     uint32_t den;
                    403:     uint32_t quot;
                    404:     uint32_t rem;
                    405:     uint32_t flags;
                    406:     
                    407:     num = env->div1;
                    408:     den = env->div2;
                    409:     /* ??? This needs to make sure the throwing location is accurate.  */
                    410:     if (den == 0)
                    411:         RAISE_EXCEPTION(EXCP_DIV0);
                    412:     quot = num / den;
                    413:     rem = num % den;
                    414:     flags = 0;
                    415:     /* Avoid using a PARAM1 of zero.  This breaks dyngen because it uses
                    416:        the address of a symbol, and gcc knows symbols can't have address
                    417:        zero.  */
                    418:     if (PARAM1 == 2 && quot > 0xffff)
                    419:         flags |= CCF_V;
                    420:     if (quot == 0)
                    421:         flags |= CCF_Z;
                    422:     else if ((int32_t)quot < 0)
                    423:         flags |= CCF_N;
                    424:     env->div1 = quot;
                    425:     env->div2 = rem;
                    426:     env->cc_dest = flags;
                    427:     FORCE_RET();
                    428: }
                    429: 
                    430: OP(divs)
                    431: {
                    432:     int32_t num;
                    433:     int32_t den;
                    434:     int32_t quot;
                    435:     int32_t rem;
                    436:     int32_t flags;
                    437:     
                    438:     num = env->div1;
                    439:     den = env->div2;
                    440:     if (den == 0)
                    441:         RAISE_EXCEPTION(EXCP_DIV0);
                    442:     quot = num / den;
                    443:     rem = num % den;
                    444:     flags = 0;
                    445:     if (PARAM1 == 2 && quot != (int16_t)quot)
                    446:         flags |= CCF_V;
                    447:     if (quot == 0)
                    448:         flags |= CCF_Z;
                    449:     else if (quot < 0)
                    450:         flags |= CCF_N;
                    451:     env->div1 = quot;
                    452:     env->div2 = rem;
                    453:     env->cc_dest = flags;
                    454:     FORCE_RET();
                    455: }
                    456: 
                    457: OP(raise_exception)
                    458: {
                    459:     RAISE_EXCEPTION(PARAM1);
                    460:     FORCE_RET();
                    461: }
                    462: 
                    463: /* Floating point comparison sets flags differently to other instructions.  */
                    464: 
                    465: OP(sub_cmpf64)
                    466: {
                    467:     float64 src0;
                    468:     float64 src1;
                    469:     src0 = get_opf64(PARAM2);
                    470:     src1 = get_opf64(PARAM3);
                    471:     set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
                    472:     FORCE_RET();
                    473: }
                    474: 
                    475: OP(update_xflag_tst)
                    476: {
                    477:     uint32_t op1 = get_op(PARAM1);
                    478:     env->cc_x = op1;
                    479:     FORCE_RET();
                    480: }
                    481: 
                    482: OP(update_xflag_lt)
                    483: {
                    484:     uint32_t op1 = get_op(PARAM1);
                    485:     uint32_t op2 = get_op(PARAM2);
                    486:     env->cc_x = (op1 < op2);
                    487:     FORCE_RET();
                    488: }
                    489: 
                    490: OP(get_xflag)
                    491: {
                    492:     set_op(PARAM1, env->cc_x);
                    493:     FORCE_RET();
                    494: }
                    495: 
                    496: OP(logic_cc)
                    497: {
                    498:     uint32_t op1 = get_op(PARAM1);
                    499:     env->cc_dest = op1;
                    500:     FORCE_RET();
                    501: }
                    502: 
                    503: OP(update_cc_add)
                    504: {
                    505:     uint32_t op1 = get_op(PARAM1);
                    506:     uint32_t op2 = get_op(PARAM2);
                    507:     env->cc_dest = op1;
                    508:     env->cc_src = op2;
                    509:     FORCE_RET();
                    510: }
                    511: 
                    512: OP(fp_result)
                    513: {
                    514:     env->fp_result = get_opf64(PARAM1);
                    515:     FORCE_RET();
                    516: }
                    517: 
                    518: OP(jmp)
                    519: {
                    520:     GOTO_LABEL_PARAM(1);
                    521: }
                    522: 
                    523: /* These ops involve a function call, which probably requires a stack frame
                    524:    and breaks things on some hosts.  */
                    525: OP(jmp_z32)
                    526: {
                    527:     uint32_t arg = get_op(PARAM1);
                    528:     if (arg == 0)
                    529:         GOTO_LABEL_PARAM(2);
                    530:     FORCE_RET();
                    531: }
                    532: 
                    533: OP(jmp_nz32)
                    534: {
                    535:     uint32_t arg = get_op(PARAM1);
                    536:     if (arg != 0)
                    537:         GOTO_LABEL_PARAM(2);
                    538:     FORCE_RET();
                    539: }
                    540: 
                    541: OP(jmp_s32)
                    542: {
                    543:     int32_t arg = get_op(PARAM1);
                    544:     if (arg < 0)
                    545:         GOTO_LABEL_PARAM(2);
                    546:     FORCE_RET();
                    547: }
                    548: 
                    549: OP(jmp_ns32)
                    550: {
                    551:     int32_t arg = get_op(PARAM1);
                    552:     if (arg >= 0)
                    553:         GOTO_LABEL_PARAM(2);
                    554:     FORCE_RET();
                    555: }
                    556: 
                    557: void OPPROTO op_goto_tb0(void)
                    558: {
                    559:     GOTO_TB(op_goto_tb0, PARAM1, 0);
                    560: }
                    561: 
                    562: void OPPROTO op_goto_tb1(void)
                    563: {
                    564:     GOTO_TB(op_goto_tb1, PARAM1, 1);
                    565: }
                    566: 
                    567: OP(exit_tb)
                    568: {
                    569:     EXIT_TB();
                    570: }
                    571: 
                    572: 
                    573: /* Floating point.  */
                    574: OP(f64_to_i32)
                    575: {
                    576:     set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
                    577:     FORCE_RET();
                    578: }
                    579: 
                    580: OP(f64_to_f32)
                    581: {
                    582:     union {
                    583:         float32 f;
                    584:         uint32_t i;
                    585:     } u;
                    586:     u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
                    587:     set_op(PARAM1, u.i);
                    588:     FORCE_RET();
                    589: }
                    590: 
                    591: OP(i32_to_f64)
                    592: {
                    593:     set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
                    594:     FORCE_RET();
                    595: }
                    596: 
                    597: OP(f32_to_f64)
                    598: {
                    599:     union {
                    600:         float32 f;
                    601:         uint32_t i;
                    602:     } u;
                    603:     u.i = get_op(PARAM2);
                    604:     set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
                    605:     FORCE_RET();
                    606: }
                    607: 
                    608: OP(absf64)
                    609: {
                    610:     float64 op0 = get_opf64(PARAM2);
                    611:     set_opf64(PARAM1, float64_abs(op0));
                    612:     FORCE_RET();
                    613: }
                    614: 
                    615: OP(chsf64)
                    616: {
                    617:     float64 op0 = get_opf64(PARAM2);
                    618:     set_opf64(PARAM1, float64_chs(op0));
                    619:     FORCE_RET();
                    620: }
                    621: 
                    622: OP(sqrtf64)
                    623: {
                    624:     float64 op0 = get_opf64(PARAM2);
                    625:     set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
                    626:     FORCE_RET();
                    627: }
                    628: 
                    629: OP(addf64)
                    630: {
                    631:     float64 op0 = get_opf64(PARAM2);
                    632:     float64 op1 = get_opf64(PARAM3);
                    633:     set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
                    634:     FORCE_RET();
                    635: }
                    636: 
                    637: OP(subf64)
                    638: {
                    639:     float64 op0 = get_opf64(PARAM2);
                    640:     float64 op1 = get_opf64(PARAM3);
                    641:     set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
                    642:     FORCE_RET();
                    643: }
                    644: 
                    645: OP(mulf64)
                    646: {
                    647:     float64 op0 = get_opf64(PARAM2);
                    648:     float64 op1 = get_opf64(PARAM3);
                    649:     set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
                    650:     FORCE_RET();
                    651: }
                    652: 
                    653: OP(divf64)
                    654: {
                    655:     float64 op0 = get_opf64(PARAM2);
                    656:     float64 op1 = get_opf64(PARAM3);
                    657:     set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
                    658:     FORCE_RET();
                    659: }
                    660: 
                    661: OP(iround_f64)
                    662: {
                    663:     float64 op0 = get_opf64(PARAM2);
                    664:     set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
                    665:     FORCE_RET();
                    666: }
                    667: 
                    668: OP(itrunc_f64)
                    669: {
                    670:     float64 op0 = get_opf64(PARAM2);
                    671:     set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
                    672:     FORCE_RET();
                    673: }
                    674: 
                    675: OP(compare_quietf64)
                    676: {
                    677:     float64 op0 = get_opf64(PARAM2);
                    678:     float64 op1 = get_opf64(PARAM3);
                    679:     set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
                    680:     FORCE_RET();
                    681: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.