2011-11-14 17 views
8

Bất kỳ lập trình viên lắp ráp 68k nào tốt ngoài đó ?? Tôi đang sử dụng một trình biên dịch Green Hills thương mại cho một Motorola 68040 và tôi thấy một số hành vi rất lạ từ mã. Đôi khi, mã sẽ thực hiện so sánh if/else và lấy chi nhánh sai. Ví dụ:68040 Mất chi nhánh sai nếu người khác

float a = 1, b = 2; 

if (a < b) 
    do c; 
else 
    do d; 

Mã đôi khi sẽ d !? Tôi đã phát hiện ra rằng khi xảy ra lỗi này, luôn có một ISR cụ thể làm gián đoạn quá trình so sánh. Tôi đã nhìn vào hội đồng được tạo ra cho ISR và thấy một vài điều không hợp lý với tôi. Đầu tiên nó trông giống như các thanh ghi trạng thái dấu phẩy động, FPSR, FPCR và FPIAR, không được lưu trong ISR. Điều này sẽ giải thích tại sao if/elses đang dùng sai chi nhánh. Thanh ghi FPSR được sử dụng để xác định kết quả của phép so sánh, và nếu thanh ghi đó được ghi đè trong ISR thì nhánh có thể đi sai đường dẫn. Sau đây là xuất nhập cảnh lắp ráp tạo ra bởi trình biên dịch:

isr_function: 
    FSAVE -(%SP) 
    LINK %A6,#-192 
    MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP) 
    FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP) 

    ; isr code ... 

    FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7 
    MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1 
    UNLK %A6 
    FRESTORE (%SP)+ 
    RTE 

Tôi nhìn qua của Programmer Reference Manual và tôi không thể tìm thấy bất cứ điều gì gợi ý rằng FSAVE, hoặc FMOVEM, tiết kiệm dung thanh ghi trạng FP. Trên thực tế, tôi thấy một bình luận cho thấy rằng nó không, "FSAVE không lưu sổ đăng ký mô hình của lập trình viên của đơn vị dấu chấm động; nó chỉ tiết kiệm phần vô hình của người dùng của máy." Vì vậy, tôi đã thêm một số lắp ráp của riêng tôi để tiết kiệm đi đăng ký tại đầu của ISR, và khôi phục lại chúng ở cuối, và điều này cải thiện đáng kể hiệu suất, nhưng tôi vẫn thấy một số vấn đề. Sau đây là những bổ sung tôi đã thực hiện; các biến dự phòng được nhập là unsigned long trong mã C:

isr_function: 
    FSAVE -(%SP) 
    LINK %A6,#-192 
    MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP) 
    FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP) 

    FMOVE %FPIAR,fpiar_backup 
    FMOVE %FPSR,fpsr_backup 
    FMOVE %FPCR,fpcr_backup 

    ; isr code ... 

    FMOVE fpiar_backup,%FPIAR 
    FMOVE fpsr_backup,%FPSR 
    FMOVE fpcr_backup,%FPCR 

    FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7 
    MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1 
    UNLK %A6 
    FRESTORE (%SP)+ 
    RTE 

Tôi đã có một thời gian khó tin rằng trình biên dịch thực sự có lỗi do không lưu sổ đăng ký. Vì vậy, tôi bắt đầu xem xét các giá trị của FPx và Dx để thấy rằng chúng được khôi phục về giá trị thích hợp, và có vẻ như chúng không. Tuy nhiên tôi không phải là 100% mà tôi không làm xáo trộn mã lắp ráp với những sửa đổi của tôi. Sau đây là mã tôi đã thêm để lưu sổ đăng ký; các biến debug được gõ như chờ đợi unsigned:

isr_function: 
    FMOVE %FP0,debug3 
    FMOVE %FP1,debug5 
    FMOVE %FP2,debug7 
    FMOVE %FP3,debug9 
    FMOVE %FP4,debug11 
    FMOVE %FP5,debug13 
    FMOVE %FP6,debug15 
    FMOVE %FP7,debug17 
    FMOVE %FPCR,debug19 
    FMOVE %FPIAR,debug23 
    FMOVE %FPSR,debug25 

    FSAVE -(%SP) 
    LINK %A6,#-192 
    MOVEM.L %D0/%D1/%D2/%A0/%A1,-(%SP) 
    FMOVEM %FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7,-(%SP) 

    ; isr code ... 

    FMOVEM -308(%A6),%FP0/%FP1/%FP2/%FP3/%FP4/%FP5/%FP6/%FP7 
    MOVEM.L -212(%A6),%D0/%D1/%D2/%A0/%A1 
    UNLK %A6 

    FMOVE %FP0,debug4 
    FMOVE %FP1,debug6 
    FMOVE %FP2,debug8 
    FMOVE %FP3,debug10 
    FMOVE %FP4,debug12 
    FMOVE %FP5,debug14 
    FMOVE %FP6,debug16 
    FMOVE %FP7,debug18 
    FMOVE %FPCR,debug20 
    FMOVE %FPIAR,debug24 
    FMOVE %FPSR,debug26 

    FRESTORE (%SP)+ 
    RTE 

Nói tóm lại câu hỏi của tôi là,

1) là có một vấn đề với việc lắp ráp được tạo ra ở chỗ nó không lưu FPSR, FPCR, và thanh ghi FPIAR , và

2) Tôi có lưu đúng các giá trị của thanh ghi khi tôi nhập và thoát ISR không?

Sẽ tuyệt vời nếu tôi có trình biên dịch khác để so sánh. Rất tiếc, tôi không thể đính kèm trình gỡ lỗi vào mã. Tôi có nhiều kinh nghiệm trong C/C++/C#/Java/Python/PHP/v.v., nhưng tôi ở xa một chuyên gia lắp ráp.

