home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p1 / Runtime (.c & .h) / emul.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-26  |  15.1 KB  |  434 lines  |  [TEXT/KAHL]

  1. /* Emulation of M68020 and M68881 instructions */
  2.  
  3. #include "params.h"
  4. #include "gambit.h"
  5. #include "struct.h"
  6. #include "os.h"
  7. #include "opcodes.h"
  8.  
  9.  
  10. /*---------------------------------------------------------------------------*/
  11.  
  12. char *emul_code_alloc, *emul_code_top;
  13.  
  14.  
  15. #define MAX_GEN_WORDS 32
  16.  
  17. short gen[MAX_GEN_WORDS];
  18. short *gen_ptr;
  19. long code_len;
  20.  
  21. void gen_ea( ea, code_ptr )
  22. long ea;
  23. short *code_ptr;
  24. { if (((ea&0x38)==0x28) || (ea==0x3c) || (ea==0x3a))
  25.     *gen_ptr++ = code_ptr[code_len++];
  26.   if (ea==0x3c) *gen_ptr++ = code_ptr[code_len++];
  27. }
  28.  
  29. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  30.  
  31. void long_mul()
  32. { pstate->temp[1] = pstate->temp[1] * pstate->temp[0];
  33. }
  34.  
  35.  
  36. void long_div()
  37. { pstate->temp[1] = pstate->temp[2] % pstate->temp[0];
  38.   pstate->temp[2] = pstate->temp[2] / pstate->temp[0];
  39. }
  40.  
  41.  
  42. long emul_M68020_instr( code_ptr )
  43. short *code_ptr;
  44. { short *p1, *p2, *p3;
  45.   gen_ptr = gen;
  46.   code_len = 2;
  47.   *gen_ptr++ = MOVE_L_PINCA7_A5_DISP_OP;
  48.   *gen_ptr++ = pstate_offset( &pstate->temp[3] );
  49.   switch (code_ptr[0] & 0xffc0)
  50.   { case 0x4c00: /* MULS.L <ea>,Dl */
  51.     { long ea, dl_reg;
  52.       if ((code_ptr[1] & 0x8ff8) != 0x0800) goto error;
  53.       dl_reg = (code_ptr[1] & 0x7000) >> 12;
  54.       ea = code_ptr[0] & 0x3f;
  55.       *gen_ptr++ = MOVE_L_EA_A5_DISP_OP+ea;
  56.       gen_ea( ea, code_ptr );
  57.       *gen_ptr++ = pstate_offset( &pstate->temp[0] );
  58.       *gen_ptr++ = MOVE_L_EA_A5_DISP_OP+dl_reg;
  59.       *gen_ptr++ = pstate_offset( &pstate->temp[1] );
  60.       *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  61.       *(void (**)())gen_ptr = long_mul;  gen_ptr += 2;
  62.       *gen_ptr++ = JSRA6_DISP_OP;
  63.       *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  64.       *gen_ptr++ = MOVE_L_A5_DISP_EA_OP+(dl_reg<<9);
  65.       *gen_ptr++ = pstate_offset( &pstate->temp[1] );
  66.       break;
  67.     }
  68.     case 0x4c40: /* DIVS.L <ea>,Dr:Dq */
  69.     { long ea, dr_reg, dq_reg;
  70.       if ((code_ptr[1] & 0x8ff8) != 0x0800) goto error;
  71.       dr_reg = code_ptr[1] & 0x7;
  72.       dq_reg = (code_ptr[1] & 0x7000) >> 12;
  73.       ea = code_ptr[0] & 0x3f;
  74.       *gen_ptr++ = MOVE_L_EA_A5_DISP_OP+ea;
  75.       gen_ea( ea, code_ptr );
  76.       *gen_ptr++ = pstate_offset( &pstate->temp[0] );
  77.       *gen_ptr++ = MOVE_L_EA_A5_DISP_OP+dr_reg;
  78.       *gen_ptr++ = pstate_offset( &pstate->temp[1] );
  79.       *gen_ptr++ = MOVE_L_EA_A5_DISP_OP+dq_reg;
  80.       *gen_ptr++ = pstate_offset( &pstate->temp[2] );
  81.       *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  82.       *(void (**)())gen_ptr = long_div;  gen_ptr += 2;
  83.       *gen_ptr++ = JSRA6_DISP_OP;
  84.       *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  85.       *gen_ptr++ = MOVE_L_A5_DISP_EA_OP+(dr_reg<<9);
  86.       *gen_ptr++ = pstate_offset( &pstate->temp[1] );
  87.       *gen_ptr++ = MOVE_L_A5_DISP_EA_OP+(dq_reg<<9);
  88.       *gen_ptr++ = pstate_offset( &pstate->temp[2] );
  89.       break;
  90.     }
  91.     default:
  92.       goto error;
  93.   }
  94.   *gen_ptr++ = MOVE_L_A5_DISP_PDECA7_OP;
  95.   *gen_ptr++ = pstate_offset( &pstate->temp[3] );
  96.   *gen_ptr++ = RTS_OP;
  97.   p1 = (short *)pstate->emul_code_bot;
  98.   while (p1 < (short *)emul_code_alloc)
  99.   { p2 = p1;
  100.     p3 = gen;
  101.     while ((p3 < gen_ptr) && (*p2 == *p3)) { p2++; p3++; }
  102.     if (p3 == gen_ptr)
  103.     { *code_ptr++ = JSRA5_DISP_OP;
  104.       *code_ptr++ = pstate_offset( p1 );
  105.       while (code_len > 2) { *code_ptr++ = NOP_OP; code_len--; }
  106.       return 0;
  107.     }
  108.     p1++;
  109.   }
  110.   if (emul_code_alloc+(gen_ptr-gen)*sizeof(short) > emul_code_top)
  111.   { os_err = "Emulation code memory overflow"; return 1; }
  112.   *code_ptr++ = JSRA5_DISP_OP;
  113.   *code_ptr++ = pstate_offset( emul_code_alloc );
  114.   while (code_len > 2) { *code_ptr++ = NOP_OP; code_len--; }
  115.   p1 = gen;
  116.   while (p1 < gen_ptr)
  117.   { *(short *)emul_code_alloc = *p1++;
  118.     emul_code_alloc += sizeof(short);
  119.   }
  120.   return 0;
  121.   error:
  122.   os_err = "Unknown M68020 instruction";
  123.   return 1;
  124. }
  125.  
  126. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  127.  
  128. #ifdef NO_EMUL_M68881
  129.  
  130. long emul_M68881_instr( code_ptr )
  131. short *code_ptr;
  132. { os_err = "No M68881 emulation";
  133.   return 1;
  134. }
  135.  
  136. #else
  137.  
  138. #include <math.h>
  139.  
  140. int matherr( x )
  141. struct exception *x;
  142. { return 1; /* don't trap on error */
  143. }
  144.  
  145. void fp_mov_l_to_fp0()   { pstate->fp0 = pstate->temp[0]; }
  146. void fp_mov_l_from_fp0() { pstate->temp[0] = pstate->fp0; }
  147.  
  148. void fp_mov_d_to_fp0()   { pstate->fp0 = *pstate->fp_ptr; }
  149. void fp_mov_d_from_fp0() { *pstate->fp_ptr = pstate->fp0; }
  150.  
  151. void fp_abs_to_fp0()     { pstate->fp0 = fabs( (double)*pstate->fp_ptr ); }
  152. void fp_abs_from_fp0()   { *pstate->fp_ptr = fabs( (double)pstate->fp0 ); }
  153.  
  154. void fp_int_to_fp0()
  155. { double x = *pstate->fp_ptr;
  156.   double y = fmod( x, 2.0 );
  157.   if (y == 0.5)
  158.     pstate->fp0 = x-0.5;
  159.   else if (y == -1.5)
  160.     pstate->fp0 = x-0.5;
  161.   else 
  162.     pstate->fp0 = floor( 0.5+x );
  163. }
  164.  
  165. void fp_int_from_fp0()
  166. { double x = pstate->fp0;
  167.   double y = fmod( x, 2.0 );
  168.   if (y == 0.5)
  169.     *pstate->fp_ptr = x-0.5;
  170.   else if (y == -1.5)
  171.     *pstate->fp_ptr = x-0.5;
  172.   else 
  173.     *pstate->fp_ptr = floor( 0.5+x );
  174. }
  175.  
  176. void fp_intrz_to_fp0()
  177. { if (*pstate->fp_ptr < 0.0)
  178.     pstate->fp0 = -floor( -(double)*pstate->fp_ptr );
  179.   else
  180.     pstate->fp0 = floor( (double)*pstate->fp_ptr );
  181. }
  182.  
  183. void fp_intrz_from_fp0()
  184. { if (pstate->fp0 < 0.0)
  185.     *pstate->fp_ptr = -floor( -(double)pstate->fp0 );
  186.   else
  187.     *pstate->fp_ptr = floor( (double)pstate->fp0 );
  188. }
  189.  
  190. void fp_sqrt_to_fp0()    { pstate->fp0 = sqrt( (double)*pstate->fp_ptr ); }
  191. void fp_sqrt_from_fp0()  { *pstate->fp_ptr = sqrt( (double)pstate->fp0 ); }
  192.  
  193. void fp_etox_to_fp0()    { pstate->fp0 = exp( (double)*pstate->fp_ptr ); }
  194. void fp_etox_from_fp0()  { *pstate->fp_ptr = exp( (double)pstate->fp0 ); }
  195.  
  196. void fp_logn_to_fp0()    { pstate->fp0 = log( (double)*pstate->fp_ptr ); }
  197. void fp_logn_from_fp0()  { *pstate->fp_ptr = log( (double)pstate->fp0 ); }
  198.  
  199. void fp_sin_to_fp0()     { pstate->fp0 = sin( (double)*pstate->fp_ptr ); }
  200. void fp_sin_from_fp0()   { *pstate->fp_ptr = sin( (double)pstate->fp0 ); }
  201.  
  202. void fp_cos_to_fp0()     { pstate->fp0 = cos( (double)*pstate->fp_ptr ); }
  203. void fp_cos_from_fp0()   { *pstate->fp_ptr = cos( (double)pstate->fp0 ); }
  204.  
  205. void fp_tan_to_fp0()     { pstate->fp0 = tan( (double)*pstate->fp_ptr ); }
  206. void fp_tan_from_fp0()   { *pstate->fp_ptr = tan( (double)pstate->fp0 ); }
  207.  
  208. void fp_asin_to_fp0()    { pstate->fp0 = asin( (double)*pstate->fp_ptr ); }
  209. void fp_asin_from_fp0()  { *pstate->fp_ptr = asin( (double)pstate->fp0 ); }
  210.  
  211. void fp_acos_to_fp0()    { pstate->fp0 = acos( (double)*pstate->fp_ptr ); }
  212. void fp_acos_from_fp0()  { *pstate->fp_ptr = acos( (double)pstate->fp0 ); }
  213.  
  214. void fp_atan_to_fp0()    { pstate->fp0 = atan( (double)*pstate->fp_ptr ); }
  215. void fp_atan_from_fp0()  { *pstate->fp_ptr = atan( (double)pstate->fp0 ); }
  216.  
  217. void fp_add_to_fp0()     { pstate->fp0 = pstate->fp0 + *pstate->fp_ptr; }
  218. void fp_add_from_fp0()   { *pstate->fp_ptr = *pstate->fp_ptr + pstate->fp0; }
  219.  
  220. void fp_sub_to_fp0()     { pstate->fp0 = pstate->fp0 - *pstate->fp_ptr; }
  221. void fp_sub_from_fp0()   { *pstate->fp_ptr = *pstate->fp_ptr - pstate->fp0; }
  222.  
  223. void fp_mul_to_fp0()     { pstate->fp0 = pstate->fp0 * *pstate->fp_ptr; }
  224. void fp_mul_from_fp0()   { *pstate->fp_ptr = *pstate->fp_ptr * pstate->fp0; }
  225.  
  226. void fp_div_to_fp0()     { pstate->fp0 = pstate->fp0 / *pstate->fp_ptr; }
  227. void fp_div_from_fp0()   { *pstate->fp_ptr = *pstate->fp_ptr / pstate->fp0; }
  228.  
  229. void fp_cmp_to_fp0()     { pstate->fp_cmp1 = *pstate->fp_ptr; pstate->fp_cmp2 = pstate->fp0; }
  230. void fp_cmp_from_fp0()   { pstate->fp_cmp1 = pstate->fp0; pstate->fp_cmp2 = *pstate->fp_ptr; }
  231.  
  232.  
  233. void fp_beq()
  234. { if (pstate->fp_cmp2 == pstate->fp_cmp1) pstate->temp[3] += pstate->temp[0];
  235. }
  236.  
  237.  
  238. void fp_bne()
  239. { if (pstate->fp_cmp2 != pstate->fp_cmp1) pstate->temp[3] += pstate->temp[0];
  240. }
  241.  
  242.  
  243. void fp_blt()
  244. { if (pstate->fp_cmp2 < pstate->fp_cmp1) pstate->temp[3] += pstate->temp[0];
  245. }
  246.  
  247.  
  248. void fp_bgt()
  249. { if (pstate->fp_cmp2 > pstate->fp_cmp1) pstate->temp[3] += pstate->temp[0];
  250. }
  251.  
  252.  
  253. void fp_ble()
  254. { if (pstate->fp_cmp2 <= pstate->fp_cmp1) pstate->temp[3] += pstate->temp[0];
  255. }
  256.  
  257.  
  258. void fp_bge()
  259. { if (pstate->fp_cmp2 >= pstate->fp_cmp1) pstate->temp[3] += pstate->temp[0];
  260. }
  261.  
  262.  
  263. long emul_M68881_instr( code_ptr )
  264. short *code_ptr;
  265. { short *p1, *p2, *p3;
  266.   gen_ptr = gen;
  267.   code_len = 2;
  268.   *gen_ptr++ = MOVE_L_PINCA7_A5_DISP_OP;
  269.   *gen_ptr++ = pstate_offset( &pstate->temp[3] );
  270.   switch (code_ptr[0] & 0xffc0)
  271.   { case 0xf200: /* floating point operation */
  272.     { long ea, f_reg, op;
  273.       ea = code_ptr[0] & 0x003f;
  274.       op = code_ptr[1] & 0x003f;
  275.       f_reg = (code_ptr[1] & 0x0380) >> 7;
  276.       if (f_reg != 0) goto error;
  277.       if (op == 0) /* fmov ? */
  278.         switch (code_ptr[1] & 0xfc00)
  279.         { case 0x4000: /* fmov.l <ea>,fp0 */
  280.             *gen_ptr++ = MOVE_L_EA_A5_DISP_OP+ea;
  281.             gen_ea( ea, code_ptr );
  282.             *gen_ptr++ = pstate_offset( &pstate->temp[0] );
  283.             *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  284.             *(void (**)())gen_ptr = fp_mov_l_to_fp0;  gen_ptr += 2;
  285.             *gen_ptr++ = JSRA6_DISP_OP;
  286.             *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  287.             break;
  288.           case 0x5400: /* fmov.d <ea>,fp0 */
  289.             *gen_ptr++ = PEA_OP+ea;
  290.             gen_ea( ea, code_ptr );
  291.             *gen_ptr++ = MOVE_L_PINCA7_A5_DISP_OP;
  292.             *gen_ptr++ = pstate_offset( &pstate->fp_ptr );
  293.             *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  294.             *(void (**)())gen_ptr = fp_mov_d_to_fp0;  gen_ptr += 2;
  295.             *gen_ptr++ = JSRA6_DISP_OP;
  296.             *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  297.             break;
  298.           case 0x6000: /* fmov.l fp0,<ea> */
  299.             *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  300.             *(void (**)())gen_ptr = fp_mov_l_from_fp0;  gen_ptr += 2;
  301.             *gen_ptr++ = JSRA6_DISP_OP;
  302.             *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  303.             *gen_ptr++ = MOVE_L_A5_DISP_EA_OP+((ea&0x07)<<9)+((ea&0x38)<<3);
  304.             *gen_ptr++ = pstate_offset( &pstate->temp[0] );
  305.             gen_ea( ea, code_ptr );
  306.             break;
  307.           case 0x7400: /* fmov.d fp0,<ea> */
  308.             *gen_ptr++ = PEA_OP+ea;
  309.             gen_ea( ea, code_ptr );
  310.             *gen_ptr++ = MOVE_L_PINCA7_A5_DISP_OP;
  311.             *gen_ptr++ = pstate_offset( &pstate->fp_ptr );
  312.             *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  313.             *(void (**)())gen_ptr = fp_mov_d_from_fp0;  gen_ptr += 2;
  314.             *gen_ptr++ = JSRA6_DISP_OP;
  315.             *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  316.             break;
  317.           default:
  318.             goto error;
  319.           }
  320.       else
  321.       { if ((code_ptr[1] & 0xdc00) != 0x5400) goto error;
  322.         *gen_ptr++ = PEA_OP+ea;
  323.         gen_ea( ea, code_ptr );
  324.         *gen_ptr++ = MOVE_L_PINCA7_A5_DISP_OP;
  325.         *gen_ptr++ = pstate_offset( &pstate->fp_ptr );
  326.         *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  327.         if ((code_ptr[1] & 0x2000) == 0)
  328.           switch (op)
  329.           { case 0x01: *(void (**)())gen_ptr = fp_int_to_fp0;   break;
  330.             case 0x03: *(void (**)())gen_ptr = fp_intrz_to_fp0; break;
  331.             case 0x04: *(void (**)())gen_ptr = fp_sqrt_to_fp0;  break;
  332.             case 0x0a: *(void (**)())gen_ptr = fp_atan_to_fp0;  break;
  333.             case 0x0c: *(void (**)())gen_ptr = fp_asin_to_fp0;  break;
  334.             case 0x0e: *(void (**)())gen_ptr = fp_sin_to_fp0;   break;
  335.             case 0x0f: *(void (**)())gen_ptr = fp_tan_to_fp0;   break;
  336.             case 0x10: *(void (**)())gen_ptr = fp_etox_to_fp0;  break;
  337.             case 0x14: *(void (**)())gen_ptr = fp_logn_to_fp0;  break;
  338.             case 0x18: *(void (**)())gen_ptr = fp_abs_to_fp0;   break;
  339.             case 0x1c: *(void (**)())gen_ptr = fp_acos_to_fp0;  break;
  340.             case 0x1d: *(void (**)())gen_ptr = fp_cos_to_fp0;   break;
  341.             case 0x20: *(void (**)())gen_ptr = fp_div_to_fp0;   break;
  342.             case 0x22: *(void (**)())gen_ptr = fp_add_to_fp0;   break;
  343.             case 0x23: *(void (**)())gen_ptr = fp_mul_to_fp0;   break;
  344.             case 0x28: *(void (**)())gen_ptr = fp_sub_to_fp0;   break;
  345.             case 0x38: *(void (**)())gen_ptr = fp_cmp_to_fp0;   break;
  346.             default:   goto error;
  347.           }
  348.         else
  349.           switch (op)
  350.           { case 0x01: *(void (**)())gen_ptr = fp_int_from_fp0;   break;
  351.             case 0x03: *(void (**)())gen_ptr = fp_intrz_from_fp0; break;
  352.             case 0x04: *(void (**)())gen_ptr = fp_sqrt_from_fp0;  break;
  353.             case 0x0a: *(void (**)())gen_ptr = fp_atan_from_fp0;  break;
  354.             case 0x0c: *(void (**)())gen_ptr = fp_asin_from_fp0;  break;
  355.             case 0x0e: *(void (**)())gen_ptr = fp_sin_from_fp0;   break;
  356.             case 0x0f: *(void (**)())gen_ptr = fp_tan_from_fp0;   break;
  357.             case 0x10: *(void (**)())gen_ptr = fp_etox_from_fp0;  break;
  358.             case 0x14: *(void (**)())gen_ptr = fp_logn_from_fp0;  break;
  359.             case 0x18: *(void (**)())gen_ptr = fp_abs_from_fp0;   break;
  360.             case 0x1c: *(void (**)())gen_ptr = fp_acos_from_fp0;  break;
  361.             case 0x1d: *(void (**)())gen_ptr = fp_cos_from_fp0;   break;
  362.             case 0x20: *(void (**)())gen_ptr = fp_div_from_fp0;   break;
  363.             case 0x22: *(void (**)())gen_ptr = fp_add_from_fp0;   break;
  364.             case 0x23: *(void (**)())gen_ptr = fp_mul_from_fp0;   break;
  365.             case 0x28: *(void (**)())gen_ptr = fp_sub_from_fp0;   break;
  366.             case 0x38: *(void (**)())gen_ptr = fp_cmp_from_fp0;   break;
  367.             default:   goto error;
  368.           }
  369.         gen_ptr += 2;
  370.         *gen_ptr++ = JSRA6_DISP_OP;
  371.         *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  372.       }
  373.       break;
  374.     }
  375.     case 0xf280: /* floating point conditional branch */
  376.     { long disp = ((long)code_ptr[1])-2;
  377.       *gen_ptr++ = MOVE_L_IMM_A5_DISP_OP;
  378.       *gen_ptr++ = (disp >> 16) & 0xffff;
  379.       *gen_ptr++ = disp & 0xffff;
  380.       *gen_ptr++ = pstate_offset( &pstate->temp[0] );
  381.       *gen_ptr++ = MOVE_L_IMM_PDECA7_OP;
  382.       switch (code_ptr[0] & 0x003f)
  383.       { case 0x01: *(void (**)())gen_ptr = fp_beq; break;
  384.         case 0x0e: *(void (**)())gen_ptr = fp_bne; break;
  385.         case 0x14: *(void (**)())gen_ptr = fp_blt; break;
  386.         case 0x12: *(void (**)())gen_ptr = fp_bgt; break;
  387.         case 0x15: *(void (**)())gen_ptr = fp_ble; break;
  388.         case 0x13: *(void (**)())gen_ptr = fp_bge; break;
  389.         default:   goto error;
  390.       }
  391.       gen_ptr += 2;
  392.       *gen_ptr++ = JSRA6_DISP_OP;
  393.       *gen_ptr++ = table_offset( &sstate->traps[C_TRAP_trap].jmp );
  394.       break;
  395.     }
  396.     default:
  397.       goto error;
  398.   }
  399.   *gen_ptr++ = MOVE_L_A5_DISP_PDECA7_OP;
  400.   *gen_ptr++ = pstate_offset( &pstate->temp[3] );
  401.   *gen_ptr++ = RTS_OP;
  402.   p1 = (short *)pstate->emul_code_bot;
  403.   while (p1 < (short *)emul_code_alloc)
  404.   { p2 = p1;
  405.     p3 = gen;
  406.     while ((p3 < gen_ptr) && (*p2 == *p3)) { p2++; p3++; }
  407.     if (p3 == gen_ptr)
  408.     { *code_ptr++ = JSRA5_DISP_OP;
  409.       *code_ptr++ = pstate_offset( p1 );
  410.       while (code_len > 2) { *code_ptr++ = NOP_OP; code_len--; }
  411.       return 0;
  412.     }
  413.     p1++;
  414.   }
  415.   if (emul_code_alloc+(gen_ptr-gen)*sizeof(short) > emul_code_top)
  416.   { os_err = "Emulation code memory overflow"; return 1; }
  417.   *code_ptr++ = JSRA5_DISP_OP;
  418.   *code_ptr++ = pstate_offset( emul_code_alloc );
  419.   while (code_len > 2) { *code_ptr++ = NOP_OP; code_len--; }
  420.   p1 = gen;
  421.   while (p1 < gen_ptr)
  422.   { *(short *)emul_code_alloc = *p1++;
  423.     emul_code_alloc += sizeof(short);
  424.   }
  425.   return 0;
  426.   error:
  427.   os_err = "Unknown M68881 instruction";
  428.   return 1;
  429. }
  430.  
  431. #endif
  432.  
  433. /*---------------------------------------------------------------------------*/
  434.