00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "real.h"
00029 #include "insn-config.h"
00030 #include "conditions.h"
00031 #include "function.h"
00032 #include "output.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "recog.h"
00036 #include "tree.h"
00037 #include "expr.h"
00038 #include "toplev.h"
00039 #include "tm_p.h"
00040 #include "target.h"
00041 #include "target-def.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050 int current_first_parm_offset;
00051
00052
00053
00054
00055 static rtx find_addr_reg PARAMS ((rtx));
00056 static const char *singlemove_string PARAMS ((rtx *));
00057 static bool pdp11_assemble_integer PARAMS ((rtx, unsigned int, int));
00058 static void pdp11_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00059 static void pdp11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00060
00061
00062 #undef TARGET_ASM_BYTE_OP
00063 #define TARGET_ASM_BYTE_OP NULL
00064 #undef TARGET_ASM_ALIGNED_HI_OP
00065 #define TARGET_ASM_ALIGNED_HI_OP NULL
00066 #undef TARGET_ASM_ALIGNED_SI_OP
00067 #define TARGET_ASM_ALIGNED_SI_OP NULL
00068 #undef TARGET_ASM_INTEGER
00069 #define TARGET_ASM_INTEGER pdp11_assemble_integer
00070
00071 #undef TARGET_ASM_FUNCTION_PROLOGUE
00072 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
00073 #undef TARGET_ASM_FUNCTION_EPILOGUE
00074 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
00075
00076 #undef TARGET_ASM_OPEN_PAREN
00077 #define TARGET_ASM_OPEN_PAREN "["
00078 #undef TARGET_ASM_CLOSE_PAREN
00079 #define TARGET_ASM_CLOSE_PAREN "]"
00080
00081 struct gcc_target targetm = TARGET_INITIALIZER;
00082
00083
00084
00085 int
00086 arith_operand (op, mode)
00087 rtx op;
00088 enum machine_mode mode;
00089 {
00090 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
00091 }
00092
00093 int
00094 const_immediate_operand (op, mode)
00095 rtx op;
00096 enum machine_mode mode ATTRIBUTE_UNUSED;
00097 {
00098 return (GET_CODE (op) == CONST_INT);
00099 }
00100
00101 int
00102 immediate15_operand (op, mode)
00103 rtx op;
00104 enum machine_mode mode ATTRIBUTE_UNUSED;
00105 {
00106 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
00107 }
00108
00109 int
00110 expand_shift_operand (op, mode)
00111 rtx op;
00112 enum machine_mode mode ATTRIBUTE_UNUSED;
00113 {
00114 return (GET_CODE (op) == CONST_INT
00115 && abs (INTVAL(op)) > 1
00116 && abs (INTVAL(op)) <= 4);
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 #ifdef TWO_BSD
00129
00130 static void
00131 pdp11_output_function_prologue (stream, size)
00132 FILE *stream;
00133 HOST_WIDE_INT size;
00134 {
00135 fprintf (stream, "\tjsr r5, csv\n");
00136 if (size)
00137 {
00138 fprintf (stream, "\t/*abuse empty parameter slot for locals!*/\n");
00139 if (size > 2)
00140 fprintf(stream, "\tsub $%d, sp\n", size - 2);
00141
00142 }
00143 }
00144
00145 #else
00146
00147 static void
00148 pdp11_output_function_prologue (stream, size)
00149 FILE *stream;
00150 HOST_WIDE_INT size;
00151 {
00152 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
00153 int regno;
00154 int via_ac = -1;
00155
00156 fprintf (stream,
00157 "\n\t; /* function prologue %s*/\n", current_function_name);
00158
00159
00160
00161 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
00162 {
00163 fprintf(stream,
00164 "\t;/* switch cpu to double float, single integer */\n");
00165 fprintf(stream, "\tsetd\n");
00166 fprintf(stream, "\tseti\n\n");
00167 }
00168
00169 if (frame_pointer_needed)
00170 {
00171 fprintf(stream, "\tmov fp, -(sp)\n");
00172 fprintf(stream, "\tmov sp, fp\n");
00173 }
00174 else
00175 {
00176
00177 }
00178
00179
00180 if (fsize)
00181 fprintf (stream, "\tsub $%o, sp\n", fsize);
00182
00183
00184 for (regno = 0; regno < 8; regno++)
00185 if (regs_ever_live[regno] && ! call_used_regs[regno])
00186 if (! ((regno == FRAME_POINTER_REGNUM)
00187 && frame_pointer_needed))
00188 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
00189
00190
00191
00192 via_ac = -1;
00193
00194 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
00195 {
00196
00197 if (LOAD_FPU_REG_P(regno)
00198 && regs_ever_live[regno]
00199 && ! call_used_regs[regno])
00200 {
00201 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
00202 via_ac = regno;
00203 }
00204
00205
00206
00207 if (NO_LOAD_FPU_REG_P(regno)
00208 && regs_ever_live[regno]
00209 && ! call_used_regs[regno])
00210 {
00211 if (via_ac == -1)
00212 abort();
00213
00214 fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
00215 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
00216 }
00217 }
00218
00219 fprintf (stream, "\t;/* end of prologue */\n\n");
00220 }
00221
00222 #endif
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 #ifdef TWO_BSD
00244
00245 static void
00246 pdp11_output_function_epilogue (stream, size)
00247 FILE *stream;
00248 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
00249 {
00250 fprintf (stream, "\t/* SP ignored by cret? */\n");
00251 fprintf (stream, "\tjmp cret\n");
00252 }
00253
00254 #else
00255
00256 static void
00257 pdp11_output_function_epilogue (stream, size)
00258 FILE *stream;
00259 HOST_WIDE_INT size;
00260 {
00261 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
00262 int i, j, k;
00263
00264 int via_ac;
00265
00266 fprintf (stream, "\n\t; /*function epilogue */\n");
00267
00268 if (frame_pointer_needed)
00269 {
00270
00271 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
00272
00273 for (i =7, j = 0 ; i >= 0 ; i--)
00274 if (regs_ever_live[i] && ! call_used_regs[i])
00275 j++;
00276
00277
00278 k = 2*j;
00279
00280 for (i =7 ; i >= 0 ; i--)
00281 if (regs_ever_live[i] && ! call_used_regs[i])
00282 fprintf(stream, "\tmov %o(fp), %s\n",-fsize-2*j--, reg_names[i]);
00283
00284
00285 via_ac = FIRST_PSEUDO_REGISTER -1;
00286
00287 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
00288 if (regs_ever_live[i] && ! call_used_regs[i])
00289 {
00290 via_ac = i;
00291 k += 8;
00292 }
00293
00294 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
00295 {
00296 if (LOAD_FPU_REG_P(i)
00297 && regs_ever_live[i]
00298 && ! call_used_regs[i])
00299 {
00300 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[i]);
00301 k -= 8;
00302 }
00303
00304 if (NO_LOAD_FPU_REG_P(i)
00305 && regs_ever_live[i]
00306 && ! call_used_regs[i])
00307 {
00308 if (! LOAD_FPU_REG_P(via_ac))
00309 abort();
00310
00311 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[via_ac]);
00312 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
00313 k -= 8;
00314 }
00315 }
00316
00317 fprintf(stream, "\tmov fp, sp\n");
00318 fprintf (stream, "\tmov (sp)+, fp\n");
00319 }
00320 else
00321 {
00322 via_ac = FIRST_PSEUDO_REGISTER -1;
00323
00324
00325 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
00326 if (regs_ever_live[i] && call_used_regs[i])
00327 via_ac = i;
00328
00329 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
00330 {
00331 if (LOAD_FPU_REG_P(i)
00332 && regs_ever_live[i]
00333 && ! call_used_regs[i])
00334 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
00335
00336 if (NO_LOAD_FPU_REG_P(i)
00337 && regs_ever_live[i]
00338 && ! call_used_regs[i])
00339 {
00340 if (! LOAD_FPU_REG_P(via_ac))
00341 abort();
00342
00343 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
00344 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
00345 }
00346 }
00347
00348 for (i=7; i >= 0; i--)
00349 if (regs_ever_live[i] && !call_used_regs[i])
00350 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
00351
00352 if (fsize)
00353 fprintf((stream), "\tadd $%o, sp\n", fsize);
00354 }
00355
00356 fprintf (stream, "\trts pc\n");
00357 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
00358 }
00359
00360 #endif
00361
00362
00363
00364 static const char *
00365 singlemove_string (operands)
00366 rtx *operands;
00367 {
00368 if (operands[1] != const0_rtx)
00369 return "mov %1,%0";
00370
00371 return "clr %0";
00372 }
00373
00374
00375
00376
00377
00378 const char *
00379 output_move_double (operands)
00380 rtx *operands;
00381 {
00382 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
00383 rtx latehalf[2];
00384 rtx addreg0 = 0, addreg1 = 0;
00385
00386
00387
00388 if (REG_P (operands[0]))
00389 optype0 = REGOP;
00390 else if (offsettable_memref_p (operands[0]))
00391 optype0 = OFFSOP;
00392 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
00393 optype0 = POPOP;
00394 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
00395 optype0 = PUSHOP;
00396 else if (GET_CODE (operands[0]) == MEM)
00397 optype0 = MEMOP;
00398 else
00399 optype0 = RNDOP;
00400
00401 if (REG_P (operands[1]))
00402 optype1 = REGOP;
00403 else if (CONSTANT_P (operands[1]))
00404 #if 0
00405 || GET_CODE (operands[1]) == CONST_DOUBLE)
00406 #endif
00407 optype1 = CNSTOP;
00408 else if (offsettable_memref_p (operands[1]))
00409 optype1 = OFFSOP;
00410 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
00411 optype1 = POPOP;
00412 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
00413 optype1 = PUSHOP;
00414 else if (GET_CODE (operands[1]) == MEM)
00415 optype1 = MEMOP;
00416 else
00417 optype1 = RNDOP;
00418
00419
00420
00421
00422
00423 if (optype0 == RNDOP || optype1 == RNDOP)
00424 abort ();
00425
00426
00427
00428
00429
00430 if (optype0 == PUSHOP && optype1 == POPOP)
00431 {
00432 operands[0] = XEXP (XEXP (operands[0], 0), 0);
00433 output_asm_insn ("sub $4,%0", operands);
00434 operands[0] = gen_rtx_MEM (SImode, operands[0]);
00435 optype0 = OFFSOP;
00436 }
00437 if (optype0 == POPOP && optype1 == PUSHOP)
00438 {
00439 operands[1] = XEXP (XEXP (operands[1], 0), 0);
00440 output_asm_insn ("sub $4,%1", operands);
00441 operands[1] = gen_rtx_MEM (SImode, operands[1]);
00442 optype1 = OFFSOP;
00443 }
00444
00445
00446
00447
00448 if (optype0 == MEMOP)
00449 addreg0 = find_addr_reg (XEXP (operands[0], 0));
00450
00451 if (optype1 == MEMOP)
00452 addreg1 = find_addr_reg (XEXP (operands[1], 0));
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 if (optype0 == REGOP)
00464 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
00465 else if (optype0 == OFFSOP)
00466 latehalf[0] = adjust_address (operands[0], HImode, 2);
00467 else
00468 latehalf[0] = operands[0];
00469
00470 if (optype1 == REGOP)
00471 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
00472 else if (optype1 == OFFSOP)
00473 latehalf[1] = adjust_address (operands[1], HImode, 2);
00474 else if (optype1 == CNSTOP)
00475 {
00476 if (CONSTANT_P (operands[1]))
00477 {
00478
00479
00480
00481 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
00482 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
00483 }
00484 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
00485 {
00486
00487 abort();
00488 }
00489 }
00490 else
00491 latehalf[1] = operands[1];
00492
00493
00494
00495
00496 if (optype0 == PUSHOP
00497 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
00498 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
00499 operands[1] = latehalf[1];
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 if (optype0 == PUSHOP || optype1 == PUSHOP
00510 || (optype0 == REGOP && optype1 == REGOP
00511 && REGNO (operands[0]) == REGNO (latehalf[1])))
00512 {
00513
00514 if (addreg0)
00515 output_asm_insn ("add $2,%0", &addreg0);
00516 if (addreg1)
00517 output_asm_insn ("add $2,%0", &addreg1);
00518
00519
00520 output_asm_insn (singlemove_string (latehalf), latehalf);
00521
00522
00523 if (addreg0)
00524 output_asm_insn ("sub $2,%0", &addreg0);
00525 if (addreg1)
00526 output_asm_insn ("sub $2,%0", &addreg1);
00527
00528
00529 return singlemove_string (operands);
00530 }
00531
00532
00533
00534 output_asm_insn (singlemove_string (operands), operands);
00535
00536
00537 if (addreg0)
00538 output_asm_insn ("add $2,%0", &addreg0);
00539 if (addreg1)
00540 output_asm_insn ("add $2,%0", &addreg1);
00541
00542
00543 output_asm_insn (singlemove_string (latehalf), latehalf);
00544
00545
00546 if (addreg0)
00547 output_asm_insn ("sub $2,%0", &addreg0);
00548 if (addreg1)
00549 output_asm_insn ("sub $2,%0", &addreg1);
00550
00551 return "";
00552 }
00553
00554
00555
00556 const char *
00557 output_move_quad (operands)
00558 rtx *operands;
00559 {
00560 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
00561 rtx latehalf[2];
00562 rtx addreg0 = 0, addreg1 = 0;
00563
00564 output_asm_insn(";; movdi/df: %1 -> %0", operands);
00565
00566 if (REG_P (operands[0]))
00567 optype0 = REGOP;
00568 else if (offsettable_memref_p (operands[0]))
00569 optype0 = OFFSOP;
00570 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
00571 optype0 = POPOP;
00572 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
00573 optype0 = PUSHOP;
00574 else if (GET_CODE (operands[0]) == MEM)
00575 optype0 = MEMOP;
00576 else
00577 optype0 = RNDOP;
00578
00579 if (REG_P (operands[1]))
00580 optype1 = REGOP;
00581 else if (CONSTANT_P (operands[1])
00582 || GET_CODE (operands[1]) == CONST_DOUBLE)
00583 optype1 = CNSTOP;
00584 else if (offsettable_memref_p (operands[1]))
00585 optype1 = OFFSOP;
00586 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
00587 optype1 = POPOP;
00588 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
00589 optype1 = PUSHOP;
00590 else if (GET_CODE (operands[1]) == MEM)
00591 optype1 = MEMOP;
00592 else
00593 optype1 = RNDOP;
00594
00595
00596
00597
00598
00599 if (optype0 == RNDOP || optype1 == RNDOP)
00600 abort ();
00601
00602
00603 if (optype0 == REGOP && optype1 == REGOP)
00604
00605 if (CPU_REG_P(REGNO(operands[0]))
00606 || CPU_REG_P (REGNO(operands[1])))
00607 abort();
00608
00609 if (optype0 == REGOP || optype1 == REGOP)
00610 {
00611
00612
00613
00614
00615
00616
00617
00618
00619 if (FPU_REG_P(REGNO(operands[0])))
00620 {
00621 if (GET_CODE(operands[1]) == CONST_DOUBLE)
00622 {
00623 union { double d; int i[2]; } u;
00624 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
00625 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
00626
00627 if (u.d == 0.0)
00628 return "{clrd|clrf} %0";
00629 }
00630
00631 return "{ldd|movf} %1, %0";
00632 }
00633
00634 if (FPU_REG_P(REGNO(operands[1])))
00635 return "{std|movf} %1, %0";
00636 }
00637
00638
00639
00640
00641
00642 if (optype0 == PUSHOP && optype1 == POPOP)
00643 {
00644 operands[0] = XEXP (XEXP (operands[0], 0), 0);
00645 output_asm_insn ("sub $8,%0", operands);
00646 operands[0] = gen_rtx_MEM (DImode, operands[0]);
00647 optype0 = OFFSOP;
00648 }
00649 if (optype0 == POPOP && optype1 == PUSHOP)
00650 {
00651 operands[1] = XEXP (XEXP (operands[1], 0), 0);
00652 output_asm_insn ("sub $8,%1", operands);
00653 operands[1] = gen_rtx_MEM (SImode, operands[1]);
00654 optype1 = OFFSOP;
00655 }
00656
00657
00658
00659
00660 if (optype0 == MEMOP)
00661 addreg0 = find_addr_reg (XEXP (operands[0], 0));
00662
00663 if (optype1 == MEMOP)
00664 addreg1 = find_addr_reg (XEXP (operands[1], 0));
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675 if (optype0 == REGOP)
00676 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
00677 else if (optype0 == OFFSOP)
00678 latehalf[0] = adjust_address (operands[0], SImode, 4);
00679 else
00680 latehalf[0] = operands[0];
00681
00682 if (optype1 == REGOP)
00683 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
00684 else if (optype1 == OFFSOP)
00685 latehalf[1] = adjust_address (operands[1], SImode, 4);
00686 else if (optype1 == CNSTOP)
00687 {
00688 if (GET_CODE (operands[1]) == CONST_DOUBLE)
00689 {
00690
00691
00692
00693
00694
00695
00696
00697 abort();
00698
00699 #ifndef HOST_WORDS_BIG_ENDIAN
00700 latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
00701 operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
00702 #else
00703 latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
00704 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
00705 #endif
00706 }
00707 else if (GET_CODE(operands[1]) == CONST_INT)
00708 {
00709 latehalf[1] = GEN_INT (0);
00710 }
00711 else
00712 abort();
00713 }
00714 else
00715 latehalf[1] = operands[1];
00716
00717
00718
00719
00720 if (optype0 == PUSHOP
00721 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
00722 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
00723 operands[1] = latehalf[1];
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 if (optype0 == PUSHOP || optype1 == PUSHOP
00734 || (optype0 == REGOP && optype1 == REGOP
00735 && REGNO (operands[0]) == REGNO (latehalf[1])))
00736 {
00737
00738 if (addreg0)
00739 output_asm_insn ("add $4,%0", &addreg0);
00740 if (addreg1)
00741 output_asm_insn ("add $4,%0", &addreg1);
00742
00743
00744 output_asm_insn(output_move_double(latehalf), latehalf);
00745
00746
00747 if (addreg0)
00748 output_asm_insn ("sub $4,%0", &addreg0);
00749 if (addreg1)
00750 output_asm_insn ("sub $4,%0", &addreg1);
00751
00752
00753 return output_move_double (operands);
00754 }
00755
00756
00757
00758 output_asm_insn (output_move_double (operands), operands);
00759
00760
00761 if (addreg0)
00762 output_asm_insn ("add $4,%0", &addreg0);
00763 if (addreg1)
00764 output_asm_insn ("add $4,%0", &addreg1);
00765
00766
00767 output_asm_insn (output_move_double (latehalf), latehalf);
00768
00769
00770 if (addreg0)
00771 output_asm_insn ("sub $4,%0", &addreg0);
00772 if (addreg1)
00773 output_asm_insn ("sub $4,%0", &addreg1);
00774
00775 return "";
00776 }
00777
00778
00779
00780
00781
00782 static rtx
00783 find_addr_reg (addr)
00784 rtx addr;
00785 {
00786 while (GET_CODE (addr) == PLUS)
00787 {
00788 if (GET_CODE (XEXP (addr, 0)) == REG)
00789 addr = XEXP (addr, 0);
00790 if (GET_CODE (XEXP (addr, 1)) == REG)
00791 addr = XEXP (addr, 1);
00792 if (CONSTANT_P (XEXP (addr, 0)))
00793 addr = XEXP (addr, 1);
00794 if (CONSTANT_P (XEXP (addr, 1)))
00795 addr = XEXP (addr, 0);
00796 }
00797 if (GET_CODE (addr) == REG)
00798 return addr;
00799 return 0;
00800 }
00801
00802
00803 void
00804 output_ascii (file, p, size)
00805 FILE *file;
00806 const char *p;
00807 int size;
00808 {
00809 int i;
00810
00811
00812
00813 fprintf (file, "\t.byte ");
00814
00815 for (i = 0; i < size; i++)
00816 {
00817 register int c = p[i];
00818 if (c < 0)
00819 c += 256;
00820 fprintf (file, "%o", c);
00821 if (i < size - 1)
00822 putc (',', file);
00823 }
00824 putc ('\n', file);
00825 }
00826
00827
00828
00829
00830 void
00831 print_operand_address (file, addr)
00832 FILE *file;
00833 register rtx addr;
00834 {
00835 register rtx reg1, reg2, breg, ireg;
00836 rtx offset;
00837
00838 retry:
00839
00840 switch (GET_CODE (addr))
00841 {
00842 case MEM:
00843 if (TARGET_UNIX_ASM)
00844 fprintf (file, "*");
00845 else
00846 fprintf (file, "@");
00847 addr = XEXP (addr, 0);
00848 goto retry;
00849
00850 case REG:
00851 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
00852 break;
00853
00854 case PRE_DEC:
00855 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
00856 break;
00857
00858 case POST_INC:
00859 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
00860 break;
00861
00862 case PLUS:
00863 reg1 = 0; reg2 = 0;
00864 ireg = 0; breg = 0;
00865 offset = 0;
00866 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
00867 || GET_CODE (XEXP (addr, 0)) == MEM)
00868 {
00869 offset = XEXP (addr, 0);
00870 addr = XEXP (addr, 1);
00871 }
00872 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
00873 || GET_CODE (XEXP (addr, 1)) == MEM)
00874 {
00875 offset = XEXP (addr, 1);
00876 addr = XEXP (addr, 0);
00877 }
00878 if (GET_CODE (addr) != PLUS)
00879 ;
00880 else if (GET_CODE (XEXP (addr, 0)) == MULT)
00881 {
00882 reg1 = XEXP (addr, 0);
00883 addr = XEXP (addr, 1);
00884 }
00885 else if (GET_CODE (XEXP (addr, 1)) == MULT)
00886 {
00887 reg1 = XEXP (addr, 1);
00888 addr = XEXP (addr, 0);
00889 }
00890 else if (GET_CODE (XEXP (addr, 0)) == REG)
00891 {
00892 reg1 = XEXP (addr, 0);
00893 addr = XEXP (addr, 1);
00894 }
00895 else if (GET_CODE (XEXP (addr, 1)) == REG)
00896 {
00897 reg1 = XEXP (addr, 1);
00898 addr = XEXP (addr, 0);
00899 }
00900 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
00901 {
00902 if (reg1 == 0)
00903 reg1 = addr;
00904 else
00905 reg2 = addr;
00906 addr = 0;
00907 }
00908 if (offset != 0)
00909 {
00910 if (addr != 0) abort ();
00911 addr = offset;
00912 }
00913 if (reg1 != 0 && GET_CODE (reg1) == MULT)
00914 {
00915 breg = reg2;
00916 ireg = reg1;
00917 }
00918 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
00919 {
00920 breg = reg1;
00921 ireg = reg2;
00922 }
00923 else if (reg2 != 0 || GET_CODE (addr) == MEM)
00924 {
00925 breg = reg2;
00926 ireg = reg1;
00927 }
00928 else
00929 {
00930 breg = reg1;
00931 ireg = reg2;
00932 }
00933 if (addr != 0)
00934 output_address (addr);
00935 if (breg != 0)
00936 {
00937 if (GET_CODE (breg) != REG)
00938 abort ();
00939 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
00940 }
00941 if (ireg != 0)
00942 {
00943 if (GET_CODE (ireg) == MULT)
00944 ireg = XEXP (ireg, 0);
00945 if (GET_CODE (ireg) != REG)
00946 abort ();
00947 abort();
00948 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
00949 }
00950 break;
00951
00952 default:
00953 output_addr_const_pdp11 (file, addr);
00954 }
00955 }
00956
00957
00958
00959
00960 static bool
00961 pdp11_assemble_integer (x, size, aligned_p)
00962 rtx x;
00963 unsigned int size;
00964 int aligned_p;
00965 {
00966 if (aligned_p)
00967 switch (size)
00968 {
00969 case 1:
00970 fprintf (asm_out_file, "\t.byte\t");
00971 output_addr_const_pdp11 (asm_out_file, x);
00972 fprintf (asm_out_file, " /* char */\n");
00973 return true;
00974
00975 case 2:
00976 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
00977 output_addr_const_pdp11 (asm_out_file, x);
00978 fprintf (asm_out_file, " /* short */\n");
00979 return true;
00980 }
00981 return default_assemble_integer (x, size, aligned_p);
00982 }
00983
00984
00985
00986
00987 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
00988 {
00989
00990
00991 { 0, 0, 0, 0, 0, 0, 0},
00992 { 0, 2, 2, 10, 22, 22, 22},
00993 { 0, 2, 2, 10, 22, 22, 22},
00994 { 0, 10, 10, 2, 2, 2, 10},
00995 { 0, 22, 22, 2, 2, 2, 22},
00996 { 0, 22, 22, 2, 2, 2, 22},
00997 { 0, 22, 22, 10, 22, 22, 22}
00998 } ;
00999
01000
01001
01002
01003
01004
01005
01006 int
01007 register_move_cost(c1, c2)
01008 enum reg_class c1, c2;
01009 {
01010 return move_costs[(int)c1][(int)c2];
01011 }
01012
01013 const char *
01014 output_jump(pos, neg, length)
01015 const char *pos, *neg;
01016 int length;
01017 {
01018 static int x = 0;
01019
01020 static char buf[1000];
01021
01022 #if 0
01023
01024
01025
01026
01027
01028 if (cc_status.flags & CC_IN_FPU)
01029 output_asm_insn("cfcc", NULL);
01030 #endif
01031
01032 switch (length)
01033 {
01034 case 1:
01035
01036 strcpy(buf, pos);
01037 strcat(buf, " %l0");
01038
01039 return buf;
01040
01041 case 3:
01042
01043 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
01044
01045 x++;
01046
01047 return buf;
01048
01049 default:
01050
01051 abort();
01052 }
01053
01054 }
01055
01056 void
01057 notice_update_cc_on_set(exp, insn)
01058 rtx exp;
01059 rtx insn ATTRIBUTE_UNUSED;
01060 {
01061 if (GET_CODE (SET_DEST (exp)) == CC0)
01062 {
01063 cc_status.flags = 0;
01064 cc_status.value1 = SET_DEST (exp);
01065 cc_status.value2 = SET_SRC (exp);
01066
01067
01068
01069
01070
01071 }
01072 else if ((GET_CODE (SET_DEST (exp)) == REG
01073 || GET_CODE (SET_DEST (exp)) == MEM)
01074 && GET_CODE (SET_SRC (exp)) != PC
01075 && (GET_MODE (SET_DEST(exp)) == HImode
01076 || GET_MODE (SET_DEST(exp)) == QImode)
01077 && (GET_CODE (SET_SRC(exp)) == PLUS
01078 || GET_CODE (SET_SRC(exp)) == MINUS
01079 || GET_CODE (SET_SRC(exp)) == AND
01080 || GET_CODE (SET_SRC(exp)) == IOR
01081 || GET_CODE (SET_SRC(exp)) == XOR
01082 || GET_CODE (SET_SRC(exp)) == NOT
01083 || GET_CODE (SET_SRC(exp)) == NEG
01084 || GET_CODE (SET_SRC(exp)) == REG
01085 || GET_CODE (SET_SRC(exp)) == MEM))
01086 {
01087 cc_status.flags = 0;
01088 cc_status.value1 = SET_SRC (exp);
01089 cc_status.value2 = SET_DEST (exp);
01090
01091 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
01092 && cc_status.value2
01093 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
01094 cc_status.value2 = 0;
01095 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
01096 && cc_status.value2
01097 && GET_CODE (cc_status.value2) == MEM)
01098 cc_status.value2 = 0;
01099 }
01100 else if (GET_CODE (SET_SRC (exp)) == CALL)
01101 {
01102 CC_STATUS_INIT;
01103 }
01104 else if (GET_CODE (SET_DEST (exp)) == REG)
01105
01106 {
01107 if ((cc_status.value1
01108 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
01109 cc_status.value1 = 0;
01110 if ((cc_status.value2
01111 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
01112 cc_status.value2 = 0;
01113 }
01114 else if (SET_DEST(exp) == pc_rtx)
01115 {
01116
01117 }
01118 else
01119 {
01120
01121
01122
01123 CC_STATUS_INIT;
01124 }
01125 }
01126
01127
01128 int
01129 simple_memory_operand(op, mode)
01130 rtx op;
01131 enum machine_mode mode ATTRIBUTE_UNUSED;
01132 {
01133 rtx addr;
01134
01135
01136 if (GET_CODE (op) != MEM)
01137 return FALSE;
01138
01139 #if 0
01140
01141 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
01142 return FALSE;
01143 #endif
01144
01145
01146
01147 indirection:
01148
01149 addr = XEXP (op, 0);
01150
01151 switch (GET_CODE (addr))
01152 {
01153 case REG:
01154
01155 return 1;
01156
01157 case PRE_DEC:
01158 case POST_INC:
01159
01160 return 0;
01161
01162 case MEM:
01163
01164
01165
01166
01167 if (GET_CODE (XEXP (addr, 0)) == REG)
01168 return 0;
01169
01170 op=addr;
01171 goto indirection;
01172
01173 case CONST_INT:
01174 case LABEL_REF:
01175 case CONST:
01176 case SYMBOL_REF:
01177
01178 return 0;
01179
01180 case PLUS:
01181
01182 return 0;
01183
01184 default:
01185 break;
01186 }
01187
01188 return FALSE;
01189 }
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 const char *
01204 output_block_move(operands)
01205 rtx *operands;
01206 {
01207 static int count = 0;
01208 char buf[200];
01209
01210 if (GET_CODE(operands[2]) == CONST_INT
01211 && ! optimize_size)
01212 {
01213 if (INTVAL(operands[2]) < 16
01214 && INTVAL(operands[3]) == 1)
01215 {
01216 register int i;
01217
01218 for (i = 1; i <= INTVAL(operands[2]); i++)
01219 output_asm_insn("movb (%1)+, (%0)+", operands);
01220
01221 return "";
01222 }
01223 else if (INTVAL(operands[2]) < 32)
01224 {
01225 register int i;
01226
01227 for (i = 1; i <= INTVAL(operands[2])/2; i++)
01228 output_asm_insn("mov (%1)+, (%0)+", operands);
01229
01230
01231
01232
01233
01234
01235
01236 return "";
01237 }
01238
01239
01240
01241 }
01242
01243 if (CONSTANT_P(operands[2]) )
01244 {
01245
01246 output_asm_insn("mov %2, %4", operands);
01247 }
01248 else
01249 {
01250
01251 operands[4] = operands[2];
01252 }
01253
01254
01255
01256 switch (INTVAL(operands[3]))
01257 {
01258 case 1:
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 sprintf(buf, "\nmovestrhi%d:", count);
01273 output_asm_insn(buf, NULL);
01274
01275 output_asm_insn("movb (%1)+, (%0)+", operands);
01276
01277 if (TARGET_45)
01278 {
01279 sprintf(buf, "sob %%4, movestrhi%d", count);
01280 output_asm_insn(buf, operands);
01281 }
01282 else
01283 {
01284 output_asm_insn("dec %4", operands);
01285
01286 sprintf(buf, "bgt movestrhi%d", count);
01287 output_asm_insn(buf, NULL);
01288 }
01289
01290 count ++;
01291 break;
01292
01293 case 2:
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 generate_compact_code:
01310
01311 output_asm_insn("asr %4", operands);
01312
01313 sprintf(buf, "\nmovestrhi%d:", count);
01314 output_asm_insn(buf, NULL);
01315
01316 output_asm_insn("mov (%1)+, (%0)+", operands);
01317
01318 if (TARGET_45)
01319 {
01320 sprintf(buf, "sob %%4, movestrhi%d", count);
01321 output_asm_insn(buf, operands);
01322 }
01323 else
01324 {
01325 output_asm_insn("dec %4", operands);
01326
01327 sprintf(buf, "bgt movestrhi%d", count);
01328 output_asm_insn(buf, NULL);
01329 }
01330
01331 count ++;
01332 break;
01333
01334 case 4:
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 if (optimize_size)
01354 goto generate_compact_code;
01355
01356 output_asm_insn("asr %4", operands);
01357 output_asm_insn("asr %4", operands);
01358
01359 sprintf(buf, "\nmovestrhi%d:", count);
01360 output_asm_insn(buf, NULL);
01361
01362 output_asm_insn("mov (%1)+, (%0)+", operands);
01363 output_asm_insn("mov (%1)+, (%0)+", operands);
01364
01365 if (TARGET_45)
01366 {
01367 sprintf(buf, "sob %%4, movestrhi%d", count);
01368 output_asm_insn(buf, operands);
01369 }
01370 else
01371 {
01372 output_asm_insn("dec %4", operands);
01373
01374 sprintf(buf, "bgt movestrhi%d", count);
01375 output_asm_insn(buf, NULL);
01376 }
01377
01378 count ++;
01379 break;
01380
01381 default:
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404 if (optimize_size)
01405 goto generate_compact_code;
01406
01407 output_asm_insn("asr %4", operands);
01408 output_asm_insn("asr %4", operands);
01409 output_asm_insn("asr %4", operands);
01410
01411 sprintf(buf, "\nmovestrhi%d:", count);
01412 output_asm_insn(buf, NULL);
01413
01414 output_asm_insn("mov (%1)+, (%0)+", operands);
01415 output_asm_insn("mov (%1)+, (%0)+", operands);
01416 output_asm_insn("mov (%1)+, (%0)+", operands);
01417 output_asm_insn("mov (%1)+, (%0)+", operands);
01418
01419 if (TARGET_45)
01420 {
01421 sprintf(buf, "sob %%4, movestrhi%d", count);
01422 output_asm_insn(buf, operands);
01423 }
01424 else
01425 {
01426 output_asm_insn("dec %4", operands);
01427
01428 sprintf(buf, "bgt movestrhi%d", count);
01429 output_asm_insn(buf, NULL);
01430 }
01431
01432 count ++;
01433 break;
01434
01435 ;
01436
01437 }
01438
01439 return "";
01440 }
01441
01442
01443 int
01444 comparison_operator_index(op)
01445 rtx op;
01446 {
01447 switch (GET_CODE(op))
01448 {
01449 case NE:
01450 return 0;
01451
01452 case EQ:
01453 return 1;
01454
01455 case GE:
01456 return 2;
01457
01458 case GT:
01459 return 3;
01460
01461 case LE:
01462 return 4;
01463
01464 case LT:
01465 return 5;
01466
01467 case GEU:
01468 return 6;
01469
01470 case GTU:
01471 return 7;
01472
01473 case LEU:
01474 return 8;
01475
01476 case LTU:
01477 return 9;
01478
01479 default:
01480 return -1;
01481 }
01482 }
01483
01484
01485 int
01486 comp_operator (op, mode)
01487 rtx op;
01488 enum machine_mode mode ATTRIBUTE_UNUSED;
01489 {
01490 return comparison_operator_index(op) >= 0;
01491 }
01492
01493
01494 int
01495 legitimate_address_p (mode, address)
01496 enum machine_mode mode;
01497 rtx address;
01498 {
01499
01500 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
01501
01502 return 0;
01503
01504 win:
01505 return 1;
01506
01507
01508 }
01509
01510
01511
01512
01513
01514
01515 void
01516 output_addr_const_pdp11 (file, x)
01517 FILE *file;
01518 rtx x;
01519 {
01520 char buf[256];
01521
01522 restart:
01523 switch (GET_CODE (x))
01524 {
01525 case PC:
01526 if (flag_pic)
01527 putc ('.', file);
01528 else
01529 abort ();
01530 break;
01531
01532 case SYMBOL_REF:
01533 assemble_name (file, XSTR (x, 0));
01534 break;
01535
01536 case LABEL_REF:
01537 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
01538 assemble_name (file, buf);
01539 break;
01540
01541 case CODE_LABEL:
01542 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
01543 assemble_name (file, buf);
01544 break;
01545
01546 case CONST_INT:
01547
01548
01549 fprintf (file, "%ho", (unsigned short) INTVAL (x));
01550 break;
01551
01552 case CONST:
01553
01554
01555 output_addr_const_pdp11 (file, XEXP (x, 0));
01556 break;
01557
01558 case CONST_DOUBLE:
01559 if (GET_MODE (x) == VOIDmode)
01560 {
01561
01562 if (CONST_DOUBLE_HIGH (x))
01563 abort ();
01564 else
01565 fprintf (file, "%ho", (unsigned short) CONST_DOUBLE_LOW (x));
01566 }
01567 else
01568
01569
01570 output_operand_lossage ("floating constant misused");
01571 break;
01572
01573 case PLUS:
01574
01575 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
01576 {
01577 output_addr_const_pdp11 (file, XEXP (x, 1));
01578 if (INTVAL (XEXP (x, 0)) >= 0)
01579 fprintf (file, "+");
01580 output_addr_const_pdp11 (file, XEXP (x, 0));
01581 }
01582 else
01583 {
01584 output_addr_const_pdp11 (file, XEXP (x, 0));
01585 if (INTVAL (XEXP (x, 1)) >= 0)
01586 fprintf (file, "+");
01587 output_addr_const_pdp11 (file, XEXP (x, 1));
01588 }
01589 break;
01590
01591 case MINUS:
01592
01593
01594 x = simplify_subtraction (x);
01595 if (GET_CODE (x) != MINUS)
01596 goto restart;
01597
01598 output_addr_const_pdp11 (file, XEXP (x, 0));
01599 fprintf (file, "-");
01600 if (GET_CODE (XEXP (x, 1)) == CONST_INT
01601 && INTVAL (XEXP (x, 1)) < 0)
01602 {
01603 fprintf (file, targetm.asm_out.open_paren);
01604 output_addr_const_pdp11 (file, XEXP (x, 1));
01605 fprintf (file, targetm.asm_out.close_paren);
01606 }
01607 else
01608 output_addr_const_pdp11 (file, XEXP (x, 1));
01609 break;
01610
01611 case ZERO_EXTEND:
01612 case SIGN_EXTEND:
01613 output_addr_const_pdp11 (file, XEXP (x, 0));
01614 break;
01615
01616 default:
01617 output_operand_lossage ("invalid expression as operand");
01618 }
01619 }