Bất kỳ ý tưởng nào được đánh giá cao!

Trả lời

2

Tôi đã không làm lập trình 68K kể từ những ngày của 68.020 nhưng tôi sẽ cố gắng đạt thành các nguồn lực chất xám và/hoặc trang web có liên quan :-)

Trả lời câu hỏi cụ thể của bạn:

Có sự cố với lắp ráp được tạo ra ở chỗ nó không lưu các thanh ghi FPSR, FPCR và FPIAR không?

Tôi sẽ nói có, nhưng chỉ khi có điều gì đó trong ISR ảnh hưởng đến chúng.Mặc dù điều này có vẻ không khả thi (ISR được cho là nhanh nên tôi không mong đợi họ sẽ nhạo báng với các điểm nổi), thận trọng dường như gợi ý rằng một thói quen tiết kiệm mọi thứ chỉ trên cơ hội mã đó có thể thay đổi.

Có nói rằng, tôi không chắc chắn làm thế nào bạn đang biên dịch ISR (hoặc thậm chí cho dù đó là mã của bạn cả). Nó có thể là một lá cờ đặc biệt là cần thiết để có được trình biên dịch để tạo ra nhiều mã hơn để tiết kiệm những thứ khác.

Tôi có lưu đúng giá trị của thanh ghi khi tôi nhập và thoát ISR không?

Một lần nữa, điều này phụ thuộc. Có vẻ ổn nhưng tôi hơi lo lắng về việc sử dụng các vị trí bộ nhớ cụ thể như fpiar_backup hoặc debug26 trừ khi bạn đang rất chắc chắn rằng bản thân ISR không dễ bị gián đoạn khác.

Nếu ngắt được tắt trong quá trình xử lý ISR ​​thì có thể bạn đã ổn.

Ngoài ra, phụ thuộc vào ISR đang phục vụ. Các tài liệu dường như chỉ ra rằng bất kỳ ISR nào phục vụ các vấn đề về dấu phẩy động phải luôn luôn thực hiện trước tiên là fsave.

Sẽ rất hữu ích nếu bạn bỏ giá trị của những vị trí debugX để bạn có thể thấy giá trị nào khác nhau giữa mục nhập và thoát khỏi ISR. Và đảm bảo chúng đúng kích cỡ. Và hãy cẩn thận rằng bạn không nhìn vào chúng ở giữa ISR, nơi chúng gần như chắc chắn sẽ khác.

+0

Cảm ơn phản hồi! Tôi không thực sự quan tâm đến việc sử dụng các vị trí bộ nhớ cụ thể. "Tôi sẽ có một chút lo lắng về việc sử dụng các vị trí bộ nhớ cụ thể như fpiar_backup hoặc debug26 trừ khi bạn rất chắc chắn rằng bản thân ISR không dễ bị gián đoạn khác." Các biến đó chỉ được ghi vào trong một ISR đó. Tôi không thấy những tác động bất lợi nào có thể xảy ra. Tôi không chắc chắn về các ưu tiên ngắt, nhưng có thể cho một gián đoạn khác can thiệp. – Samuel

+0

@ user1045004: mối quan tâm của tôi là, nếu xảy ra gián đoạn khác trong khi ISR ​​đó đang chạy, nó có thể ghi đè lên các giá trị. Nó chỉ là một mối quan tâm nếu mã _same_ chạy như vậy, nếu gián đoạn khác là một _different_ một, đó sẽ là okay. – paxdiablo

2

Để tham khảo trong tương lai, sự cố thực sự liên quan đến trình biên dịch không lưu giá trị của thanh ghi trạng thái dấu phẩy động. Tôi liên lạc với Green Hills và theo họ đây không phải là lỗi, và việc tiết kiệm giá trị của sổ đăng ký là trách nhiệm của lập trình viên. Đó là kỳ lạ với tôi, bởi vì trình biên dịch lưu tất cả các thanh ghi bên trong khác, bao gồm trạng thái bên trong của FPU, tại sao dừng lại với thanh ghi trạng thái?

Tóm lại, lưu giá trị của FPSR và FPIAR vào, và khi rời khỏi ISR ​​sẽ khắc phục sự cố. Sau đây nên thực hiện thủ thuật:

void isr(void) 
{ 
    // variable declarations ... 

    __asm(" FMOVE %FPIAR,-(%SP)"); 
    __asm(" FMOVE %FPSR,-(%SP)"); 

    // some code ... 


    __asm(" FMOVE (%SP)+,%FPSR"); 
    __asm(" FMOVE (%SP)+,%FPIAR"); 
} 
+4

Đó là chính xác, nếu bạn viết một thói quen phục vụ gián đoạn, bạn cần phải chăm sóc để làm điều đó một mình một cách chính xác. Điều đó có nghĩa là tiết kiệm trạng thái máy, bao gồm cả thanh ghi trạng thái. Thông thường trình biên dịch không thể làm điều này - hầu hết các ngôn ngữ thiếu cấu trúc ngôn ngữ cần thiết cho các ngắt, nhưng một số có các thuộc tính hoặc phần mở rộng của hàm. – hirschhornsalz

+1

Tôi đã rất bối rối bởi thực tế là bạn có thể bị phạt một cách tinh tế như vậy chỉ để thêm một từ khóa nổi hoặc đôi.Tôi đã nói nhiều hơn với đại diện của Green Hills và tôi nghĩ anh ấy đã nhìn thấy mặt của tôi về câu chuyện, anh ta yêu cầu thêm tài liệu cho trường hợp này và thêm cờ trong trình biên dịch để đăng ký FP tự động lưu. – Samuel

Các vấn đề liên quan